HttpHandlers – Learn Them. Use Them.

My first blog post from Word 2007 – let’s see how this goes.

Introduction

There are many features in ASP.NET that are unfortunately underused. Sometimes a feature gets looked over because it’s too complicated. Other times, like in the case of HttpHandlers, it’s because they are poorly understood. For the longest time I understood the concept and implementation of HttpHandlers, but I just couldn’t figure out under what circumstances I’d use them.

Googling HttpHandlers it’s obvious to me that bad tech writers are squarely to blame. A shameful amount of examples are nothing more than “hello world.” The problem with such a limited example is that it leaves the reader thinking “so? I can do that with an aspx page!” Without understanding what problem space HttpHandlers are meant for, it’s impossible to get developers to use them.

As an ASP.NET developer, HttpHandlers are important because they are the earliest possible point where you have access to requests. When a request is made to IIS for an ASP.NET resource (.aspx, .config, .asmx), the ASP.NET worker process internally creates an instance of the right HttpHandler for the request in question and effectively hands off the task of responding to the request. How does ASP.NET know which is the right HttpHandler for a given request? Simple, via configuration files, paths are mapped to http handlers. For example, if you open your machine.config file you’ll see a list of default mapping. For example:

<add verb=”*” path=”*.aspx” type=”System.Web.UI.PageHandlerFactory” />
<add verb=”*” path=”*.config” type=”System.Web.HttpForbiddenHandler” />
<add verb=”*” path=”*.asmx” type=”System.Web.Services.Protocols.WebServiceHandlerFactory” />

So every time any .aspx page is requested, the PageHandlerFactory is left to fulfill the request. HttpHandlers can also be added or changed for specific sites in the web.config. Handlers aren’t just mapped to extensions, your own handler can be mapped to “HandlePingback.aspx”, in which case it, not the PageHandlerFactory, will be called upon.

An HttpHandler is actually any class that implements the System.Web.IHttpHandler interface. To be of any use it needs to be mapped to a path. (I lie, PageHandlerFactory doesn’t implement IHttpHandler. Instead, it implements IHttpHandlerFactory. IHttpHandlerFactory defines a method named GetHandler which returns an IHttpHandler. We won’t cover IHttpHandlerFactories here, but it’s basically a layer between the internal ASP.NET process and the handoff to the HttpHandler. Either way, in the end you end up with a class that implements IHttpHandler). The IHttpHandler interfaces defines the very important and aptly named ProcessRequest. Basically, this is ASP.NET saying “hey you! Process this request!”

Built-in Handlers

If we look at the most important HttpHandler, the System.Web.UI.Page class (yes, the same one that all your pages inherit from), we really start to get a good feel for what an HttpHandler is responsible for. Looking at the internals of the Page class and starting from the ProcessRequest function, we quickly get to a ProcessRequestMain function which really starts to interact with stuff you do on a daily basis. Look at some of the stuff that happens in ProcessRequestMain:


base.InitRecursive(null);
if (context1.TraceIsEnabled)
{
      this.Trace.Write(“aspx.page“, “End Init“);
}
if (this.IsPostBack)
{
      if (context1.TraceIsEnabled)
      {
            this.Trace.Write(“aspx.page“, “Begin LoadViewState“);
      }
      this.LoadPageViewState();
      if (context1.TraceIsEnabled)
      {
            this.Trace.Write(“aspx.page“, “End LoadViewState“);
            this.Trace.Write(“aspx.page“, “Begin ProcessPostData“);
      }
      this.ProcessPostData(this._requestValueCollection, true);
      if (context1.TraceIsEnabled)
      {
            this.Trace.Write(“aspx.page“, “End ProcessPostData“);
      }
}
base.LoadRecursive();

As you can see, it’s this method that’s responsible for causing all those ASPX events, such as OnInit and OnLoad, to be raised. In essence, the Page class does what it’s supposed to do: it’s handling the request.

Another handler we saw listed above is the HttpForbiddenHandler (which is a straight handler as opposed to a HandlerFactory). A number of paths are mapped to this handler – generally files that might compromise a security risk if left publically accessible (like .config, .cs, .vb, .dll, …). The ProcessRequest for this handler is to the point:

public void ProcessRequest(HttpContext context)
{
      PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_NOT_FOUND);
      throw new HttpException(0×193, HttpRuntime.FormatResourceString(“Path_forbidden“, context.Request.Path));
}

Why use a handler?

