简体   繁体   English

使asp.net子应用程序处理文件请求而不是IIS

[英]Make an asp.net subapp handle file requests instead of IIS

I wrote an asp.net app that is supposed to do nothing at all when a file matching the request url is found, but when a file is not there, it gets generated (based on certain information found in the url) and then the user is redirected to the now existing file (same url). 我编写了一个asp.net应用程序,当找到与请求URL匹配的文件时,它应该什么都不做,但是当文件不存在时,它就会生成(基于URL中找到的某些信息),然后用户重定向到现有文件(相同的URL)。 I implemented it using Application_Error in global.asax and it works as intended locally, but doesn't work on remote server (where it is added as an app within an MVC application). 我在global.asax使用Application_Error实现了它,它在本地可以正常工作,但在远程服务器(在MVC应用程序中作为应用程序添加到远程服务器)上不起作用。 I know the problem lies with IIS handling file requests on remote server, but I don't know how to make it not handle those. 我知道问题在于IIS处理远程服务器上的文件请求,但是我不知道如何使它不处理那些请求。 I just need the asp.net subapp to handle those file requests within it's own scope (path), but keep using IIS elsewhere (parent MVC app with the exception of subapp's path). 我只需要asp.net子应用程序在它自己的作用域(路径)内处理这些文件请求,但是在其他地方(子应用程序路径除外的父MVC应用程序)继续使用IIS。 So how do I do this (I've seen this work in another MVC app, but I'm not sure what made it work)? 那么,我该如何做(我已经在另一个MVC应用程序中看到了这项工作,但是我不确定是什么使它起作用了)?

I've tried switching app pool to classic and altering handler mappings in both IIS and web.config, but neither did the trick. 我尝试过将应用程序池切换为经典,并在IIS和web.config中都更改了处理程序映射,但都没有成功。 I also found information on making routes that look like static files in asp.net, but from what I understand, those handle requests even if the corresponding file exists, so it's not quite what I need. 我还发现了有关在asp.net中制作类似于静态文件的路由的信息,但是据我了解,即使存在相应的文件,这些路由也可以处理请求,所以这不是我所需要的。

After spending two days on the problem I found out that: 在问题上花了两天后,我发现:

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

Should achieve the result (if I want to use Application_Error in global.asax), but I'm guessing that the parent site needs this option to be set true too. 应该可以达到结果(如果我想在global.asax中使用Application_Error ),但是我猜测父站点也需要将此选项设置为true。

Since I wasn't able to make it work, I tried my luck with error handling HttpModule , but StaticFile handler seems to beat me to handling errors on static files, so that didn't work either. 由于我无法使其正常运行,所以我尝试了使用HttpModule错误处理的运气,但是StaticFile处理程序似乎让我无法处理静态文件上的错误,因此也无法正常工作。

I tried to solve this with HttpError pages 我试图用HttpError页面解决此问题

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

and this works good because the ExecuteURL causes a rewrite rather then redirect. 这很有效,因为ExecuteURL会导致重写而不是重定向。 I don't have to hijack standard file handling in any way and I can just execute my code (I put it in Page_Load of the aspx.cs file) when the file is missing. 我不需要以任何方式劫持标准文件,当文件丢失时,我可以执行我的代码(将其放在aspx.cs文件的Page_Load中)。 There is one problem with this solution, it only works for a single app pool. 该解决方案存在一个问题,它仅适用于单个应用程序池。 If your subapp is running in a different app pool, using ExecuteURL on errors inside the subapp will lead to blank 403 errors (redirecting to errors pages does works, but is not what I wanted). 如果您的子应用程序在其他应用程序池中运行,则对子应用程序内部的错误使用ExecuteURL会导致出现空白403错误(重定向到错误页面确实可以,但不是我想要的)。 The idea behind the subapp was not to modify the parent site (actually sites), so this is a no go too. 子应用程序背后的想法是不修改父站点(实际上是站点),所以这也是不可行的。

In the end I wrote a handler for static files (only jpeg) and this works fine. 最后,我为静态文件(仅jpeg)编写了一个处理程序,并且工作正常。 I don't even need to set runAllManagedModulesForAllRequests to true. 我什至不需要将runAllManagedModulesForAllRequests设置为true。 My only concern is that it probably doesn't preform as well as the regular StaticFile handler. 我唯一关心的是它可能不像常规的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;
    }
}

In web.config: 在web.config中:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM