views:

253

answers:

3

Hey,

I'm trying to create a HTTP handler to handle all requests to a folder but I only want it to fire if the files requested don't exist (EG: Request comes in for file X, if X exists I'd like to serve the file, otherwise the handler should deal with it).

The files will only be static content, not scripts themselves, which I assume makes it a bit easier but I can't seem to find anything that will do the trick... Anyone have any ideas? I assume it can be done since the IIS7 rewrite module can manage it, but I can't see how...

Edit Just to clarify... the handler is the typical case and it is not an error-handling routine but actually delivering appropriate content. I just want the ability to add new files to the folder either as separate things or as overloads to what the handler would deliver.

+3  A: 

Probably you would want to implement an HttpModule. Otherwise you are fighting with all the other HttpHandlers that are vying for the request.

This should get you started....

You can decide where in the request lifecycle you want to perform your check and react. See this article for some background

using System;
using System.IO;
using System.Web;

namespace RequestFilterModuleTest
{
    public class RequestFilterModule : IHttpModule
    {
        #region Implementation of IHttpModule

        /// <summary>
        /// Initializes a module and prepares it to handle requests.
        /// </summary>
        /// <param name="context">
        /// An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods, 
        /// properties, and events common to all application objects within an ASP.NET application 
        /// </param>
        public void Init(HttpApplication context)
        {
            context.BeginRequest += ContextBeginRequest;
        }

        /// <summary>
        /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
        /// </summary>
        public void Dispose()
        {
        }

        private static void ContextBeginRequest(object sender, EventArgs e)
        {
            var context = (HttpApplication) sender;

            // this is the file in question
            string requestPhysicalPath = context.Request.PhysicalPath;

            if (File.Exists(requestPhysicalPath))
            {
                return;
            }

            // file does not exist. do something interesting here.....
        }

        #endregion
    }
}

<?xml version="1.0"?>
<configuration>
    ...............................
    <system.web>
    ...........................
        <httpModules>
            <add name="RequestFilterModule" type="RequestFilterModuleTest.RequestFilterModule"/>
            <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        </httpModules>
    </system.web>
    ...................
</configuration>
Sky Sanders
A: 

If you would prefer to not create an HttpModule, I can think of two hacks:

  1. Use something like mod-rewrite on Apache or II7 rewrite on IIS to allow specific URLs that exist to go through, take anything else and redirect it to your static file. This could be a large list and I would only recommend implementing this hack if you only have a small number of files.
  2. Change your URL structure to support a routing script that can check to see if the file exists and return it when appropriate. This approach will likely affect caching, so please use caution.

Jacob

TheJacobTaylor
+3  A: 

I've ended up sticking with a handler and instead using the following to solve the problem:

if (File.Exists(context.Request.PhysicalPath)) context.Response.TransmitFile(context.Request.PhysicalPath);
else { /* Standard handling */ }

Given so many people advocated Modules and catching exceptions I feel I should clarify why I didn't listen:

  1. This is standard program flow, as such I don't like the idea of using an exception to trigger it unless it becomes absolutely necessary.
  2. This is actually returning content under normal circumstances. The idea of a HttpModule actually handling typical requests rather than just doing some basic shared processing and handling edge-cases seems a bit off. As such I prefer to use a HttpHandler as it is handling the typical requests.
Tim Schneider
Fair enough - my late-night-stream-of-consciousness answer was based on having A). already done this leveraging an extant global exception handler, and B). optimising for the case where the file *does* exist. I think you have the right approach where you want to optimise for the 404 case.
annakata