【问题标题】:HttpHandler fire only if file doesn't existHttpHandler 仅在文件不存在时触发
【发布时间】:2011-01-17 04:23:15
【问题描述】:

我正在尝试创建一个 HTTP 处理程序来处理对文件夹的所有请求,但我只希望它在请求的文件不存在时触发(例如:请求进入文件 X,如果 X 存在,我会喜欢提供文件,否则处理程序应该处理它)。

这些文件将只是静态内容,而不是脚本本身,我认为这会使其更容易一些,但我似乎找不到任何可以解决问题的东西......有人有什么想法吗?我认为它可以完成,因为 IIS7 重写模块可以管理它,但我看不到如何......

编辑只是为了澄清......处理程序是典型的情况,它不是错误处理例程,而是实际提供适当的内容。我只是希望能够将新文件作为单独的东西添加到文件夹中,或者作为处理程序将交付的内容的重载。

【问题讨论】:

  • 回答中的工作代码示例。
  • 你试过<add verb="*" path="path/" ... 吗?它仅在文件不存在时调用?我没有尝试过处理无法提供的文件

标签: c# asp.net iis-7 httphandler


【解决方案1】:

我最终坚持使用处理程序,而是使用以下方法来解决问题:

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

鉴于这么多人提倡模块和捕获异常,我觉得我应该澄清我为什么不听:

  1. 这是标准程序流程,因此除非绝对必要,否则我不喜欢使用异常来触发它的想法。
  2. 这实际上是正常情况下返回的内容。 HttpModule 实际处理典型请求而不是仅仅进行一些基本的共享处理和处理边缘情况的想法似乎有点偏离。因此,我更喜欢使用 HttpHandler 来处理典型的请求。

【讨论】:

  • 很公平——我的深夜意识流答案是基于 A)。已经利用现有的全局异常处理程序完成了此操作,并且 B)。针对文件确实存在的情况进行优化。我认为你有正确的方法来优化 404 案例。
  • 对于我们其他人来说,@annakata,你的答案去哪儿了? :(
  • 我记得 annakata 的解决方案与下面的 Sky Sanders 解决方案非常相似。那是在文件不存在时使用 HttpModule 接管处理,而不是使用处理这两种情况的 HttpHandler 。对于特定应用程序来说,哪个更好确实归结为更准确地反映了真正的设计意图(我推荐处理程序的情况来自我的答案中的两个点)。
【解决方案2】:

您可能想要实现一个 HttpModule。否则,您将与所有其他争夺请求的 HttpHandlers 争吵。

这应该让你开始......

您可以决定要在请求生命周期的哪个位置执行检查和响应。请参阅 this article 了解一些背景

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>

【讨论】:

    【解决方案3】:

    如果您不想创建 HttpModule,我可以想到两个 hack:

    1. 在 Apache 上使用 mod-rewrite 或在 IIS 上使用 II7 rewrite 之类的东西,以允许存在的特定 URL 通过、获取其他任何内容并将其重定向到您的静态文件。这可能是一个很大的列表,我只建议您只有少量文件时才实施此 hack。
    2. 更改您的 URL 结构以支持路由脚本,该脚本可以检查文件是否存在并在适当时返回它。这种方法可能会影响缓存,因此请谨慎使用。

    雅各布

    【讨论】:

      猜你喜欢
      • 2010-11-29
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-13
      相关资源
      最近更新 更多