ASP.NET MVC:IIS何时返回404错误,何时将其转发到我的应用程序?

3
我对以下内容产生了疑问:
我可以在IIS中定义如何处理“页面未找到/404”错误,也可以在我的应用程序中将其放入自定义错误部分或在代码中处理它。
现在我假设IIS始终首先收到请求,那么它何时会自己处理404,何时会让其通过到我的应用程序?
另外一个问题:IIS是否能够知道asp.net MVC中的请求是否是404错误,因为它可能已经映射到任何路由?

想知道为什么我这里没有“开始悬赏”的选项。 - Michel
啊,我已经看了文档,原来是因为还有另一个赏金任务在进行中,而同一时间只能有一个任务处于活动状态。 - Michel
5个回答

1
IIS是否能够知道asp.net MVC中的请求是否为404错误,因为它可能已映射或未映射任何路由,这要取决于控制器工厂如何处理未映射的请求。当DefaultController工厂找不到路由时会抛出带有404代码的HttpException,并让IIS处理错误显示。您可以通过创建自己的控制器工厂来测试并观察其操作。例如,将以下行添加到Application_Start中:
ControllerBuilder.Current.SetControllerFactory(new TestControllerFactory());

并将此类添加到全新的MVC项目中:

public class TestControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            //throw new Exception("Oops!");                               // yellow screen of death
            throw new System.Web.HttpException(404, "Oops not found!"); // bubbles up to IIS
        }
        return base.GetControllerInstance(requestContext, controllerType);
    }
}

导航到您的项目http://localhost/MvcApplication1/unmapped,并查看当您使用代码404抛出HttpException时发生了什么,与当您抛出常规异常(甚至是具有其他代码的HttpException)时发生了什么。

确保您在IIS下运行项目(而不是VS Dev Server),因为它们处理这些事情的方式不同。


1

IIS会查看请求的扩展名。如果有一个已注册的模块来处理进来的请求类型,那么它将把请求转发给该模块。

例如,如果您从服务器请求foo.jpg,则IIS内置了一个模块来处理image/jpg内容。如果该模块找不到文件,则返回404。

同样的道理。无论您的MVC处理程序不寻找什么(即:图像),IIS都会以另一种方式处理。


1

现在我假设IIS总是先收到请求,那么它什么时候处理自己的404错误,什么时候让它通过到我的应用程序?

虽然请求最初由ISS处理,但它会通过到达MVC应用程序。如果找不到文件,则会抛出HttpException,该异常会向IIS返回。如果找到文件,则直接提供服务,绕过路由。
但是,您可以通过调整RouteExistingFiles属性来修改行为。如果我没有记错,当属性设置为true(默认值为false)时,您需要创建一个路由来处理所有静态内容。但是,正如此处的帖子所建议的那样,根据Steve Sanderson的说法,路由系统将首先检查磁盘上是否存在文件。(请参见相关SO问题,特别是评论部分,以获得更好的澄清)。
自己试试吧。在Global.asax文件中使用Application_Error()Application_EndRequest()事件,并检查HttpContext.Current.Response对象,以查看提供内容时的最终响应。

还有一个问题:在asp.net MVC中,如果请求可能或可能没有通过任何路由映射而导致404错误,IIS是否能够知道?

这就是路由配置发挥作用的地方。由于MVC首先会检查文件是否存在,如果存在,则直接提供服务并绕过路由。对于控制器和操作,同样适用。例如,/SomeController/ActionThatDoesExist首先被检查以验证它是否为物理文件。显然,这不是一个文件,应用程序将返回404异常。

我认为与此问题相关的第三个方面是MVC和IIS如何协同工作。我指的是“集成模式”和“经典模式”。可以在这里找到一个很棒的解释。


1

IIS总是处理请求,然后将其转发到MVC应用程序。这基本上决定了如何处理它。

如果磁盘上已经有一个物理文件,则整个路由将被绕过并提供该文件。如果找不到文件,则尝试匹配路由。如果仍然无法解决,则MVC应用程序可能会处理404,否则它会抛出HTTPException,IIS处理404。

我相信即使在Webforms中,404情况在内部也基本相同。唯一的区别是目标始终是物理磁盘,但请求仍然转到ASP.NET Webforms,以防您想自己处理404。


0

你需要确保在MVC应用程序内执行,就像其他人所说的那样,通常情况下IIS会首先将请求传递到MVC,只有当MVC将404异常传递到足够高的位置时,IIS才会将其返回并应用其决策过程。

关键是:正确处理MVC中的404错误!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接