An image is now worth two thousand HTML tags [How to: Use ASP.NET's IHttpHandler interface to display a custom image]
In a previous post, I referred to some MSDN sample code and outlined the process of creating an ASP.NET page to display an image instead of HTML. As is often the case, the relevant sample code was written to demonstrate a concept rather than to be "production-ready". In one of the comments for that post, Heath Stewart suggested the use of a .ashx file as a more efficient way to do the same thing. This seems like a great opportunity to learn a little more about ASP.NET, so let's give it a try!
First, a little research is in order - I recommend starting with the documentation for Creating HttpHandlers and following up by learning a little about the corresponding IHttpHandler Interface. Armed with that knowledge, we should be able to convert the modified sample code over to the IHttpHandler interface.
Begin by creating a new file in the web site directory you were already using. I used Visual Studio's "Add New Item" action to add a "Generic Handler" page that was automatically named Handler.ashx. I then pasted in the existing code from my earlier post, tweaked a few minor things, and had a working IHttpHandler in considerably less time than it's taken me to write this post. :)
Here's what I ended up with in my Handler.ashx:
<%@ WebHandler Language="C#" Class="Handler" %> using System.Drawing; using System.Drawing.Imaging; using System.Web; public class Handler : IHttpHandler { public void ProcessRequest(HttpContext context) { // Set the page's content type to JPEG files context.Response.ContentType = "image/jpeg"; // Create integer variables. int height = 100; int width = 200; // ... // Create a bitmap and use it to create a // Graphics object. using (Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb)) { using (Graphics g = Graphics.FromImage(bmp)) { // ... g.Clear(Color.LightGray); // ... } // Save the bitmap to the response stream and // convert it to JPEG format. bmp.Save(context.Response.OutputStream, ImageFormat.Jpeg); } } public bool IsReusable { get { return true; } } }
As you can see, the code is almost identical to the initial Page-based implementation! The only thing I think is worth calling out is that I've chosen to return "true" for the IsReusable property. The documentation for the IHttpHandler.IsReusable Property suggests that this property can be used to prevent concurrent use of the instance. Since our simple implementation doesn't make use of any global state, it should be safely reentrant, and therefore returns "true" to help ASP.NET avoid creating unnecessary instances of the class.
There you have it: a simple change that gives us an implementation consuming fewer resources and consequently scaling better on a busy web server. Thanks for the great suggestion, Heath!!