Grabbing a StaticFileHandler RRS feed

  • Question

  • User-1029435529 posted
    <color="#000000;width:550px;">My website serves three different kinds of GIF images. 1) Static .gif files existing in the file system. 2) Dynamic .gif files created via System.Drawing classes. 3) Resource .gif file served directly from assemblies. For the last two types, I have created a custom HttpHandler. They work fine. In my web.config, I have specified that requests for a .gif file are mapped to my own GifHandlerFactory. It returns the necessary HttpHandler, following some logic to determine which of the three types of GIF is being requested. If the logic determines that it's just a .gif file sitting in the file system, I would like to use the System.Web.StaticFileHandler. However, this is an internal class that I cannot access. Is there any indirect way of grabbing a StaticFileHandler?</color>
    Friday, December 17, 2004 11:00 AM

All replies

  • User-1029435529 posted
    <color="#000000;width:550px;">I ended up writing my own StaticFileHandler. Still, if anyone has previously found an indirect way of grabbing the ASP.NET's built-in StaticFileHandler, I'm interested to hear of their technique.</color>
    Saturday, December 18, 2004 1:00 PM
  • User-2116183294 posted

    Yes, there is a way that may work. I have not implemented it, so let me know if you get it to work.

    To begin, use a IHttpHandlerFactory to serve any GIF files. Ensure your factory decides which handler to use based on the physical location of the GIF resource. (Don't forget to cache the handler instances if the handlers are IsReusable == true.) It should be easy for you to select the right handler in the cases in which the GIF is non static.

    If a request for a static GIF occurs, then we're missing a few moving parts. Do the following:

    1. Ensure that, in Web.config, you've added System.Web.StaticFileHandler for resources matching *.nonexistent.

    2. Ensure you've created a custom IHttpModule and enabled it in your Web.config. Modules oversee all requests to your application and this specific module will help get you an instance of System.Web.StaticFileHandler when a call to a *.nonexistent resource occurs, as will become apparent in step 4.

    3. Back to our request for a GIF that would be served from a static file. When such a request occurs, your handler factory should first make an internal HTTP call to a *.nonexistent resource. (A synchronous call, of course.) The resource will not exist (see next step) so be prepared to handle the error (and swallow it, as it's no use even in the logs; but do be specific about which error you swallow so you don't get burnt - HTTP 404).

    4. In the custom IHttpModule (now activated indirectly by the internal call), detect the call for a *.nonexistent resource and retrieve the configured handler from the context. The handler is available to certain IHttpModule methods from somewhere inside the HttpContext. Google it, I don't know it by heart. Once you get the handler, which just so happens to be a StaticFileHandler (yippie!), serve it to the IHttpHandlerFactory instance, whether directly or through some shared location. Because StaticFileHandler may not be reentrant (and not even reusable), return a 404 immediately instead of letting the request go through to the handler. That way, you ensure it's the IHttpHandlerFactory that will first use the handler.

    5. Back in the handler factory, use the saved StaticFileHandler as handler for the GIF request.

    6. Optionally (but desirably), use the memoized result on all future calls to your handler factory.

    If you decide to memoize, then you need to be sure System.Web.StaticFileHandler is reentrant. If you've inferred that System.Web.StaticFileHandler is reentrant, then, in the interest of simplicity and uniformity, you can modify step 4 allowing the request to go to the handler (which will ultimately return a 404 itself).

    Don't forget that the module gets invoked for all requests, so it will need to store handlers only for *.nonexistent resources. If StaticFileHandler is reentrant (and therefore only needs to be retrieved once), then you might want to deactivate the module once you got the instance by unsubscribing from the events. ;)

    It's sad they weren't smart about enabling reuse of their code, innit? I'm still struggling with this, because I want to capture not just *.gif, but pretty much all the calls. Perhaps there's a way for me to swap handlers from within a HTTP module.

    If not that, then perhaps I can play with the handler priorities in Web.config and force StaticFileHandler over my catch-all handler with the downside of having to re-enumerate all those static resources. Bleh.

    As I said, the approach is untested. If you test it successfully, let me know.

    Good luck.

    Mihai Danila

    Wednesday, September 9, 2009 8:14 AM