【问题标题】:Make an asp.net subapp handle file requests instead of IIS使 asp.net 子应用程序处理文件请求而不是 IIS
【发布时间】:2015-07-08 16:27:40
【问题描述】:

我编写了一个 asp.net 应用程序,当找到与请求 url 匹配的文件时,它应该什么都不做,但是当文件不存在时,它会生成(基于在 url 中找到的某些信息)和然后用户被重定向到现在存在的文件(相同的 url)。我在global.asax 中使用Application_Error 实现了它,它在本地按预期工作,但在远程服务器上不起作用(它作为应用程序添加到MVC 应用程序中)。我知道问题在于 IIS 处理远程服务器上的文件请求,但我不知道如何让它不处理这些请求。我只需要 asp.net 子应用程序在它自己的范围(路径)内处理这些文件请求,但在其他地方继续使用 IIS(父 MVC 应用程序,子应用程序的路径除外)。那么我该怎么做(我在另一个 MVC 应用程序中看到过这个工作,但我不确定是什么让它工作)?

我尝试将应用程序池切换为经典应用程序池并更改 IIS 和 web.config 中的处理程序映射,但都没有成功。我还找到了有关在 asp.net 中制作看起来像静态文件的路由的信息,但据我了解,即使相应的文件存在,这些路由也会处理请求,所以这不是我所需要的。

【问题讨论】:

  • 您应该使用集成模式并编写一个 HTTP 模块来处理它,而不是使用错误事件。错误事件仅针对 ASP.NET 请求,在 IIS 处理静态文件请求时不起作用。
  • 您还需要为所有请求启用此托管模块。
  • @LexLi 经过大量试验和错误后,我发现最好的两个解决方案是使用httpError 页面(请参阅答案)并编写一个 http 处理程序。第一个不适用于子应用程序,所以我使用了第二个。使用 http 模块看起来是个好主意,但由于各种原因,它们不适用于静态文件。为了让它工作,我必须编写自己的静态文件处理程序,这会使模块变得多余。我们大概可以删除这个问题之前的cmets。

标签: c# asp.net iis


【解决方案1】:

花了两天时间解决这个问题后,我发现:

<system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
</system.webServer>

应该可以实现结果(如果我想在 global.asax 中使用Application_Error),但我猜测父站点也需要将此选项设置为 true。

由于我无法使其工作,我尝试了错误处理HttpModule 的运气,但StaticFile 处理程序似乎在处理静态文件上的错误方面胜过我,所以这也不起作用。

我试图用 HttpError 页面解决这个问题

<system.webServer>
    <httpErrors>
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" prefixLanguageFilePath="" path="/Error404.aspx" responseMode="ExecuteURL" />
    </httpErrors>
</system.webServer>

这很好用,因为ExecuteURL 会导致重写而不是重定向。我不必以任何方式劫持标准文件处理,我可以在文件丢失时执行我的代码(我把它放在 aspx.cs 文件的Page_Load 中)。此解决方案存在一个问题,它仅适用于单个应用程序池。如果您的子应用程序在不同的应用程序池中运行,则在子应用程序内的错误上使用ExecuteURL 将导致空白 403 错误(重定向到错误页面确实有效,但不是我想要的)。子应用背后的想法不是修改父站点(实际上是站点),所以这也是不行的。

最后,我为静态文件(仅 jpeg)编写了一个处理程序,并且效果很好。我什至不需要将runAllManagedModulesForAllRequests 设置为true。我唯一担心的是它的性能可能不如常规的StaticFile 处理程序。

public class JpegHandler : IHttpHandler
{
    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        var url = context.Request.Url.PathAndQuery;
        var path = context.Server.MapPath(url);
        try
        {
            if (File.Exists(path) || TryRecreateFile(url)) // TryRecreateFile attempts to create the file and if it succeeds, it returns true
            {
                context.Response.Clear();
                context.Response.ContentType = "image/jpeg";
                context.Response.TransmitFile(path);
                //Response.End(); // TransmitFile already Ends the response
                return;
            }
        }
        catch (Exception ex)
        {
            context.Response.StatusCode = 500;

            Logger.LogException(ex);
            return;
        }

        context.Response.StatusCode = 404;
    }
}

在 web.config 中:

<system.webServer>
  <handlers>
    <add name="jpgs" path="*.jpg" verb="GET" type="JpegHandler" resourceType="Unspecified" preCondition="integratedMode" />
  </handlers>
</system.webServer>

【讨论】:

    猜你喜欢
    • 2020-07-28
    • 2022-11-14
    • 1970-01-01
    • 2012-09-23
    • 1970-01-01
    • 2017-12-11
    • 2021-10-25
    • 2012-10-10
    相关资源
    最近更新 更多