Tuesday 30 October 2012

Custom CMS using HTTPHandlerFactory




This is a handy chunk of code I want to keep, it allows for the use of the HttpHandlerfactory to return pages that are content managed alongside physical pages.

namespace Web.Helpers {
public class HttpCMSHandlerFactory : IHttpHandlerFactory
{
public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
    string pageName = Path.GetFileNameWithoutExtension(context.Request.PhysicalPath);
    
    //on Server.Transfer the context is kept, so this just overrides the existing value.
    if (context.Items.Contains("PageName")) 
    {
        context.Items["PageName"] = pageName; } else { context.Items.Add("PageName", pageName); }
        FileInfo fi = new FileInfo(context.Request.MapPath(context.Request.CurrentExecutionFilePath)); 

        //if File is not physical 
        if (fi.Exists == false) 
        {
             //Check if is survey
             if (pageName.IndexOf("Survey", 0, StringComparison.InvariantCultureIgnoreCase) >= 0) 
            { return PageParser.GetCompiledPageInstance(url, context.Server.MapPath("~/Survey.aspx"), context); 
            } 
            else 
           {
            //return page to CMS handler the context containing "PageName" is passed on to this page, which then calls to the database to return the copy.
                return PageParser.GetCompiledPageInstance(url, context.Server.MapPath("~/CMSPage.aspx"),  context); 
            } 
        } 
        else 
        {
            // Returns real page.
            return PageParser.GetCompiledPageInstance(context.Request.CurrentExecutionFilePath, fi.FullName, context); 
        } 
    }
}

All that is then needed is to override the *.aspx handler on the iis site config (which should already be there for an asp.net sites) and also add the following to the web.config:
<httphandlers>
<add path="*.aspx" type="Web.Helpers.HttpCMSHandlerFactory, Web.helpers" verb="*"/>
</httphandlers>

Friday 26 October 2012

When Session times out before FormsAuthentication is dropped

Just wanted to keep this safe, there are probably better ways of doing this, but I often find that the FormsAuthentication object holds on to your login, after the session has cleared.

This often happens when I am testing a site and making changes, the site will drop it's session but the FormsAuthentication stays populated and logged in causing an error to be thrown until you logout and back into to repopulate the necessary session objects.

So in the OnInit event I add a simple check:
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        var current = Path.GetFileNameWithoutExtension(Request.PhysicalPath);
        if (current.StartsWith("Registration", StringComparison.InvariantCultureIgnoreCase) && Session["Objectx"] == null)
        {
            Response.Redirect("SignIn.aspx");
        }
    }

The above only worries about pages with the word Registration in then page name.

For an entire site you need to be a bit different:
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        var current = Path.GetFileNameWithoutExtension(Request.PhysicalPath);
        if (!current.Equals("SignIn", StringComparison.InvariantCultureIgnoreCase) && Session["Objectx"] == null)
        {
            Response.Redirect("SignIn.aspx");
        }
    }