Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>If anyone else is having this issue. I did solve it. Here is my complete code :) First, create our RouteHandler</p> <pre><code>public class CmsRouteHandler : IRouteHandler { public IHttpHandler GetHttpHandler(RequestContext requestContext) { return new CmsHandler(requestContext); // Return the requestContext and handle as normal } } </code></pre> <p>Then we need to create our MvcHanlder</p> <pre><code>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&lt;IPage&gt; pages = vpp.pages; // Get all the published pages for this company // If we have pages if (pages != null) { IPage oPage = pages.SingleOrDefault(page =&gt; 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); } } </code></pre> <p>You can see in my application I have a companyId that is because I am using subdomains for multiple companies, but in a normal case that would not be needed.</p> <p>And the full VirtualPathProvider looks like this:</p> <pre><code>public class CmsVirtualPathProvider : VirtualPathProvider { public Collection&lt;IPage&gt; 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 =&gt; 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; } } </code></pre> <p>Now you just need a controller to handle all the page requests. Mine looks like this:</p> <pre><code>public class _CmsController : Controller { private Collection&lt;IPage&gt; 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 =&gt; 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 &amp;&amp; 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 =&gt; 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 } } </code></pre> <p>And just because I am feeling nice, here is my table structure</p> <pre><code>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 </code></pre> <p>obviously again, you don't need the companyId :) Here is a peek at the data contained inside the table</p> <p><img src="https://i.stack.imgur.com/PbfvC.png" alt="enter image description here"></p> <p>I transformed the html for a page into bytes using this line of code:</p> <pre><code>ASCIIEncoding encoding = new ASCIIEncoding(); var decodedContent = HttpUtility.UrlDecode(Content, Encoding.Default); Byte[] bytes = encoding.GetBytes(decodedContent); </code></pre> <p>you only need the UrlDecode if you are escaping your HTML before submitting it to your save function. If you are not then you can just use:</p> <pre><code>ASCIIEncoding encoding = new ASCIIEncoding(); Byte[] bytes = encoding.GetBytes(Content); </code></pre> <p>I really hope this helps someone out. I was in a right mess trying to work this out :)</p> <p>cheers, r3plica</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload