What is the Difference between an httpModule and an httpHandler?
HttpHandlers and HttpModules are low level aspects of the ASP.NET platform. The key difference between the two is a handler responds to a request by extension and a module plugs into the ASP.NET pipeline to manipulate the response.
I used to be asked all the time at developer conferences about the what each was and how they differed. If you are still working with ASP.NET, especially legacy versions it is important you understand how each work.
Somewhere back in the 2008 timeframe I even wrote a pair of small books on each.
A slightly more detailed answer is httpModules work with the web application as sort of an adjunct to the request pipeline because modules generally add some processing in response to an event in the pipeline.
An httpHandler actually processes the request type and renders the output being sent to the browser. A module can invoke a handler, not the other way around.
Custom modules implement the ihttpModule interface, which consist of a Dispose and Init method. In the Init method you would typically add event handlers to catch ASP.NET events, like AuthorizeRequest to perform custom logic. While you can access the Response filter to actually adjust the actual markup being sent to the client, this is very rare. Typically the module will process things outside of producing actual markup.
Custom handlers implement the ihttpHandler interface, which consist of the IsReusable property and the ProcessRequest method. The IsResuable property indicates to the ASP.NET engine if an instance of the handler can be reused for simultaneous requests. So typically this will return true for static content and false for dynamic content.
The ProcessRequest method operates much like the PageLoad event handler in the Page class (which by the way is an httpHandler). From the ProcessRequest method you initiate your code to actually build the markup being sent to the client.
To continue with my series on httpHandlers I want to cover how to stream a vCard to the user based on a parameter. First let me say that I grabbed the code for the .NET vCard class from a CodeProject.com article. There is also a corresponding vCalendar class. The idea behind a vCard is it is a standard format for sharing information about a person that can be imported directly to applications like Outlook.
The first thing to do in building the vCard httpHandler is to add a Generic Handler to the Web site. This can be done just like adding a page to the Web site, instead of selection a WebForm you would select Generic Handler from the Add New File Dialog. This will add a new file to the site with the .ashx extension. The 'h' indicates it is a handler, just like the 'p' in aspx indicates a page.
The file itself is a code page, that is either a VB.NET or a C# class file. There are two members in the httpHandler class, ProcessRequest and IsReusable property. By default the IsResuable property is set to False, which will suit our needs.
The ProcessRequest method is the workhorse for the handler and it is actually called by the ASP.NET engine to let the handler produce the output to be sent to the client. The ProcessRequest method has one parameter, the current httpContext of the request. This gives us access to everything we need to output a customized stream of formatted text, binary content or just about anything else we can possible send to a client across the wire.
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Place Code to Stream vCard here
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
The first thing we need to do to stream a vCard to the client is to set the ContentType of the response. In this case a 'text/directory' value, which indicates we are sending text and some sort of directory type information. If this were a normal HTML Web page it would be 'text/HTML' and a PDF would be 'application/PDF'. There are numerous possible values that can be passed at this point, and this deserves another entry for the Blog so I will leave it at this for today.
context.Response.ContentType = 'text/directory'
Now we can build our vCard class. For demonstration purposes I am just going to show how to build one in a hard coded manor, but you can substitute however you are going to retrieve user information. This could be from a database, Active Directory or where ever you store your personal data.
Dim vc As New vc.FirstName = 'Chris'vc.LastName = 'Love'vc.URLs.Add(New vCard.vURL('https://love2dev.com'))vc.Emails.Add(New vCard.vEmail('chris@love2dev.com'))Dim _address = New vCard.vAddress()_address.AddressName = 'Home Office'_address.City = 'Willow Spring'_address.State = 'NC'_address.Zip = '27592'
vc.Addresses.Add(_address)
For more practical uses you would typically get a parameter either through the Form or QueryString. Because the ProcessRequest method receives the current context these parameters are accessible. Typically you will need to process the QueryString, which would be context.Request.QueryString('UserName') for example.
We are almost done with the code. To actually place the vCard content in the output stream you pass the Response.Write method the vCard string. The vCard class I am using has a ToString method that outputs the vCard according to the vCard RFC. The Response.Write method writes the string to the output stream, so this is the actual content that will be rendered in the browser. Because we set the ContentType, typically this means it will try to open an associated application for the content type.
context.Response.Write(vc.ToString)
Finally you just need to call the Response.Flush and Response.End methods. The Flush method sends the content to the browser and the End method ends the request. You can actually push data to the browser as it is being built in an httpHandler and continue processing more output by using the Flush method. You can continue doing this until the End method is called. The End method stops all execution for the current request.
context.Response.Flush()
context.Response.End()
One more thing is left, registering our custom handler with the vCard extension, .vcf. To do this we need to do two things, set the Mime Type in IIS to process .vcf through the ASP.NET engine and in the web.config file.
In the web.config file we must associate the .vcf extension to the custom httpHandler. This is done in the httpHandlers section of the config file. You simply add the handler by defining the verbs, such as Get and Post, the extension and the actual handler class we have built.
Now that we have built our custom vCard httpHandler class, registered the vCard file extension with IIS and the custom handler with the extension we can start retrieving vCards from our Web site. if we have done everything correctly you will be prompted to either open or save the vCard. If you have an application, such as Outlook, associated with the .vcf extension an you select Open it will open open the vCard in the application. From there you can typically store it in the address book. Of course saving it will place the file on your hard drive.
The more I go out and do presentations about ASP.NET tactics the more I seem to find myself demonstrating the use of httpModules and httpHandlers. I wanted to give a brief introduction to httpModules for everyone. Especially since I have already been discussing ASP.NET httpModules here and have several that will be published very soon.
HttpModules are simply classes that can reside either in your Web site's code or in a separate class library. They are plugged into the life cycle of each request run through the ASP.NET engine. Typically they hook into events in the request life cycle and can react to actual request or modify the output in the Response object before it is sent to the client.
Each httpModule must be registered with the site in the web.config file. This is done in the system.web section through the httpModules element. This example show a typical registration for one of my current sites. I have two modules built into the site and then the ASP.NET AJAX module registration.
httpModules add type = 'RegExUrlMapping_HTTPModule.RegExUrlMappingModule'name = 'RegExUrlMappingModule' add name ='ScriptModule' type ='System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' add type ='_301RedirectModule' name ='_301RedirectModule' httpModules
To create your own httpModule you must define a class that implements the IhttpModule interface. This interface requires you implement two methods, Init and Dispose. In the Init method you typically will wire up event handlers for one or more events in the Page life cycle, such as AuthenticateRequest. You can learn more about the ASP.NET page life cycle in this detailed MSDN article.
The httpModule's Init method passes a reference to the current httpApplication object. This provides access to the current application, and the ASP.NET page life cycle events. These events can be wire to event handlers in the module. Each event handler must have the standard ASP.NET event signature, a sender as an Object and and EventArgs object. You can add any custom code you would like to your event handler, just be aware that some objects may not have been instantiated or might have been destroyed at the various points of the life cycle.
An example from a Previous post on 301 redirects
Private
_contextAs
System.Web.HttpApplicationPublic
Sub
Init(ByVal
contextAs
System.Web.HttpApplication)Implements
System.Web.IHttpModule.InitAddHandler
context.AuthorizeRequest,AddressOf
Process301End
Sub
Public
Sub
Process301(ByVal
senderAs
Object
,ByVal
eAs
EventArgs)_context = contextDim
appAs
HttpApplication =CType
(sender, HttpApplication)
Dim
htAs
Hashtable = Get301Mappings()
Dim
sPathAs
String
= app.Context.Request.AppRelativeCurrentExecutionFilePath
If
Not
IsNothing(ht(sPath))Then
app.Response.StatusCode = 301
' make a permanent redirect
app.Response.AddHeader(
'Location'
, ht(sPath).ToString)app.Response.End()
End
If
End
Sub
The Module's Dispose method allows you to clean up any resources that need to be destroyed before the application closes. Typically you will want to remove any event handlers, close any open files, etc.
Public
Sub
Dispose()Implements
System.Web.IHttpModule.DisposeRemoveHandler
_context.AuthorizeRequest,AddressOf
Process301End
Sub
Now most of what you can do with an httpModule can be done in the Global.asax file. The main difference between the two is that common functionality can be encapsulated in an httpModule and distributed among various sites and even placed in the GAC. The advantage the Global.asax has is that it is easier to work with Session level events.
I encourage you to read my entries on practical application of httpModules, the MSDN articles and any other online resources for httpModules you can find. Using modules can be a great benefit to making your site more professional, easier to maintain and running efficiently.
I think these two distinctive aspects of ASP.NET get confused by many because they both serve near the metal. Both are responsible for separate tasks, but typically work in harmony to make ASP.NET the great framework it is.