Last post Sep 09, 2009 08:14 AM by mstratus
Dec 17, 2004 11:00 AM|SomeNewKid|LINK
Dec 18, 2004 01:00 PM|SomeNewKid|LINK
Sep 09, 2009 08:14 AM|mstratus|LINK
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.