Click here to Skip to main content
Click here to Skip to main content
Go to top

Implementing HTTPHandler and HTTPModule in ASP.NET

, 27 Feb 2012
Rate this:
Please Sign up or sign in to vote.
This article aims at understanding the role of HTTPHandler and HTTPModule in ASP.NET applications.

Introduction

This article aims at understanding the role of HTTPHandler and HTTPModule in ASP.NET applications. We will try to work on a basic example to see how these can be implemented.

Background

ASP.NET handles all the HTTP requests coming from the user and generates the appropriate response for it. ASP.NET framework knows how to process different kind of requests based on extension, for example, It can handle request for .aspx, .ascx and .txt files, etc. When it receives any request, it checks the extension to see if it can handle that request and performs some predefined steps to serve that request.

Now as a developer, we might want to have some of our own functionality plugged in. We might want to handle some new kind of requests or perhaps we want to handle an existing request ourselves to have more control on the generated response, for example, we may want to decide how the request for .jpg or .gif files will be handled. Here, we will need an HTTPHandler to have our functionality in place.

There are also some scenarios where we are ok with the way ASP.NET is handling the requests but we want to perform some additional tasks on each request, i.e., we want to have our tasks execute along with the predefined steps ASP.NET is taking on each request. If we want to do this, we can have HTTPModule in place to achieve that.

So from the above discussion, it is clear that HTTPHandlers are used by ASP.NET to handle the specific requests based on extensions. HTTPModule, on the other hand, is used if we want to have our own functionality working along with the default ASP.NET functionality. There is one Handler for a specific request but there could be N number of modules for that.

Using the Code

Let us try to understand these two concepts by writing a small application for each. What we will do is we will try to have a mechanism where we can process the web pages with extension like .bspx and .cspx. Although this is a very unrealistic scenario, a similar concept is used to have search engine friendly URLs so perhaps it's not that realistic either.

Note: The HTTPHandler example here is just for demonstration purpose, I am not recommending the use of HTTPHandlers for something that I am about to do now. HTTPHandlers should ideally be used to customize the handling of existing MIME types and not for serving search engine friendly URLs or non standard URLs.

Implementing the HTTPHandler

So with our problem definition, let us try to see how we can handle the request for .cspx pages using HTTPHandlers. First we need to have the handler class with us, so let us create the handler class.

public class CspxHandler :IHttpHandler
{
    public bool IsReusable
    {
        get { return false; }
    }

    public void ProcessRequest(HttpContext context)
    {

    }
}

The class should have a method ProcessRequest and a property called IsReusable. The property tells whether this handler can be reused or not and the method will be called whenever a request for that type comes. But wait, Where have we defined the type of request where this handler should be invoked? This can be defined either in IIS, if we have a handler common to all the sites running on that server or we can configure it in web.config file, if the handler is specific for a website. Let's do that in web.config file for now.

<httpHandlers>
    <add verb="*" path="*.cspx" type="CspxHandler"/>
</httpHandlers>

Here we registered our handler to specify that if any request for .cspx file comes, it should be forwarded to our handler.

Now, since we don't have any "real" files with .cspx extension, what we will do is we will handle the request for .cspx and in turn push the user to the corresponding .aspx file.

public class CspxHandler :IHttpHandler
{
    public bool IsReusable
    {
        get { return false; }
    }

    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "text/plain";

        if (context.Request.RawUrl.Contains(".cspx"))
        {
            string newUrl = context.Request.RawUrl.Replace(".cspx", ".aspx");
            context.Server.Transfer(newUrl);
        }
    }
}

Whenever a request for .cspx file comes, we will handle it in our handler and show the corresponding .aspx file instead. Let's see how it works.

Note: I have also changed the startup page name to Default.cspx but there is no page like that. I want my handler to handle that and show me the actual default page.

Important: I reiterate, This example is just for illustration. This is not how HTTPHandlers should be used at all. HTTPHandlers should ideally be used to customize the handling of existing MIME types.