There are likely few times where you have to use a handler. Almost anything you can do in a handler, you could simply create an aspx page to take care of. So why bother? There are two main reasons. First and foremost, HttpHandlers are far more reusable/portable than pages. Since there’s no visual element to an HttpHandler (no .aspx), they can easily be placed into their own assembly and reused from project to project or even sold as is. Secondly, the Page handler is relatively expensive. Going with the “Hello World” examples, if you do that in a page you’ll end up raising a number of events (onInit, onLoad, onPreRender, onUnload, …) and make use of a number of ASP.NET features such as viewstate and postback. In most cases, the performance hit is negligible, but it nonetheless highlights that you’re using the page framework when you have no need to.

Real Examples

The first example to look at is the TrackbackHandler than’s part of CommunityServer 1.1. If you go to http://code.communityserver.org/ and open 1.1/Blogs/Components/TrackbackHandler.cs you’ll see the relevant source code. The purpose of this handler is to track pingbacks made to blog entries. Most blog engines will automatically send a pingback to any linked posts. This means that blog engines must also have a way to capture these pingbacks and record them. There’s more or less a standard between how the communication is supposed to happen, but each blog engine is really on its own as far as implementation. Without spending too much time in the code, we can see that the handler looks for a number of POST parameters and creates the trackback based on what’s passed in.

There’s absolutely no reason why all of this couldn’t be done using an ASPX page. But as I’ve already mentioned, that would force the entire ASPX page framework to be invoked. Additionally, this handler doesn’t even have a visual element – so a page doesn’t make too much sense.

(you can look at the web.config to see how the handler’s added).

Another example is my open source AMF.NET project which makes it possible for a Flash application to communicate with server-side ASP.NET code. The AmfGetwayHandler deserializes the AMF input (AMF is a proprietary binary protocol used by Flash), executes the right server side .NET function and returns a serialized response. Again, a single ASP.NET page could be used to accomplish the same thing, but then it would be impossible to package AMF.NET as a single assembly.

Another common example you’ll run across is using HttpHandlers to generate RSS feeds. Many applications will map “Rss.aspx” to an HttpHandler which generates a XML feed.

Why not to use HttpHandlers

The biggest and very significant drawback of HttpHandlers is that they can only be used for extensions that are mapped to ASP.NET in IIS. It might be great to create a file download counter for your .zip files using an HttpHandler, but since IIS doesn’t go through ASP.NET to serve .zip files, it isn’t going to work. One solution is to map those extra extension to ASP.NET, but that might have undesirable side effects and might not even be possible for you (many developers don’t have direct access to IIS). In this case, the only solution is to create an ISAPI filter which is much more difficult. IIS 7 promises to let us write ISAPI filters in .NET (or extend HttpHandlers beyond the ASP.NET pipeline depending on how you look at it), but that’s still a ways away.

This entry was posted in Grab a coffee before reading. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

