Scott Hanselman

A Boilerplate HttpHandler

March 17, 2005 Comment on this post [8] Posted in ASP.NET | HttpHandler
Sponsored By

I've been writing HttpHandlers lately for such things as Check Images and Statement Downloads. Remember, an HttpHandler is the kind of thing you want to use when an HttpRequest is going to return a file or image to the browser. Basically anything other than a standard page. True, you could use a page, remove all the HTML from the ASPX part, and return stuff in Page_Load, but that's not really what pages are for, right? Also, Pages are themselves an HttpHandler (returned by PageHandlerFactory) so why not write your own HttpHandler?

Here's a boilerplate template I like to use for an HttpHandler. IMHO, an HttpHandler should always return appropriate HTTP Status Codes like you see below. Make sure the semantics of the status code(s) you choose match what you're trying to express. 404 for Not Found, 403 for Forbidden, 500 for Holy Crap!, etc.

One day I'll be more organized and make an abstract base class to handle this kind of boilerplate stuff. For now, it's on my blog.

    1 public class MyHandler : IHttpHandler

    2 {

    3     private const string CONSTSOMEPARAM = "SomeParam";


    5     public MyHandler(){}


    7     public void ProcessRequest(HttpContext context)

    8     {

    9         // Don't allow this response to be cached by the browser.

   10         // Note, you MIGHT want to allow it to be cached, depending on what you're doing.

   11         context.Response.Cache.SetCacheability(HttpCacheability.NoCache);

   12         context.Response.Cache.SetNoStore();

   13         context.Response.Cache.SetExpires(DateTime.MinValue);


   15         if (ValidateParameters(context) == false)

   16         {   

   17             //Internal Server Error

   18             context.Response.StatusCode = 500;

   19             context.Response.End();

   20             return;

   21         }


   23         if (context.User.Identity.IsAuthenticated == false)

   24         {

   25             //Forbidden

   26             context.Response.StatusCode = 403;

   27             context.Response.End();

   28             return;

   29         }


   31         string someParam = context.Request.QueryString[CONSTSOMEPARAM];


   33         SomethingReponse response = SomeService.SomeImportantThing(someParam);

   34         if(response.Header == null || response.Header.Success == false)

   35         {

   36             //Whatever wasn't found

   37             context.Response.StatusCode = 404;

   38             context.Response.End();

   39             return;

   40         }


   42         context.Response.ContentType = "somespecific/mimetype";


   44         context.Response.BinaryWrite();

   45         //or

   46         context.Response.Write();

   47         //or

   48         context.Response.WriteFile();

   49         //or

   50         someImageStream.Save(context.Response.OutputStream);

   51     }


   53     public bool ValidateParameters(HttpContext context)

   54     {

   55         //Validate some stuff...true if cool, false if not

   56         return false;

   57     }


   59     /// <summary>

   60     /// True if this handler can be reused between calls. That's cool if you don't have any class instance data.

   61     /// False if you'd rather get a fresh one.

   62     /// </summary>

   63     public bool IsReusable

   64     {

   65         get

   66         {

   67             return true;

   68         }

   69     }

   70 }

HttpHandlers are nice because their endpoint (fancy word for URL) is configurable in your web.config.

   <add verb="GET,POST,WHATEVER" path="SomeEndPoint.ashx" type="MyNamespace.MtHandler, MyAssemblyName" />



About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Hosting By
Hosted in an Azure App Service
March 17, 2005 2:56

How do you generate the pretty code blocks in your posts?


March 17, 2005 2:59
I use CopySourceAsHtml
March 17, 2005 4:15

I have been doing a bit with Handlers and enjoyed reading your post. Have you ever used:

<%@ WebHandler Class="ContentWeb.Content" %>

inside of an .ashx file. Where "ContentWeb.Content" is the of you class. No need to create an entry in the config file.

March 17, 2005 4:18
Andrew, that's true. I don't usually use ASHX files because:

* To change the endpoint, you have to rename the file.
* They don't compile until you hit them
* No easy syntax highlighting
* They expose your source if you deploy them outside your company

But they are nice for quick-and-dirty stuff.
March 18, 2005 4:16
Hey Scott, I happened to have an abstract base Handler laying around I incorporated what you did.

As for ASHX, you can choose to put the code in an entirely separate .cs file and only have the &lt;WebHandler&gt; declaration in your .ashx file. That addresses the concerns you listed.

I generally use .ashx in all cases except when the file extension is important (for example, if I need to handle any url for a particular file type).
March 18, 2005 4:17
P.S, if I try to post HTML in here, I get an ugly exception about potentially dangerous script. I thought your blog might be HTML encoding html in here.
March 21, 2005 11:10
Does anyone have ANY clue on how to remove those, and also the httpmodule handlers, in directories below the one you configured this in?

I use a CLEAR tag (or something like it) and also multiple remove verb, but nothing works. It's a problem with my .Text and any other applications under it, trying to look for the .Text httpmodule assembly, which is obviously not in their own /bin/ directory.
December 06, 2005 20:29

I'm having trouble with showing a 404 error page. Using exactly the same code. All I get is a blank page. Anyone else had this problem and know how to fix it?????


Comments are closed.

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.