Well the pages seems to be working fine and the user will see .cspx URL for his request. But there is one problem. The way we wrote our handler is not good to handle the postback. If I add a button on any of these pages and do a postback, the original URLs will be visible. So it is not a good solution to the problem but it sure demonstrated the way Handlers can be used.

Implementing the HTTPModule

How do we solve the problem we just saw. Well, our application needed URL rewriting and HTTPHandlers are a bad solution for that and should never be used for that. So perhaps the guys using this technique to have search friendly URLs should rethink their strategy. SO how can we solve this problem really.

Let us look at the requirement again, All we needed was to show the user URLs which are different than the real URLs and process the real URLs internally. So we don't need custom handlers, we are ok with the way ASP.NET engine is handling these requests but we need custom activities to be done during the processing phase. So it looks like we can solve it using HTTPModule.

So let's go ahead and write an HttpModule that will:

  1. Check for file extension on request.
  2. If it finds a .bspx extension it changes it to .aspx (or find real URLS if we are implementing search friendly URLs)
  3. It will pass the request to the default handler, since the page is still aspx.
  4. Once the response is generated, it will write back the original .bspx URL to users browser.
public class MyBModule : IHttpModule
{
    public void Dispose()
    {

    }

    public void Init(HttpApplication context)
    {
        context.BeginRequest += new EventHandler(context_BeginRequest);
        context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
        context.EndRequest += new EventHandler(context_EndRequest);
        context.AuthorizeRequest += new EventHandler(context_AuthorizeRequest);
    }

    void context_AuthorizeRequest(object sender, EventArgs e)
    {
        //We change uri for invoking correct handler
        HttpContext context = ((HttpApplication)sender).Context;

        if (context.Request.RawUrl.Contains(".bspx"))
        {
            string url = context.Request.RawUrl.Replace(".bspx", ".aspx");
            context.RewritePath(url);
        }
    }

    void context_PreRequestHandlerExecute(object sender, EventArgs e)
    {
        //We set back the original url on browser
        HttpContext context = ((HttpApplication)sender).Context;

        if (context.Items["originalUrl"] != null)
        {
            context.RewritePath((string)context.Items["originalUrl"]);
        }
    }

    void context_EndRequest(object sender, EventArgs e)
    {
        //We processed the request
    }

    void context_BeginRequest(object sender, EventArgs e)
    {
        //We received a request, so we save the original URL here
        HttpContext context = ((HttpApplication)sender).Context;

        if (context.Request.RawUrl.Contains(".bspx"))
        {
            context.Items["originalUrl"] = context.Request.RawUrl;
        }
    }
}

Also we need to register our module so that it can be invoked, we will do that in our web.config file.

<httpModules>
    <add name="MyBModule" type="MyBModule" />
</httpModules>

And now let's run the application:

So here we solved the problem of URL reverting back to the original on postback. This is also the ideal way of doing that.

Points of Interest

