Want to follow this site? Here's the RSS feed.

Dynamically Configuring HTTP Handlers in Themelia

Monday, July 28, 2008

This documentation has been updated for Themelia Framework 2.0 Beta 4.

One of the things that expert ASP.NET developers often find themselves doing is carefully inserting processes at just the right place in the ASP.NET pipeline and page life cycle. It's incredibly important for developers to have a strong familiarity with the ASP.NET order of operations. If you do something too early, a control may not exist or session may not be initialized. If you do it too late, any data you set will be overwritten.

Fortunately, if you aren't familiar with these concepts, there are many resources available to us. For example, Rick Strahl has written "A low-level Look at the ASP.NET Architecture" to help developers understand the order of these operations. Furthermore, MSDN contains an overview of the page life cycle eggheadcafe.com has a very detailed reference image.  Then there's a PowerPoint presentation by the queen of all architecture everywhere, Michele Leroux Bustamante, entitled "Inside the ASP.NET Runtime - Intercepting HTTP Requests".  For those of us who are already well versed in the ASP.NET pipeline and page life cycle, these are great reference to which we can turn when we (by we I mean me) forget a thing or two after not doing any pipeline hacking for a while.

Themelia Order of Operations

Within the ASP.NET pipeline and the page life cycle, Themelia runs after all HTTP modules have run, but, because Themelia is the creator of the HTTP handler, before an HTTP handler has been created. This means that you are able to modify HTTP handler properties or even call HTTP handler method before the handler themselves ever run. Granted, the former situation makes more sense than the latter, but the option for method call does exist.

To understand how this is possible, you must first understand the various parts of Themelia as explained in previous posts.  You must also know the Themelia order of operations. Here is a quick run down of the order of operations within Themelia:

  • ConfigurationPreProcessor (loads configuration information)
  • DebugPreProcessor runs
  • WebDomainPreProcessor runs
  • DefaultPagePreProcessor runs
  • Web Components Load
  • PreProcessors run
  • Exit if PassThroughHttpHandler.ForceUse was set
  • Handler Factory Load
  • Injection Processor Load
  • MidProcessors run
  • If no handler was set yet, HTTP Handler Matching Happens; otherwise skip to post processing
  • If no handler is found, the fall through processor runs
  • If no handler is found, pass the request through to IIS
  • PostProcessors run
  • SessionPostPostProcessor runs
  • PostStateProcessors run
  • Continue ASP.NET Pipeline

Dynamically Configuring HTTP Handlers

As this information demonstrates, an HTTP handler will always be set by the time the post processors run. Therefore, if you create an HTTP handler containing properties, you may use a postprocessor to configure that handler.  By doing this, when the HTTP handler itself runs, it will have the information required for its own logic.

For instance, if you want to create an efficient Windows Workflow Foundation ("WF") sales reporting workflow activator, you could create a lightweight HTTP handler that did nothing but run that specific workflow. Using Themelia, you may then create a postprocessor designed to configure that specific HTTP handler. This configuration might be nothing more than setting a the workflow activity type.  The following snippet shows what we're talking about:

public class SalesStatisticsWorkflowPostProcessor : Themelia.Web.Routing.PostProcessorBase
{
    public override IHttpHandler OnPostProcessorExecute(HttpContext context, IHttpHandler activeHttpHandler, params Object[] parameterArray)
    {
        ReportingWorkflowHttpHandler handler = activeHttpHandler as ReportingWorkflowHttpHandler;
        if (handler != null)
        {
            handler.ReportWorkFlowActivity = "Sales.Workflow.StatisticsActivity, Sales.Workflow";
        }
        //+
        return handler;
    }
}

In this particular example, the HTTP handler is abstracted away from any workflow activity.  It's the post processor that provides this information.  Developers could extend this further by utilizing Themelia web components, creating prepacked processors per department for specific workflow activity sets. Or, if the developers really thought ahead, they could use some of Themelia's supporting helping features to determine what workflow HTTP handler to run based upon a REST-style URL. For example, take a look at the following Themelia postprocessor with its associated registration:

public class SalesWorkflowPostProcessor : Themelia.Web.Routing.PostProcessorBase
{
    public override IHttpHandler OnPostProcessorExecute(HttpContext context, IHttpHandler activeHttpHandler, params Object[] parameterArray)
    {
        ReportingWorkflowHttpHandler handler = activeHttpHandler as ReportingWorkflowHttpHandler;
        if (handler != null)
        {
            String pattern = "Sales.Workflow.{0}Activity, Sales.Workflow";
            if (Http.GetHttpPart(Http.Position.Antepenultima) == "report")
            {
                String reportName = Themelia.Case.GetPascalCase(Http.GetHttpPart(Http.Position.Ultima));
                handler.ReportWorkFlowActivity = String.Format(pattern, reportName);
                handler.Region = Http.GetHttpPart(Http.Position.Penultima);
            }
        }
        //+
        return handler;
    }
}

Here is the associated HTTP handler registration for ReportWorkflowHttpHandler (obviously, there would be a aliased handler factory used here, but that's not important for out discussion):

<add matchType="contains" name="ReportingWorkFlow" text="/report/" />

In this example, the postprocessor checks to see if the HTTP handler that is going to run is ReportingWorkFlowHttpHandler.  If so, the postprocessor checks to see if the third to the last part of the URL is "report". If this is the case, then the last part of the URL is set as the workflow activity name and the second to the last part of the URL is set as the workflow sales region. For example, "http://www.netfxharmonics.com/workflow/report/signapore/demographic/" would run the "Sales.Workflow.DemographicActivity, Sales.Workflow" while "http://www.netfxharmonics.com/workflow/report/kansascity/annual/" would run the "Sales.Workflow.AnnualActivity, Sales.Workflow". The custom workflow HTTP handler would also have the region information ready to send to WF.

There's one final concluding thought that I would like to mention in passing. Since Themelia provides the SessionPostStateProcessor which allow adding to session before session state is initialized, adding to ASP.NET session is essentially available at every point in Themelia. Therefore, you may feel free to utilize session in your processors as you see fit. In this example, perhaps you would like to create a preprocessor that pulls the penultimate (second to the last) position of the URL and inserts a custom object into session based on that information so all future processors will have it available.

Links

Creative Commons License
This work is licensed under a Creative Commons Attribution 2.5 License.

Mini-icons are part of the Silk Icons set of icons at famfamfam.com