joydip_kanjilal
Contributor

How to work with HttpModules in ASP.NET

how-to
Jul 01, 20166 mins
C#Microsoft .NETSoftware Development

HTTP modules intercept incoming requests and inject pre-processing logic in the ASP.Net request processing pipeline

05 http
Credit: Thinkstock

There are two ways in which you can inject logic in the request pipeline of an ASP.NET application — HttpHandlers and HttpModules. An HttpModule is a component that is part of the ASP.NET request processing pipeline and is called on every request that is made to your application.

Note that HttpModules can have access to the life cycle events of a request and hence they can be used to modify the response as well. HttpModules are generally used for plugging in the cross cutting concerns like security, logging, etc. in the request processing pipeline and can also be used for URL re-writing and even for creating custom headers in the response.

As Microsoft’s documentation states, “An HTTP module is an assembly that is called on every request that is made to your application. HTTP modules are called as part of the ASP.NET request pipeline and have access to life-cycle events throughout the request. HTTP modules let you examine incoming and outgoing requests and take action based on the request.”

To create a custom HttpModule, you should create a class that implements the System.Web.IHttpModule interface. To create an HttpModule, follow these steps:

  1. Open Visual Studio IDE
  2. Click on File->New Project
  3. Create a class library project
  4. Add reference to System.Web assembly to this project
  5. Next, create a class inside this project that implements the IHttpModule interface
  6. Write a handler for the Init method to initialize your module and subscribe to one or more events
  7. Optionally, implement a Dispose method in your custom module

At first glance, our custom HttpModule looks like this:

public class IDGCustomHttpModule : IHttpModule
   {
       public void Dispose()
       {
           throw new NotImplementedException();
       }
       public void Init(HttpApplication context)
       {
           throw new NotImplementedException();
       }
   }

The following code snippet shows how you can subscribe to events in your custom HTTP module.

public void Init(HttpApplication context)
       {
           context.BeginRequest += new EventHandler(OnBeginRequest);
           context.EndRequest += new EventHandler(OnEndRequest);            
           context.LogRequest += new EventHandler(OnLogRequest);
       }

Let’s now write the code for the OnLogRequest method. This method is intended to log the path or every request to a text file. Here’s how the OnLogRequest method should look:

public void OnLogRequest(object sender, EventArgs e)
       {
           HttpContext context = ((HttpApplication)sender).Context;
           string filePath = @"D:IDGLog.txt";
           using (StreamWriter streamWriter = new StreamWriter(filePath))
           {
               streamWriter.WriteLine(context.Request.Path);
           }
       }

The following code listing illustrates the complete custom HTTP module.

public class IDGCustomModule: IHttpModule
   {
       public void Init(HttpApplication context)
       {
           context.BeginRequest += new EventHandler(OnBeginRequest);
           context.EndRequest += new EventHandler(OnEndRequest);          
           context.LogRequest += new EventHandler(OnLogRequest);
       }
       public void OnLogRequest(object sender, EventArgs e)
       {
           HttpContext context = ((HttpApplication)sender).Context;
           string filePath = @"D:IDGLog.txt";
           using (StreamWriter streamWriter = new StreamWriter(filePath))
           {
               streamWriter.WriteLine(context.Request.Path);
           }
       }
       public void OnBeginRequest(object sender, EventArgs e)
       {
           //Write your custom code here
       }
       public void OnEndRequest(object sender, EventArgs e)
       {
           //Write your custom code here
       }
       public void Dispose()
       {
           //Write your custom code here to dispose any objects if needed
       }
   }

The next step is to use the custom HTTP module. To do this, create another project (this time, an ASP.NET application project). First, build the solution and add reference to the custom HTTP module we just created.

Next, you will need to register the custom HTTP module in the web.config file. The following code snippet illustrates how the custom HTTP module can be registered.

<system.webServer>
   <modules>
   <add name="CustomHttpModule" type="IDGModule.IDGCustomModule, IDGCustomModule" />
   </modules>
</system.webServer>

And, that’s all you need to do to use your custom HTTP module.

When using a synchronous HTTP module, the thread would not be released until the request processing completes. This can become a major performance bottleneck when your custom HTTP module needs to perform long running I/O bound operations. To solve this, you can take advantage of asynchronous programming to implement an asynchronous HTTP module as well. This would ensure that the performance of your application doesn’t degrade when your HTTP module needs to do lot of processing. Asynchronous programming helps in better usage of available resources.

To implement asynchrony in your custom HTTP module, you would want to leverage the EventHandlerTaskAsyncHelper class available as part of .NET Framework 4.5. The following code snippet illustrates how you can take advantage of this class to subscribe to events in the Init method of your custom HTTP module. Note that the LogRequest method should return an instance of type Task.

public void Init(HttpApplication context)
       {
           EventHandlerTaskAsyncHelper asyncHelperObject = new EventHandlerTaskAsyncHelper(LogRequest); 
           context.AddOnPostAuthorizeRequestAsync(asyncHelperObject.BeginEventHandler, asyncHelperObject.EndEventHandler);
       }

Here is the complete code listing of the asynchronous version of our custom HTTP module.

public class IDGCustomModule: IHttpModule
   {
       public void Init(HttpApplication context)
       {
           EventHandlerTaskAsyncHelper asyncHelperObject = new EventHandlerTaskAsyncHelper(LogRequest);
           context.AddOnPostAuthorizeRequestAsync(asyncHelperObject.BeginEventHandler, asyncHelperObject.EndEventHandler);
       }
       private async Task LogRequest(object sender, EventArgs e)
       {
           HttpContext context = ((HttpApplication)sender).Context;
           string filePath = @"D:IDGLog.txt";
            using (StreamWriter streamWriter = new StreamWriter(filePath,true))
           {
               await streamWriter.WriteLineAsync(context.Request.Path);
           }
       }
   }

How to do more in ASP.NET and ASP.NET Core:

joydip_kanjilal
Contributor

Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.

He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as Community Credit Winner several times.

He is the author of eight books and more than 500 articles. Many of his articles have been featured at Microsoft’s Official Site on ASP.Net.

He was a speaker at the Spark IT 2010 event and at the Dr. Dobb’s Conference 2014 in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the SSWUG Virtual Conference, which is held twice each year.

More from this author