In this article, we saw how we can implement a basic HTTPHandler and HTTPModule. We saw each of their roles in page processing frameworks. We worked on an example that tried to solve the URL rewriting first the wrong way by using HTTPHandler (but we understood how to write HTTPhandler) and then the right way of doing URL rewriting using HTTPModule (we got to understand that too.

The emphasis of this article was solely on understanding how we can have HTTPHandlers and HTTPModules working. The example is a little unrealistic and perhaps a little misleading too but since I made that point really clear, it shouldn't be a problem.

Before wrapping up, there is one last thing that we should know about handlers. It is also possible to handle the request asynchronously. ASP.NET provides a mechanism for creating asynchronous handler and then increases the performance of a web page (implements the IHttpAsyncHandler do that).

History

  • 25 Feb 2012: Implementing HTTPHandlers and HTTPModules in ASP.NET

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Rahul Rajat Singh
Software Developer (Senior)
India India
I Started my Programming career with C++. Later got a chance to develop Windows Form applications using C#. Currently using C#, ASP.NET & ASP.NET MVC to create Information Systems, e-commerce/e-governance Portals and Data driven websites.

My interests involves Programming, Website development and Learning/Teaching subjects related to Computer Science/Information Systems. IMO, C# is the best programming language and I love working with C# and other Microsoft Technologies.
  • Microsoft Certified Technology Specialist (MCTS): Web Applications Development with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Accessing Data with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Windows Communication Foundation Development with Microsoft .NET Framework 4
 
If you like my articles, please visit my website for more: www.rahulrajatsingh.com[^]
Follow on   Twitter   Google+   LinkedIn

Comments and Discussions

 
GeneralMy vote of 5 PinmemberHumayun Kabir Mamun3-Sep-14 4:00 
Questiongeting error Pinmemberabdolwahab7-Aug-14 23:28 
GeneralMy vote of 3 PinmemberMember 1062364621-Jul-14 19:34 
QuestionHTTP Module Event Hierachy Pinprofessionalnileshwar shukla13-May-14 2:00 
QuestionProblem with filehandler PinmemberMember 83044137-May-14 1:47 
QuestionGetting error Pinmemberfaiz Ansari2-May-14 23:19 
QuestionNice article, simplest one i have found PinmemberSougata Mudi21-Apr-14 18:45 
QuestionNice & Clear Concept PinmemberRavi Sadalagi8-Apr-14 19:15 
QuestionVery Useful PinmemberMember 10305802-Mar-14 23:05 
QuestionError PinmemberAmi_Modi22-Jan-14 23:46 
AnswerRe: Error PinmemberJaison Devasia7-Apr-14 12:46 
GeneralRe: Error PinmemberJaison Devasia7-Apr-14 14:32 
QuestionGreatttt!!! Pinmemberparadisee13-Jan-14 7:15 
QuestionWhy we are using context_PreRequestHandlerExecute event? PinmemberChetan Naithani6-Nov-13 9:56 
GeneralMy vote of 4 PinmemberMayuri Kulkarni8-Oct-13 20:02 
GeneralMy vote of 5 PinmemberS.P. Tiwari25-Jul-13 0:53 
GeneralMy vote of 4 PinmemberRukeshjee25-Jun-13 3:34 
QuestionQuestion PinmemberNainil21-Apr-13 15:54 
GeneralMy vote of 5 PinmemberMember 998151412-Apr-13 17:24 
GeneralMy vote of 5 Pinmembervicvis28-Feb-13 12:01 
QuestionWhy HttpHandler is not best way PinmemberHarshilG23-Jan-13 20:54 
QuestionNot Working Pinmemberchenthil2819-Jan-13 23:47 
GeneralMy vote of 5 Pinmembersajid Dhukka9-Jan-13 4:02 
AnswerArticle of the Day on Microsoft's site PinmemberRahul Rajat Singh14-Dec-12 19:20 
GeneralExcellent and well written PinmemberBalaNet4-Dec-12 19:22 
Generalnice article PinmemberBo7maid1-Dec-12 7:08 
simple and clear for beginners thanks a lot !
GeneralMy vote of 5 PinmemberPiyushSinghi29-Nov-12 1:49 
QuestionGood One PinmemberMember 879811430-Oct-12 12:09 
QuestionWhich one is best for REST? PinmemberVitaly Tomilov5-Oct-12 1:41 
Generalmy vote of 5 Pinmemberbeginner201118-Jun-12 17:35 
Questiondownload link error Pinmemberbeginner201117-Jun-12 21:15 
AnswerRe: download link error PinmemberRahul Rajat Singh18-Jun-12 3:46 
GeneralThank you! Pinmemberbeginner201118-Jun-12 17:20 
QuestionThanks ! PinmemberJayantiChauhan6-Mar-12 0:52 
GeneralMy vote of 5 Pinmembersaxenaabhi629-Feb-12 13:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140926.1 | Last Updated 28 Feb 2012
Article Copyright 2012 by Rahul Rajat Singh
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid