HttpModules and HttpHandlers

HttpModules and HttpHandlers are part of the request lifecycle. When we have an incoming request, It is processed by multiple modules, for example session and authentication, and then processed by a single Handler before following back and to be processed again by the modules. Modules are called before and after the handler execution. These features allow us to intercept, modify or perform an action for each incoming request.



Fig 1 ( Request with modules and handler )

There are some scenarios where we can use these features to perform our actions. As we sad before, Modules could be use to process a session or to authenticate a request. At the same time we can use the modules to manage statistics and logging because modules are called for every request, i.e. you can process all the incoming requests. Furthermore, you can also create a custom header or footer because with modules you have the full access to the response, so you can add more information.

The handlers are used in different situations for example you could use it to create an an Image Server that serve images in a variety of size. After reading a parameter that contains the image path or the image ID, the handler could resize and send the image back. Another situation where the handler could be used is to implement an Rss feed. The handler will return the Xml that represent our information and then binding all the rss extension request to respond every time the rss extension is called. Obviously there are many way to deal with problems and sometime we need to evaluate the situation to chose the best solution. We can state that the handlers are used to process end point request so my request is an action that will create a content to display. The modules are function that intercept, take part and change the request so my module add something of my main end point request.


How can we create a new module ? We need to implement the interface System.Web.IHttpModule. This interface have just 2 methods :

void Init(HttpApplication context);
void Dispose();

The init method is used to inizialise a module and prepare it to perform our action The dispose method is used to perform the final actions to release all the allocate resources. The init method have a parameter HttpApplication that allow us to control when our module is run. Throw this parameter the module can work in various stage of the request. We have also the opportunity to configure our module in the Web.Config file on the HttpModule section. In the web config we can register our customer modules : 

<system.web>
    <httpModules>
      <add name="CustomModule" type="ModulesAndHandlers.CustomModule, ModulesAndHandlers" />
    </httpModules>
  </system.web>


To execute and debug our module with visual studio we need to use this configuration on the web config file.

<system.webServer>
    <modules>
      <add name="CustomModule" type="ModulesAndHandlers.CustomModule, ModulesAndHandlers" />
    </modules>
  </system.webServer>


This is the table of the event that we can register to run our custom modules.

Events Description
BeginRequest  First event raised when processing a request
AuthenticateRequest  Raised when a security model has identified the user 
PostAutenticateRequest  Raised after AuthenticateRequest
AuthorizeRequest  Raised after a security module has authorized a user
PostAuthorizeRequest  Raised after AuthorizeRequest
ResolveRequestCache  Raised to enable the cache to serve the request
PostResolveRequestCache  Raised after ResolveRequestCache
MapRequestHandler  Raised when the appropriate handler is selected
PostMapRequestHandler  Raised after MapRequestHandler
AcquireRequestState  Raised when the current state is obtain
PostAcquireRequestState  Raised after AcquireRequestState
PreRequestHandlerExecute  Raised before the event handler execution
PostRequestHandlerExecute  Raised after the event handler are terminated the execution
ReleaseRequestState  Raised when all event handler are completed
PostReleaseRequestState  Raised after ReleaseRequestState
UpdateRequestCache  Raised after cache module store a value
PostUpdateRequestCache  Raised after UpdateRequestCache
LogRequest  Raised before logging a request
PostLogRequest  Raised after all LogRequest are completed
EndRequest  Last event raised in the http request
PreSendRequestHeaders  Raised before the headers are sent to the client
PreSendRequestContent  Raised before the content is sent to the client 

 
This is an example code to create a custom module : 

 

public class CustomModule : IHttpModule
{

    public void Dispose()
    {
        ; // To free the resources allocates
    }

    public void Init(HttpApplication context)
    {
        // To register the event that will perform our action
        context.BeginRequest += new EventHandler(this.Application_BeginRequest);
    }

    private void Application_BeginRequest(object sender, EventArgs e)
    {
        ;// To Perform our action
    }


}



How can we define a new Handler ? We need to implement the System.Web.IHttpHandler interface. This interface have one property and one method :

bool IsReusable { get; }
void ProcessRequest(HttpContext context)


The property IsReusable is used to specify if our handler can be polled to increase the performance. The ProcessRequest method is used to perform our custom action that process the http request. We need to remember that we can run just one handler per request, conversely of modules that we can run more that one modules for each request. Also the handler have the config section on Web.config and we can configure it in HttpHandler section. The parameter that you can specify are :

- verb that specify the type of request GET, PUT or POST
- path that specify where the page is located
- type that specify the namespace and the class name that implement the custom handler


public class CustomHandler : IHttpHandler
{
    private bool _isReusable = true;

    public bool IsReusable
    {
        get { return _isReusable; }
    }

    public void ProcessRequest(HttpContext context)
    {
        context.Response.Write("This is our custom handler");
    }
}

 

<system.webServer>    
    <handlers>
      <add name="CustomHandler" verb="*" path="handler.aspx" type="ModulesAndHandlers.CustomHandler, ModulesAndHandlers"/>
    </handlers>
  </system.webServer>



With Asp.net 4.5 We can write our customer modules or handlers using asynchronous method. We need to remember the asynchronous method doesn't stop when it is called because will be created a new process that handle our async action. For example if we want to implement an authentication module using asynchronous method it is a logic error because When I run the authentication process my main action continue the execution without authentication. However when we use sync method our request will be managed from the modules and the handler by the same process so if there is an issue in one of our custom modules the main action will be negatively affected. In this case make our module async protect the main action from the module errors but there are some potential problems, for example if our application have a dependency with a data that a module product. The module doesn't product this data because fail and our application cannot use this data.

To implement an asynchronous module we need to use the await and async and task object like in this example :

public class CustomAsyncModule : IHttpModule
{
    public void Dispose()
    {
        ; // To free the resources allocates
    }

    public void Init(HttpApplication context)
    {
        // To register the event that will perform our action
        var helper = new EventHandlerTaskAsyncHelper(Application_BeginRequest);

        context.AddOnBeginRequestAsync(helper.BeginEventHandler, helper.EndEventHandler);
    }

    private async Task Application_BeginRequest(object sender, EventArgs e)
    {
        ;// To Perform our action
    }
}



To implement an async handler we need to inherit the HttpAsyncHandler like in the example :

public class CustomAsyncHandler : HttpTaskAsyncHandler
{
    public override Task ProcessRequestAsync(HttpContext context)
    {
        ;// To Perform our action
    }
}



HttpModules and HttpHandlers help us to organize our code and to encapsulate the code in a separate class that we can run in several application. Instead of using modules we could use a Global aspx file that can raise all the event that raise our module. Moreover global asax can intercept and edit the request like a module. If we use a global asax file, we cannot reuse our code in another application, so in the end modules are more flexible. 


I hope to explain this argument completely and clearly. I will be happy if you want to send me a feedback about this article.

 

 

Add comment

Calendar

<<  November 2017  >>
MonTueWedThuFriSatSun
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar

Page List

    Month List

    AuthorList