69 Responses to HttpHandlers – Learn Them. Use Them.

  1. Nabeel says:

    Thanks a lot for publishing it. God bless you.

  2. Nitin says:

    Hi All,

    I m using Asp.net 2.0 to develop my web app.
    i m using Webhandler (.ashx) pages to wrrite some html from backend..
    the code is work finr for IE but it is not work for mozilla,safari..
    here is the code..
    In Javascript i write:-

    var xmlhttp = null;

    if (window.XMLHttpRequest) { // if Mozilla, Safari etc
    xmlhttp = new XMLHttpRequest();

    }
    else if (window.ActiveXObject) { // if IE
    try {
    xmlhttp = new ActiveXObject(“Msxml2.XMLHTTP”);

    } catch (e) {
    try {
    xmlhttp = new ActiveXObject(“Microsoft.XMLHTTP”);

    } catch (e) {}
    }
    }

    if (xmlhttp)
    {
    xmlhttp.open(“POST”, “./htask_getDevicesGroupWise.ashx”, true); //varAsynx = true
    xmlhttp.onreadystatechange = function()
    {
    if (xmlhttp.readystate ==4) //4 is a success
    {
    try{
    var result = xmlhttp.responseText;
    eval(result);
    LoadingHide();
    }
    catch(e)
    {
    //alert(e.message)
    //throwError(e.message,’fn_runHandler’,'Common Handler’,'ve.js’);
    }
    }
    }
    xmlhttp.send(null);
    }

    And in Handler page i just write

    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
    context.Response.Write(“alert(‘sfs’);”)
    End Sub

    alert message is not showing on mozilla,safari but it is working in IE.
    so i think context.Response.Write is not working ..
    Why?

    Please help!!!
    Thanks in advance
    Nitin

  3. Nitin says:

    Hi All,

    I m using Asp.net 2.0 to develop my web app.
    i m using Webhandler (.ashx) pages to wrrite some html from backend..
    the code is work finr for IE but it is not work for mozilla,safari..
    here is the code..

    In Javascript i write:-

    var xmlhttp = null;

    if (window.XMLHttpRequest) { // if Mozilla, Safari etc
    xmlhttp = new XMLHttpRequest();

    }
    else if (window.ActiveXObject) { // if IE
    try {
    xmlhttp = new ActiveXObject(“Msxml2.XMLHTTP”);

    } catch (e) {
    try {
    xmlhttp = new ActiveXObject(“Microsoft.XMLHTTP”);

    } catch (e) {}
    }
    }

    if (xmlhttp)
    {
    xmlhttp.open(“POST”, “./htask_getDevicesGroupWise.ashx”, true); //varAsynx = true
    xmlhttp.onreadystatechange = function()
    {
    if (xmlhttp.readystate ==4) //4 is a success
    {
    try{
    var result = xmlhttp.responseText;
    eval(result);
    LoadingHide();
    }
    catch(e)
    {
    //alert(e.message)
    //throwError(e.message,’fn_runHandler’,'Common Handler’,'ve.js’);
    }
    }
    }
    xmlhttp.send(null);
    }

    And in Handler page i just write

    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
    context.Response.Write(“alert(‘sfs’);”)
    End Sub

    alert message is not showing on mozilla,safari but it is working in IE.
    so i think context.Response.Write is not working ..
    Why?

    Please help!!!
    Thanks in advance
    Nitin

  4. DevMan says:

    Still pretty foggy on the advantages and uses of an http handler.

    I’d say this article falls into the “bad tech writers are squarely to blame” catagorie.

    You’ve jumped from hello world to proprietary binary serialization.

  5. Seo says:

    Very helpful infos about HttpHandlers. Thanks a lot for publishing it. ;-)

  6. SEO Texter says:

    Great article. Thanks for the information.

  7. Nice stuff… thanks for sharing…

  8. Sucharitha says:

    plzz check my client code also….if client sends a string server is recieveing (NameValuePair) but if it sends a file it is not recieving…

    File input = new File(“XMLFile1.xml”);
    RequestEntity entity = new FileRequestEntity(input);
    PostMethod post = new PostMethod(url);
    post.setRequestEntity(entity);
    HttpClient httpclient = new HttpClient();

    try
    {
    int result = httpclient.executeMethod(post);
    if (result >=200 && result <=210 ) {
    System.out.println(“Request Timed out”);
    System.err.println(“Method Failed:”post.getStatusLine()+ post.getStatusText());}
    System.out.println(“Response status code: “+result);
    System.out.println(post.getResponseBodyAsString());
    }
    catch(Exception e)
    {
    System.out.println(“Response body: “);
    }
    finally
    {
    post.releaseConnection();
    }

    I’m getting the response code as 200. but no files are uploaded at the server. i checked all permissions they are fine and firewall is turned on.

    plzz help out with this……..

    thanq in advance

  9. karl says:

    Sucharitha:
    Your code works fine for me. Have you been able to step through the code and check for any exceptions? The only thing I can really think of is a filepermission error. Maybe you can try to save the file directly in the root of the website (for now), and see if that works.

    You might want to try using FileMon (google “FileMon”, it’s free) and seeing if there’s a permission problem.

  10. sucharitha says:

    hey,

    please answer any question its very important to me.
    how server will save a file which is posted to it by the client in asp.net.?

    please do reply

  11. sucharitha says:

    my other question is

    i wanted to send a file to server. i used post method to do so. the server should save that file.
    but this is not happening.

    i posted the file sucessfully. i got the response code as 200 but the file is not saved in specified directory.
    at server.

    in webform page_load event i wrote:

    Dim f As String

    Dim file

    For Each f In Request.Files.AllKeys

    file = Request.Files(f)

    file.SaveAs(“c:\test2\” & file.FileName)

    Next f

    but this code is not working. how can i save the incomming file?

  12. karl says:

    They go in


    ….

    You can only have 1 httphandler per type, so if you specify your own handler for .aspx files, the default handler will no longer process the page normally (which I can’t imagine is what you actually want).

    Not sure about your other question with respect to file uploads.

  13. sucharitha says:

    I’m sorry…that some sentences are incomplete in my previous post.

    Actually I wanted to create a my own handler to process requests for .aspx pages.

    my doubt is
    where should i add

    in web.config file?
    where i want in ?or is there any particular location?
    because i’m getting an exception whenever a request is sent from client.

    & the other question is about whether i can save files sent by client with default Handler in pageFactoryHandler.

    if so, could you please tell me how a server will handle such type of requests.

  14. sucharitha says:

    i have doubt regarding where to add

    in web.config file.

    i want to create a new handler for .aspx pages.

    & one more question about default handler in PageFactoryHandler saves the files to the specified directory sent by client.

    if so, could you please how server will handle such type of requests?

    thanku in advance

  15. Banjo says:

    I tried following mapping in webconfig-file inside system.web:



    ..and it works for me!

    / Banjo

  16. Banjo says:

    Good article.

    How can I ‘redirect’ (url rewrite) http://myhostname.org/Doc.aspx?id=12345&extension=pdf&filename=myfile.pdf request for the httphandler http://myhostname.org/Doc.ashx?id=12345&extension=pdf&filename=myfile.pdf ?

    Is it possible to do that url rewrite in webconfig file? How about those request querystring parameters which are not static?

    Thanks, Banjo

  17. Mahmoud Raad says:

    i didn’t like your comments maybe i am idiot :D

  18. karl says:

    Stephen:
    Sounds right. It’s pretty much being used as a soap-less webservice at that point, which is fine. You end up having a custom service sitting on top of a very powerful multi threaded server (Windows 2003/IIS).

  19. Stephen says:

    Great article.

    I’ve been asked to write a web service that serves up multipart MIME messages – it’ll be consumed by a Java client that expects SwA attachments. I’m thinking that I could use a HTTP Handler to construct and return the multipart MIME response. Is this an appropriate use of HTTP Handlers?

  20. karl says:

    Richard:
    I can’t help but think a socket server would be better off handling this type of task. I even see something UDP based as being highly efficient and scalable and capable of circumventing firewalls.

    You might want to check out:
    http://www.pluralsight.com/blogs/fritz/archive/2006/04/11/21480.aspx

    along with the comments (especially Josh Twist’s post with the links).

    I’m pretty sure that ThreadPool in ASP.NET is per site/app domain…HttpHandlers are well below this – so yes, they would all share the same one.

  21. Brian says:

    Nice article. But the problem I find with the ProcessRequest is that it fires more than once.

  22. Richard Norris says:

    Hi Karl,

    Great article. I’ve got a particular problem that I hope HTTPHandlers can help me to achieve. I want to mimic the Exchange 2003 SP2 Push Email feature for mobile devices.

    My research has led me to discover that MS do this with a ISAPI extension. Basically the WM device makes a HTTP/HTTPS call to this extension. The time-out of this request is set high. The extension then holds on to the request through-out this period until it finds that an email is available. If it does it just responds to the client. Otherwise it returns nothing before the time-out expires.

    Doing this is kind of resource intensive and bad news for ASP.NET. I’m not a ASP.NET developer but when I started to look at doing this with ASP.NET everything told me not to play with the thread-pool. This means I am restricted to 20 threads and that is no good for this app. Obviously I could increase the pool but I’m worried that performance will be severly effected.

    Ok, so the performance issue is never going to really go away, but are HTTPHandlers limited to the same thread-pool (My first guess is yes). I hope I’m wrong. Am I looking in the right place for this solution?

    TIA

    Richard

  23. Ankit Goel says:

    hi karl
    this article was very helpful to me in understanding HTTPHandler

    Thanks
    Ankit

  24. karl says:

    Dennis: no. Handlers are meant to handle specific requests. What you’d be more interested in is an HttpModule. Except that’s only fed into the pipeline of files being served by the ASP.NET module (via extension mapping in IIS) – which may very well be good enough for you. If that’s what you want, then use an HttpModule and hook into the BeginRequest event…I’ve blogged about HttpModules as well.

    Until IIS 7.0 comes out, the only solution to filter ALL requests (images, .js, .css,…) is to use an ISAPI filter written in C++.

  25. Dennis says:

    Is it possible to intercept all http requests to an IIS site and determine the client browser with an HTTPHandler?

  26. karl says:

    Jack, not sure.

    You should get a IHttpHandler instance out of that (which is actually a page), which you should be able to call ProcessRequest on, which expects the HttpContext.

    If you’re handler is using GetCompiledPageInstance, why not just use the normal page framework? Without knowing more, it seems like you are using HttpHandlers for the wrong reasons.

    Also, from the MSDN documentation:
    “This method supports the .NET Framework infrastructure and is not intended to be used directly from your code.”

  27. Jack says:

    I have PageParser.GetCompiledPageInstance. The result is that it returns a blank page? Why is that?

  28. naybet says:

    how can i use HttpHandler in dot net nuke

  29. karl says:

    Seems to me that you you are trying to POST to a file that has a handler set up for GET only. From your explanation, I figured you were opening directly to a .doc file, so something like:

    By default .doc files aren’t handled by ASP.NET. Did you add a handler in your web.config or your machine.config? Are you using a different extension? What subfolder are your .doc files in?

    Even if I’m on the right track, it’s very odd because window.open(“xxx”) should be doing a GET…so I don’t see why you’d be getting back a POST.

    I’d love to see an example…you can zip something up and mail it to kseguin FuelIndustries . com

  30. rajdev says:

    Karl, the codebehind here means the .vb file of the aspx page. Currently I am not having any httphandler. The error is “Path ‘POST’ is forbidden”. I believe that this occurs because of trying to open a word document. If it is a html document i am not getting any error. I believe that you will be clear on the error..

  31. karl says:

    Rajdev…I’m not reallly clear…you say you are doing this in codebehind…but I take it you mean within your httphandler/ What error are you getting specifically?

  32. rajdev says:

    Hi,
    I am trying to open a word document from code behind file. I am using Response.Write(““. But i am getting http handler error. Is there any way to solve the problem?
    It seems that we have to write our own handler. Is there any alternative method available?
    Thanks in advance

  33. Yankee says:

    Nice Comments

  34. karl says:

    Stefe:
    You normally set up your handler to handle a very specific request, say “rss.axd” or “imageGenerator.aspx”. At most you might map it to a full subfolder, like “ajax/*”.

    I’m not sure exactly when the HttpHandler is invoked with respect to the HttpModule. It’s possible that in BeginRequest the HttpHandler hasn’t been invoked yet (it’d be fairly easy to find out), so yes, you could circumvent it, but then your module will fire for every hit..so if you stop the httphandler chain, your .aspx handlers (PageFactoryHandler) will never fire and you’ll cripple your asp.net. yes, there might be ways around this (like checking the page url in BeginRequest and doing different stuff)..but why?

  35. Stefe says:

    Well, also with handlers you tipycally end up serving all requests … I mean, you typically register your handler to serve all aspx requests ending up obtaining the same result as for modules.
    What you say about having each request being finally served by a handler is generally true but not necessarily true. Suppose I have a module that on a request responds doing something and then rising the EndRequest event. That would end the request. And no handler has been invoked. Am I right?

  36. karl says:

    Steve,
    There is some similarity between the two. The main difference though is that IHttpHandlers handle specific requests, IHttpModules service all application requests. It’s probably possible to do everything in an HttpModule -but the request will still use an HttpHandler, so you still want to take advantage of a custom handler in some situation (i.e., you don’t necessarily always want to inherit all the stuff the default handler does).

  37. Steve says:

    I’m kind of confused as to when use modules and when use handlers … by using module you should be able to do all that you can do with handlers, right???

  38. karl says:

    Chris:
    You can remap .HTML files to be processed by ASP.NET. I’d then use an HttpHandler to URL Rewrite to an aspx page (static.aspx) which has your master page. Before URL Rewriting, store the actual requested page in the Context.Items collection, which you can retrieve from static.aspx to fetch the right file to drop inside the content placeholder.

    The only problem with this approach is that it’ll apply this change to all .html files. Maybe you can rename them to ashx? Or use .htm so that you can still use .html…

  39. Chris W says:

    Great Article. I had one question that somewhat relates to Stuart’s question. I want to go about creating a custom handler that will take *.html (i do have access to IIS), find the existing .html static page, place the master page on it and then feed it to the user.

    The reason i want to do this is i am currently in the process of converting a static .html website to dynamic asp.net. However, not all pages will be static (most won’t be at the start) and they will feel more comfortable continuing to generate static pages in the future. My hope was i could create this handler so that they could continue to generate static, plain, html pages that will inherit the MasterPage automatically. They won’t even need to use Visual Studio this way.

    Please let me know if you think i am going about this wrong.

    Any help would be appreciated.

  40. karl says:

    Zidane:
    It sounds like you want to read in an RSS Feed into .NET. Take a look at
    http://www.rssdotnet.com/

    and

    http://scottonwriting.net/sowBlog/RssFeed.htm

  41. Zidane says:

    i want to access RSS xml generated successfully from .net code.
    when i acces it from xmlreader
    it give me some qouate error however file hav not any sysntax error as it is working when placed on local path.

    i try to use the application configuration in iss to mapp .aspx to .rss extension and Httphandlers
    i didnt get how to do this

  42. Kevin Dente says:

    Another limitation of HttpHandlers is that they don’t support the ASPCompat page attribute, which is key when interacting with legacy COM components.

  43. Meysam says:

    a newbie ? – problem with WebResource.axd >> maybe not entirely related to this post. anyway i don’t know why the server (on LOCAL (Development Server [internal VS2005 server] because after installing FrameWork2 my IIS5.1 doesn’t parse .aspx pages anymore!!) & tested on some free asp.net2 hosts) doesn’t inject the client scripts to the page needed to run functions like “WebForm_DoPostBackWithOptions” (but it injects Pictures like Minus & Plus used controls like TreeView). i googled & found that alot of people have the “no script injection by WebResource.axd” problem but no solution! any clue here ?

  44. karl says:

    Stuart: Not that I know of. It doesn’t make sense to do that anyways. The point of the HttpHandler is to be handle requests outside of the page framework. Master Pages are a part of the page framework – if you need them, you should just be using the default page handler.

  45. Stuart Snaddon says:

    I’ve written an HTTPHandler that ouputs some HTML content, just a few links and some contact details.
    Is it possible to use a MasterPage.master with the resulting HTML?

  46. Nice article.

    ELMAH rocks we have our own flavor that is used in every application and has proven so valuable we have created our own entlib application block with modules and handlers at the base.

    Another unused 2.0 feature: HEALTH MONITORING

  47. karl says:

    Paul, not 100% sure. I’ve given it a quick try on a simplified form and everything works aok…

    You should take a look at:
    http://codebetter.com/blogs/jeffrey.palermo/archive/2005/08/10/130532.aspx

    Also, is this converted from a 2003 project? Have you looked at the source code to see what javascript IS being generated by asp.net? Have you tried without cross-page posting (if you aren’t cross page posting, then you likely ARE converting from 2003 ‘cuz that can happen…)

    I’m still not sure I like the idea of using HttpHandlers for url rewriting. HttpModules seems better able to handle that…

  48. I was just wondering if this neat trick in ASP.Net 2.0:



    To force all documents to pass the authentication doesn’t also make it possible to let zip-files being passed through IIS and thus you own HttpHandler…

    Cheers,
    Wes

  49. Paul says:

    The other thing I should mention is that the following javascript is missing from the form tag through the httpheader, but is present when going directly to the page:

    onsubmit=”javascript:return WebForm_OnSubmit();”

  50. Paul says:

    I am in the process of trying to get a httphandler working for the purposes of URL re-writing. I have it to the point that it is successfully processing an aspx page and returning the html correctly, but not the scripts for postbacks. When viewing the headers using the ieHTTPHeaders utility, I find that when I view the target page directly, I see several headers such as the following that refer to WebResource.axd, but when looking at the source after re-writing through the httphandler, these are missing.

    GET /BrokerExtranet/WebResource.axd?d=PdBB8Jr4AQt4rLgwO2gTUA2&t=632737057228488874 HTTP/1.1
    Accept: */*
    Referer: http://test.pncs.com.au/BrokerExtranet/ExtranetLogin.aspx?PageId=87801FDC-9668-4d59-85D7-4D21A58ABE1F
    Accept-Language: en-au
    Accept-Encoding: gzip, deflate
    User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
    Host: test.pncs.com.au
    Connection: Keep-Alive
    Cookie: ASP.NET_SessionId=pozkme45kr1pob454owdjyis

    The end result is that trying to click my submit button I get the following error:

    Microsoft JScript runtime error: ‘WebForm_PostBackOptions’ is undefined

    with the code for my button:

    onclick=”javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("loginButton", "", true, "", "", false, false))”

    I have scoured the net and there are several references to this error being related to WebResource.axd, but none on how to solve the problem within a httphandler. Any help would be much appreciated!

  51. karl says:

    Travis:
    I probably gotta put HttpHandlers at, or very near, the top of the list. Quickly, others that come to mind (all of which I plan on blogging/writing about at some point) would be:

    -HttpModules
    -Custom Server Controls (we could lump in a lot of other OO features into that one)
    -Configuration sections
    -Event driven communication between pages/user controls
    -OnItemDataBound (less and less of an issue)
    -HttpContext.Current.Items

    I’m sure I could come up with some other big ones…

  52. Travis D. Falls says:

    “There are many features in ASP.NET that are unfortunately underused. Sometimes a feature gets looked over because it’s too complicated. Other times, like in the case of HttpHandlers, it’s because they are poorly understood.”

    What other features are you speaking of besides HTTPHandlers?

  53. karl says:

    Lee:
    If your challenge is unruly querystring’s, I think your best bet might be to use url rewriting in an HttpModule. Check out:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/urlrewriting.asp

    for more details.

  54. LeeB says:

    Hi, all very interesting this…and mind blowing at times for somebody new like me! Here’s my question…

    I’m trying to optimise my dynamic (.aspx) site for search engines and know there is a way on Apache servers of configuring the HTACCESS file to run one file type as another. This example I’ve been given is for processing PHP extensions as HTML…

    AddType application/x-httpd-php .htm
    AddType application/x-httpd-php .html

    I’ve read about how the web.config file and http handlers can be configured to map any file extension to the appropriate handler.

    My site has lots of query strings and dynamically called content which is bad for search engine rankings. If I can implement a solution to ensure search engine spiders see my pages as static html pages, it will give me great advantages. But I need to keep my dynamic methods.

    So my question is – can ASP.NET on IIS be configured to effectively process .ASPX pages as though they are .HTML?

  55. simone_b says:

    In my opinion using the Transfer method to switch the execution to a custom handler doesn’t make much sense. If you’re trying to implement a sort of url mapping then use url rewriting. Otherwise don’t do a Transfer but just make a new request either using a Redirect or a ChildRequest from the code.

  56. karl says:

    I was under the impression that you couldn’t Server.Transfer from one type of handler to another. Check out this link for some more insight on this.

  57. Manpreet says:

    OK.

    My Original web.config file had

    path="ajax/*.ashx"
    type="Ajax.PageHandlerFactory, Ajax">

    however when i was trying to use Server.Transfer it gave me error: “Error executing child request”. Which then made me add the other handler

    path="*/Reports/*.aspx"
    type="System.Web.UI.PageHandlerFactory">

    this made the Server.Transfer to work however it broke up something that was using the ajax handler..

    how can i get both to work.?

    please help.

  58. simone_b says:

    Manpreet, I think I can’t understand what you’re trying to achieve… .aspx files are already mapped to the PageHandlerFactory class, why are you trying to remap them?

    “when i remove the first one then my reports does not work as the page uses Server.Transfer and gives me an error – Error executing child request”

    What does this mean?

  59. Manpreet says:

    Hi Karl,

    I am trying to use http handlers but am really confused…

    i have put this in the web.config

    path="*/Reports/*.aspx"
    type="System.Web.UI.PageHandlerFactory">

    path="ajax/*.ashx"
    type="Ajax.PageHandlerFactory, Ajax">

    when this is the case my Ajax handler does not work…..
    when i remove the first one then my reports does not work as the page uses Server.Transfer and gives me an error – Error executing child request.

    how can i get both to work?
    any help would be greatly appreciated….

  60. Atif Aziz says:

    Regarding your closing comment…

    >>

    The biggest and very significant drawback of HttpHandlers is that they can only be used for extensions that are mapped to ASP.NET in IIS. It might be great to create a file download counter for your .zip files using an HttpHandler, but since IIS doesn’t go through ASP.NET to serve .zip files, it isn’t going to work. One solution is to map those extra extension to ASP.NET, but that might have undesirable side effects and might not even be possible for you (many developers don’t have direct access to IIS). In this case, the only solution is to create an ISAPI filter which is much more difficult.

    <<

    There’s an old trick that can really help in getting around this problem entirely and that is to rely on Request.PathInfo (a.k.a PATH_INFO server variable). What you need to do is generate a URL where your handler’s ASHX reference appears somewhere *before* the last component of the path. In other words, something like this:

    http://www.example.com/myhandler.ashx/report.zip

    That’s a perfectly valid URL. When it gets cracked on the server, however, your HTTP handler that is mapped to the path "myhandler.ashx" will get called back and Request.PathInfo will contain "/report.zip" as the remainder path. Now you can do what you like in your handler, such as make that counter bump up, do authorization checks or what have you. Once you’re ready to send down the ZIP file, just call Response.TransmitFile and IIS will take care of the rest. You could alternatively stream the resource down from a database if that’s where it resides. To finish up, your handler should also set two response headers, namely "Content-Type" and "Content-Disposition". Taking the URL example above, these would read "application/zip" and "attachment; file=report.zip" respectively. The second header tells the user-agent/browser that the response entity is like an e-mail attachment and, if saved to disk, should be given the file name report.zip. So it’s like doing a rename on the client file system from the server-side. That’s it. Hope this helps.

    BTW, Scott Mitchell and I wrote an MSDN article [1] some time ago on the same essence as your piece here. There’s even a complete sample in there called ELMAH [2] that demonstrates adding error logging to a running ASP.NET application using modules and handlers and a binary deployment model only. The idea of ELMAH was to provide a fairly real-world example rather than, as you put it so finely :), yet another shameful “hello world” one. You’ll also see a usage of Request.PathInfo in there (see ErrorLogPageFactory.cs if you’re interested) though not exactly in the same context as outlined above.

    [1] http://msdn.microsoft.com/library/en-us/dnaspp/html/elmah.asp

    [2] http://www.raboof.com/Projects/ELMAH/

  61. simone_b says:

    They are good for retrieving embedded resources too, especially when you have to do some work on them before to send them back through the pipeline, because the new ASP.NET 2.0 WebResource feature is not as flexible.

    I used this approach when building a web control library, to embed many Javascript scripts in one shot. The request is in the form:

    GET MyHandler.axd?q=script1.js$script2.js$scriptN.js

    This way I have been able to manage on the server-side the content to return, instead of writing a thousand times RegisterClientScriptResource, which in turn performs that thousand number of requests to the server (ok, it caches them…)

    In general, they are useful whenever you need to apply some personalization to the response sent to the client.

  62. btompkins says:

    Great post! I use handlers all the time. Very handy when working with non-html output.

  63. Good post. The lack of use of HttpHandlers (when appropriate) has always frustrated me. The Page class (.aspx) should only be used when you need the functionality it supplies (just like any class). Too many people do not know what is in their toolbox, so they use the same tool for every job. When you are just spitting out xml, or some binary data, or anything else that does not involve a tree of controls w/events/postback behavior, you should choose an HttpHandler over a Page.
    Finding Response.Write in a Page derived class is a good sign you should be using an HttpHandler instead (or studying up on ASP.NET’s use of Controls).

  64. Alfred Hitchcock says:

    We use them to prevent unauthorised access to the attachments on our site. I would have used an ISAPI filter but lifes a bit too short for that sort of thing :)

  65. We have a system that serves up different pages and one thing that we also did was create our own PageHandlerFactory that uses the PageParser.GetCompiledPageInstance which allows us to have different page instances based on particular master pages. What you basically end up with is a completely blank instance of the Page class and you can add a bunch of content controls to the Controls collection.

  66. karl says:

    Thanks for the example Jeff.

    I forgot the “IsReusable” property of the IHttpHandler…This tells ASP.NET whether an instance can be reused for another request. To be honest, I’m not 100% sure what determines whether you should return true or false. I’ve always read that you can generally return true. I assume you should only return false (like the Page class does) if you’re instance is pretty much becomes garbage after a single execution (an example that pops in my mind is if you also implement IDisposable or something)

  67. If you use the .ashx extension you are not required to register a new extension to asp.net. We use this extensively for our graphics such as .gif/.png/.jpg.

    Whenever we render a link to a graphic we append .ashx to the file path of the image. This allows us to do things like pass in a width and do a dynamic resize on that image.

    You just need to create an ashx file with the following at the top:

    < %@ WebHandler Language="C#" Class="StyleSheetHandler" %>

    Then just add a class like this:

    public class StyleSheetHandler : IHttpHandler
    {

    public void ProcessRequest(HttpContext context)
    {
    context.Response.Write(“Test”)
    }

    public bool IsReusable
    {
    get { return true; }
    }

    }

    This allows you to get around the pesky “extension register” on my hosts.

  68. karl says:

    uhhmm…not sure if I expected my formatted code to show up perfectly or not…