free geoip HttpHandler Custom ISAPI Extension Mapping - Jayson's Blog - jaysonKnight.com
jaysonKnight.com
Welcome to my corner of the internet
HttpHandler Custom ISAPI Extension Mapping

one of the great things about IIS on windows is the pluggable architecture for supplying your own http handlers to intercept page requests from your web server...if you wanted to, you could write your own parsing routines from the ground up and implement them as an ISAPI filter, then map page extensions to that filter.  one of the bad things about this (pre .Net) is that you had to have a very intricate knowledge of IIS, C++, and ATL (active template library).  ATL is a pretty arcane API into IIS for ISAPI stuff, and i personally don't know anyone who has tried to roll their own filters from scratch.  that being said, .Net makes this task infinitely more palatable with the introduction of the IHttpHandler interface located in the System.Web namespace.  the interface consists of two members, a bool property IsReusable, and a ProcessRequest method that takes an HttpContext parameter and returns void. 

when i got punked by microsoft, i needed to come up with a way to keep the name of the link (which was directly to the .rar file, when you navigate to a file with this extension IE will attempt to download the .rar file, if there isn't one there, you will get a 404 error) the same, however not have it download the .rar file.  so of course what better solution than to roll my own parser and map it to .rar extension for that particular web directory (this is not a global change, only directory specific).  to implement this functionality, there are 3 steps that need to be taken:

  1. create a class that derives from IHttpHandler and override the 2 members
  2. add an httpHandlers section in the web.config file that specifies the file extension to map to the type created above, as well as the type and assembly name
  3. modify the settings in the IIS MMC snap-in to map requests for the file extension to the aspnet_isapi.dll library (unless you really want to write your own).

the solution i wrote is an overly simplified example of what you can do with this technology.  in my override of ProcessRequest i simply call Response.Write method of the HttpContext object that is implicitely passed in by IIS when it process any file with the file extension you specify, and in this case it simply says “i got punked by MS”.  ultimately i will have something a bit more clever posted (when i have the time to actually think about it).  here is what the httpHandlers section looks like in the web.config file:

<httpHandlers>

      <add verb="*" path="*.rar" type="WebLogger.PunkedHandler.Punked, WebLogger.PunkedHandler" />

httpHandlers>

here is the class implementing this:

 

using System;

using System.IO;

using System.Web;

using System.Web.UI;

 

 

namespace WebLogger.PunkedHandler

{

      ///

      /// I got punked by Microsoft for my X# demo

      ///

      public class Punked : IHttpHandler

      {

            private const string link = "http://jaysonknight.com/blog/archive/2004/01/13/205.aspx";

           

            #region IHttpHandler Members

 

            ///

            /// Method called automatically by IIS when a request to the file extension mapped to this type in the web.config file

            ///

            /// Intrinsic HttpContext object associated with this request

           

            public void ProcessRequest(HttpContext context)

            {

                  // instantiate the user control

                  PunkedControl lst = new PunkedControl(link);

                 

                  // new stringwriter object

                  using (StringWriter textWriter = new StringWriter())

                  {

                        // new htmlwriter object

                        using (HtmlTextWriter writer = new HtmlTextWriter(textWriter))

                        {

                              // render the control

                              lst.RenderControl(writer);

 

                              // flush the response to the client

                              context.Response.Write(textWriter.ToString());

                        }

                  }

            }

 

            ///

            /// Specifies whether this instance is reusable by other Http requests

            ///

            public bool IsReusable

            {

                  get

                  {

                        return true;

                  }

            }

 

            #endregion

      }

}

 

and here is the custom user control used to output the html stream back to the client:

 

using System;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

 

namespace WebLogger.PunkedHandler

{

      ///

      /// User Control to output an Html stream to the client

      ///

      public class PunkedControl : WebControl

      {

            private string _link;

           

            ///

            /// Overloaded constructor for PunkedControl

            ///

            /// The page to link to

            public PunkedControl(string linkTo)

            {

                  // the page to link to

                  _link = linkTo;

            }

 

            ///

            /// Method called when the control starts to render

            ///

            /// HmtlWriter object to output an Html stream to the client

            protected override void Render(HtmlTextWriter writer)

            {

                  // I

                  writer.Write("I");

                  // space

                  writer.WriteLine(HtmlTextWriter.SpaceChar);

                  // begin an anchor tag

                  writer.WriteBeginTag("a");

                  // specify the value for the href attribute

                  writer.WriteAttribute("href", _link);

                  // closing whicket

                  writer.Write(HtmlTextWriter.TagRightChar);

                  // got punked

                  writer.Write("got punked");

                  // close the anchor tag

                  writer.WriteEndTag("a");

                  // space

                  writer.Write(HtmlTextWriter.SpaceChar);

                  // by MS

                  writer.Write("by MS");

            }

      }

}

 

all that's left to do now is add a mapping in IIS.  if you right click a virtual directory and go to properties, click on configuration, click on add, then browse to \%system%\microsoft.net\framework\[version]\aspnet_isapi.dll for the executable (we still want the ASP.NET runtime to handle the low level stuff), type in .rar for the extension, specificy the http verbs to handle (in this case GET would suffice), and clear the “check that file exists“ checkbox (in our web.config file we specified *.rar, so you could actually go to jaysonknight.com/blog/misc/[any file name whatsoever].rar, if you leave that checkbox checked and the file isn't really there, you'll get a 404...in this case i actually did remove the .rar file, but we've tricked IIS into thinking it's still there and behaving as an .aspx page).  Build it, and you're off to the races!

 

this has been an extremely high level look at how a custom HttpHandler works in .Net...a couple of people had emailed me asking how i kept the same link to the .rar file, but it displayed as any other web page would without prompting for a download of a file that isn't even there anymore.

 

happy coding


Posted Thu, Jan 15 2004 3:42 PM by Jayson Knight

Comments

eComTim wrote re: HttpHandler Custom ISAPI Extension Mapping
on Mon, Feb 23 2004 10:47 PM
This is really powerful stuff. The problem I've run into is that I don't know how to add the mapping to my handler in IIS in the Install script. It appears that I can do so in a web app setup but I need to deploy the dll to which i am mapping. In your example (and mine), i'm mapping to a framework file (aspnet_isapi.dll) which I don't want to deploy. Is there any way to script the creation of the mapping to this existing file?

thanks

tvanhammond@edci.com
Parthiv Joshi wrote re: HttpHandler Custom ISAPI Extension Mapping
on Thu, Aug 5 2004 11:47 AM
I have ISAPI extension DLL which I use to call from an ASP page. Now can I can not call the same DLL from ASP.NET page. So what I need to change for that. Can you help me ??
Parthiv Joshi wrote re: HttpHandler Custom ISAPI Extension Mapping
on Thu, Aug 5 2004 11:48 AM
I have ISAPI extension DLL which I use to call from an ASP page. Now can I can not call the same DLL from ASP.NET page. So what I need to change for that. Can you help me ??
jayson knight wrote re: HttpHandler Custom ISAPI Extension Mapping
on Thu, Aug 5 2004 6:44 PM
can you provide more details, i.e. what exactly does the extension do? how are you attempting to call it? etc.

thanks
jayson
Bruno wrote re: HttpHandler Custom ISAPI Extension Mapping
on Sun, Aug 8 2004 1:19 AM
how to do that if my site is hosted in a hosting company?
jayson knight wrote re: HttpHandler Custom ISAPI Extension Mapping
on Mon, Aug 9 2004 8:22 AM
you have to request this from your ISP, and they may have policies against this. what exactly are you attempting?
Rüya tabirleri wrote re: HttpHandler Custom ISAPI Extension Mapping
on Thu, May 14 2009 1:33 AM

Thanks for your comment!

Add a Comment

(optional)  
(optional)
(required)  
Remember Me?

Copyright © :: JaysonKnight.com
External Content © :: Respective Authors

Terms of Service/Privacy Policy