我正在尝试使用MVC框架创建CMS。 一切顺利,我创建了我的表来存储我的ViewData,ViewTitle和virtualPath。 我使用VirthPathProvider,它看起来像这样:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Hosting;
using CMS;
using System.Collections.ObjectModel;
using CMS.Components;
using System.Web;
namespace CMS.Providers
{
public class PageVirtualPathProvider : VirtualPathProvider
{
private Directory current { get; set; }
private Collection<Directory> directories { get; set; }
private Collection<BasePage> pages { get; set; }
public override bool FileExists(string virtualPath)
{
string Path = (VirtualPathUtility.GetDirectory(virtualPath) != "~/") ? VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(virtualPath)) : VirtualPathUtility.GetDirectory(virtualPath);
if (IsVirtualPath(Path))
{
BasePage oPage = FindPage(virtualPath);
if (oPage != null)
return true;
}
bool bExists = base.FileExists(virtualPath);
return bExists;
}
public override VirtualFile GetFile(string virtualPath)
{
string Path = (VirtualPathUtility.GetDirectory(virtualPath) != "~/") ? VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(virtualPath)) : VirtualPathUtility.GetDirectory(virtualPath);
if (IsVirtualPath(Path))
{
BasePage oPage = FindPage(virtualPath);
if (oPage != null)
return new PageVirtualFile(virtualPath, oPage.ViewData.ToArray());
}
return base.GetFile(virtualPath);
}
public override bool DirectoryExists(string virtualDir)
{
if (IsVirtualPath(virtualDir))
{
if (current != null)
{
if (current.Path.ToLower() != virtualDir.ToLower())
current = new Directory(virtualDir, "53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
else
{
current = new Directory(virtualDir, "53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
if (current != null)
return true;
}
return base.DirectoryExists(virtualDir);
}
public override VirtualDirectory GetDirectory(string virtualDir)
{
if (IsVirtualPath(virtualDir))
{
if (current != null)
{
if (current.Path.ToLower() != virtualDir.ToLower())
current = new Directory(virtualDir, "53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
else
{
current = new Directory(virtualDir, "53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
if (current != null)
return new CmsVirtualDirectory(virtualDir, "53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
return base.GetDirectory(virtualDir);
}
public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
{
string Path = (VirtualPathUtility.GetDirectory(virtualPath) != "~/") ? VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(virtualPath)) : VirtualPathUtility.GetDirectory(virtualPath);
if (IsVirtualPath(Path))
return null;
return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
public override string GetFileHash(string virtualPath, System.Collections.IEnumerable virtualPathDependencies)
{
string Path = (VirtualPathUtility.GetDirectory(virtualPath) != "~/") ? VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(virtualPath)) : VirtualPathUtility.GetDirectory(virtualPath);
if (IsVirtualPath(Path))
return Guid.NewGuid().ToString();
return base.GetFileHash(virtualPath, virtualPathDependencies);
}
private BasePage FindPage(string virtualPath)
{
string VirtualName = VirtualPathUtility.GetFileName(virtualPath).ToLower();
if (pages == null)
{
pages = PageManager.getAllPages("53AF0033-4011-4C8F-A14D-7CE9301E264D", false);
}
BasePage oPage = pages.SingleOrDefault(page => page.Path.ToLower() == VirtualName);
return oPage;
}
private bool IsVirtualPath(string virtualPath)
{
string Path = VirtualPathUtility.ToAppRelative(virtualPath);
if (directories == null)
{
directories = DirectoryManager.GetAllDirectories("53AF0033-4011-4C8F-A14D-7CE9301E264D");
}
Directory oDir = directories.SingleOrDefault(dir => dir.Path.ToLower() == Path.ToLower());
if (oDir == null || virtualPath == "~/") return false; // If we don't have directory, return false
return true; // Hit only if we are null
}
}
}
现在我的问题是: 获取页面很好,当它们是虚拟的时候,它返回null作为Cache,而FileHash总是一个不同的字符串,因此调用GetFile。 我的文件被返回,但它永远找不到布局。
我相信这是因为没有_ViewStart.cshtml因为没有视图目录....所以如何强制它使用布局? 我尝试了很多东西,比如让我的虚拟页面继承自@inherits System.Web.Mvc.WebViewPage等,但我仍然遇到同样的问题....
当我导航到虚拟页面时,我收到此错误: 无法投射类型&#39; ASP._Page_Guidelines_index_cshtml&#39;输入&#39; System.Web.IHttpHandler&#39;。
请帮帮我;我已经坚持了3个星期....
答案 0 :(得分:4)
如果有其他人遇到此问题。我确实解决了。这是我的完整代码:) 首先,创建我们的RouteHandler
public class CmsRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new CmsHandler(requestContext); // Return the requestContext and handle as normal
}
}
然后我们需要创建我们的MvcHanlder
class CmsHandler : MvcHandler, IRequiresSessionState
{
public CmsHandler(RequestContext requestContext)
: base(requestContext)
{
}
protected override IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state)
{
return base.BeginProcessRequest(httpContext, callback, state);
}
protected override IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state)
{
try
{
// If we are using a company Url, then the session should not be null
if (CompanyProvider.CurrentCompanyId() != null)
{
var vpp = new CmsVirtualPathProvider(); // Create an instance of our VirtualPathProvider class
var requestContext = ((MvcHandler)httpContext.Handler).RequestContext; // Get our request context
string path = requestContext.HttpContext.Request.Url.AbsolutePath; // Get our requested path
// If we have a path
if (path != null)
{
Collection<IPage> pages = vpp.pages; // Get all the published pages for this company
// If we have pages
if (pages != null)
{
IPage oPage = pages.SingleOrDefault(page => page.Path.ToLower() == path.ToLower()); // Select the page matching our requested path (if any)
if (oPage != null) // If we find the page
{
requestContext.RouteData.Values["controller"] = "_Cms"; // Set the controller
requestContext.RouteData.Values["action"] = "Index"; // And the action
}
}
}
}
return base.BeginProcessRequest(httpContext, callback, state);
}
catch (Exception ex)
{
log4net.ILog _log = log4net.LogManager.GetLogger(this.GetType());
_log.Fatal(ex);
throw new Exception(ex.Message);
}
}
protected override void ProcessRequest(HttpContext httpContext)
{
base.ProcessRequest(httpContext);
}
}
您可以在我的应用程序中看到我有一个companyId,因为我正在为多家公司使用子域名,但在正常情况下不需要。
完整的VirtualPathProvider如下所示:
public class CmsVirtualPathProvider : VirtualPathProvider
{
public Collection<IPage> pages
{
get
{
if (HttpContext.Current.Session != null)
{
return PageProvider.GetPublishedPages(CompanyProvider.CurrentCompanyId(), true);
}
else
return null;
}
}
public override bool FileExists(string virtualPath)
{
if (IsVirtualPath(virtualPath))
{
if (FindPage(virtualPath) != null)
{
PageVirtualFile file = (PageVirtualFile)GetFile(virtualPath);
return file.Exists;
}
}
return Previous.FileExists(virtualPath);
}
public override VirtualFile GetFile(string virtualPath)
{
if (IsVirtualPath(virtualPath))
{
IPage oPage = FindPage(virtualPath);
if (oPage != null)
return new PageVirtualFile(virtualPath, oPage.ViewData);
}
return Previous.GetFile(virtualPath);
}
public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
{
if (IsVirtualPath(virtualPath))
return null;
return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
public override string GetFileHash(string virtualPath, System.Collections.IEnumerable virtualPathDependencies)
{
if (IsVirtualPath(virtualPath))
return Guid.NewGuid().ToString();
return Previous.GetFileHash(virtualPath, virtualPathDependencies);
}
private IPage FindPage(string virtualPath)
{
string VirtualName = VirtualPathUtility.GetFileName(virtualPath).ToLower();
if (pages != null)
{
IPage oPage = pages.SingleOrDefault(page => page.FileName == VirtualName);
return oPage;
}
else
return null;
}
private bool IsVirtualPath(string virtualPath)
{
string Path = (VirtualPathUtility.GetDirectory(virtualPath) != "~/") ? VirtualPathUtility.RemoveTrailingSlash(VirtualPathUtility.GetDirectory(virtualPath)) : VirtualPathUtility.GetDirectory(virtualPath);
if (Path.StartsWith("/Views/_Cms", StringComparison.InvariantCultureIgnoreCase))
return true;
else
return false;
}
}
现在您只需要一个控制器来处理所有页面请求。我看起来像这样:
public class _CmsController : Controller
{
private Collection<IPage> pages { get; set; }
public ActionResult Index()
{
string uri = Request.Url.AbsolutePath; // Get our Requested Url
string queryString = Request.Url.Query;
Profile currentUser = ProfileProvider.CurrentUser(); // Get our current user if we have one
if (pages == null) // If pages is null
pages = PageProvider.GetPublishedPages(CompanyProvider.CurrentCompanyId(), true); // Get our published pages
IPage page = pages.SingleOrDefault(p => p.Path.ToLower() == uri.ToLower()); // Get the current page
if (page == null) // If our page is null
throw new HttpException(404, "Are you sure this page exists?"); // Throw the 404 error
if (page.Restricted && currentUser == null) // If our page is restricted and we are not logged in
return Redirect("~/Account/LogOn?ReturnUrl=" + page.Path + queryString); // Redirect to the login page
if (currentUser != null)
{
IPage oForbidden = currentUser.GetForbiddenPages().SingleOrDefault(p => p.Id == page.Id); // Finds the page in our forbidden pages, if it exists
if (oForbidden != null) // If we find the forbidden page
throw new HttpException(401, "You do not have permission to view this page."); // Throw 401 error
AuditProvider.Create(currentUser, page, Event.View); // Create our audit trail if we get this far
}
return View(Path.GetFileNameWithoutExtension(page.Id.ToString())); // Show the page
}
}
只是因为我感觉很好,这是我的表结构
CREATE TABLE [dbo].[cms_Pages](
[Id] [int] IDENTITY(1,1) NOT NULL,
[DateCreated] [datetime] NOT NULL,
[UserId] [uniqueidentifier] NOT NULL,
[Author] [nvarchar](256) NOT NULL,
[DateModified] [datetime] NULL,
[ModifiedById] [uniqueidentifier] NULL,
[ModifiedBy] [nvarchar](256) NULL,
[CompanyId] [uniqueidentifier] NOT NULL,
[Name] [varchar](100) NOT NULL,
[Description] [text] NULL,
[FileName] [varchar](255) NULL,
[Path] [varchar](255) NULL,
[Link] [varchar](255) NULL,
[Published] [bit] NOT NULL,
[TypeId] [int] NOT NULL,
[Order] [int] NOT NULL,
[Lineage] [nvarchar](255) NOT NULL,
[ParentId] [int] NULL,
[ViewData] [varbinary](max) NULL,
[ViewTitle] [varchar](255) NULL,
[Restricted] [bit] NOT NULL,
CONSTRAINT [PK_cg_Pages] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
显然,你不需要companyId :) 这里是一个表格中包含的数据
我使用这行代码将页面的html转换为字节:
ASCIIEncoding encoding = new ASCIIEncoding();
var decodedContent = HttpUtility.UrlDecode(Content, Encoding.Default);
Byte[] bytes = encoding.GetBytes(decodedContent);
如果您在将HTML提交到保存功能之前转义HTML,则只需要UrlDecode。如果你不是那么你可以使用:
ASCIIEncoding encoding = new ASCIIEncoding();
Byte[] bytes = encoding.GetBytes(Content);
我真的希望这可以帮助别人。我正试图解决这个问题:)
欢呼声, r3plica