Asp.net mvc ASP.NET MVC 404错误处理

Asp.net mvc ASP.NET MVC 404错误处理,asp.net-mvc,error-handling,Asp.net Mvc,Error Handling,可能重复: 我已经做了在中概述的更改,并且仍然得到标准的404错误页面。是否需要在IIS中更改某些内容?在IIS中,可以根据错误代码指定重定向到“特定”页面。在您的示例中,您可以配置404->自定义的404错误页面。我建议您查看FilterAttribute。例如,MVC已经具有HandleErrorAttribute。您可以将其自定义为仅处理404。回答如果你感兴趣,我会看看例子 顺便说一句 您在上一个问题中接受的解决方案(最后一条路线)在大多数情况下都不起作用。带有HandleUnknow

可能重复:


我已经做了在中概述的更改,并且仍然得到标准的404错误页面。是否需要在IIS中更改某些内容?

在IIS中,可以根据错误代码指定重定向到“特定”页面。在您的示例中,您可以配置404->自定义的404错误页面。

我建议您查看FilterAttribute。例如,MVC已经具有HandleErrorAttribute。您可以将其自定义为仅处理404。回答如果你感兴趣,我会看看例子

顺便说一句

您在上一个问题中接受的解决方案(最后一条路线)在大多数情况下都不起作用。带有HandleUnknownAction的第二个解决方案将起作用,但需要在每个控制器中进行此更改或使用单个基本控制器

<system.web>
    <customErrors mode="On" >
       <error statusCode="404" redirect="~/Errors/Error404" />
    </customErrors>
</system.web>

我的选择是使用HandleUnknownAction解决方案。

看起来这是捕捉一切的最佳方式

另一个解决方案

将ErrorController或静态页面添加到包含404错误信息的

修改web.config(如果是控制器)


或者在静态页面的情况下

<system.web>
    <customErrors mode="On" >
        <error statusCode="404" redirect="~/Static404.html" />
    </customErrors>
</system.web>


这将处理错过的路线和错过的操作。

我已经调查了很多关于如何在MVC(特别是MVC3)中正确管理404的问题,这是我提出的最好的解决方案:

在global.asax中:

public class MvcApplication : HttpApplication
{
    protected void Application_EndRequest()
    {
        if (Context.Response.StatusCode == 404)
        {
            Response.Clear();

            var rd = new RouteData();
            rd.DataTokens["area"] = "AreaName"; // In case controller is in another area
            rd.Values["controller"] = "Errors";
            rd.Values["action"] = "NotFound";

            IController c = new ErrorsController();
            c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
        }
    }
}
错误控制器:

public sealed class ErrorsController : Controller
{
    public ActionResult NotFound()
    {
        ActionResult result;

        object model = Request.Url.PathAndQuery;

        if (!Request.IsAjaxRequest())
            result = View(model);
        else
            result = PartialView("_NotFound", model);

        return result;
    }
}
编辑:

如果您使用的是IoC(如AutoFac),则应使用以下方法创建控制器:

var rc = new RequestContext(new HttpContextWrapper(Context), rd);
var c = ControllerBuilder.Current.GetControllerFactory().CreateController(rc, "Errors");
c.Execute(rc);
而不是

IController c = new ErrorsController();
c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
(可选)

说明:

我可以想到6个场景,其中ASP.NET MVC3应用程序可以生成404

由ASP.NET生成:

  • 场景1:URL与路由表中的路由不匹配
由ASP.NET MVC生成:

  • 场景2:URL匹配路由,但指定不存在的控制器

  • 场景3:URL匹配路由,但指定不存在的操作

手动生成:

  • 场景4:操作使用HttpNotFound()方法返回HttpNotFoundResult

  • 场景5:一个操作抛出一个状态代码为404的HttpException

  • 场景6:操作手动将Response.StatusCode属性修改为404

目标

<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Errors/NotFound"/>
    </customErrors>
</system.web>
<system.webServer>
    <httpErrors errorMode="Custom">
        <remove statusCode="404"/>
        <error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>
<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Errors/NotFound"/>
    </customError>
</system.web>
  • (A)向用户显示自定义404错误页面

  • (B)在客户端响应上维护404状态代码(对于SEO特别重要)

  • (C)直接发送响应,不涉及302重定向

解决方案尝试:自定义错误

<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Errors/NotFound"/>
    </customErrors>
</system.web>
<system.webServer>
    <httpErrors errorMode="Custom">
        <remove statusCode="404"/>
        <error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>
<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Errors/NotFound"/>
    </customError>
</system.web>

此解决方案的问题:

  • 不符合情景(1)、(4)、(6)中的目标(A)
  • 不自动符合目标(B)。必须手动编程
  • 不符合目标(C)
解决方案尝试:HTTP错误

<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Errors/NotFound"/>
    </customErrors>
</system.web>
<system.webServer>
    <httpErrors errorMode="Custom">
        <remove statusCode="404"/>
        <error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>
<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Errors/NotFound"/>
    </customError>
</system.web>

此解决方案的问题:

  • 仅适用于IIS 7+
  • 不符合情景(2)、(3)、(5)中的目标(A)
  • 不自动符合目标(B)。必须手动编程
解决方案尝试:HTTP错误与替换

<system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="404"/>
        <error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>

此解决方案的问题:

  • 仅适用于IIS 7+
  • 不自动符合目标(B)。必须手动编程
  • 它掩盖了应用程序级http异常。例如,不能使用customErrors部分、System.Web.Mvc.HandleErrorAttribute等。它不能仅显示一般错误页面
解决方案尝试自定义错误和HTTP错误

<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Errors/NotFound"/>
    </customErrors>
</system.web>
<system.webServer>
    <httpErrors errorMode="Custom">
        <remove statusCode="404"/>
        <error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>
<system.web>
    <customErrors mode="On">
        <error statusCode="404" redirect="~/Errors/NotFound"/>
    </customError>
</system.web>


此解决方案的问题:

  • 仅适用于IIS 7+
  • 不自动符合目标(B)。必须手动编程
  • 不符合情景(2)、(3)、(5)中的目标(C)

以前对此有过困扰的人甚至试图创建自己的库(请参阅)。但是前面的解决方案似乎涵盖了所有场景,而不需要使用外部库的复杂性。

来自Marco的响应是最好的解决方案。我需要控制我的错误处理,我的意思是真正控制它。当然,我对解决方案进行了一些扩展,并创建了一个完整的错误管理系统来管理一切。我也在其他博客上读到过这个解决方案,大多数高级开发人员似乎都非常接受它

下面是我使用的最后一个代码:

protected void Application_EndRequest()
    {
        if (Context.Response.StatusCode == 404)
        {
            var exception = Server.GetLastError();
            var httpException = exception as HttpException;
            Response.Clear();
            Server.ClearError();
            var routeData = new RouteData();
            routeData.Values["controller"] = "ErrorManager";
            routeData.Values["action"] = "Fire404Error";
            routeData.Values["exception"] = exception;
            Response.StatusCode = 500;

            if (httpException != null)
            {
                Response.StatusCode = httpException.GetHttpCode();
                switch (Response.StatusCode)
                {
                    case 404:
                        routeData.Values["action"] = "Fire404Error";
                        break;
                }
            }
            // Avoid IIS7 getting in the middle
            Response.TrySkipIisCustomErrors = true;
            IController errormanagerController = new ErrorManagerController();
            HttpContextWrapper wrapper = new HttpContextWrapper(Context);
            var rc = new RequestContext(wrapper, routeData);
            errormanagerController.Execute(rc);
        }
    }
在我的ErrorManager控制器中:

        public void Fire404Error(HttpException exception)
    {
        //you can place any other error handling code here
        throw new PageNotFoundException("page or resource");
    }
现在,在我的操作中,我抛出了一个我创建的自定义异常。我的控制器是从我创建的基于自定义控制器的类继承的。创建自定义基本控制器是为了覆盖错误处理。以下是我的自定义基本控制器类:

public class MyBasePageController : Controller
{
    protected override void OnException(ExceptionContext filterContext)
    {
        filterContext.GetType();
        filterContext.ExceptionHandled = true;
        this.View("ErrorManager", filterContext).ExecuteResult(this.ControllerContext);
        base.OnException(filterContext);
    }
}
上面代码中的“ErrorManager”只是一个使用基于ExceptionContext的模型的视图


我的解决方案工作得很好,我能够处理网站上的任何错误,并根据任何异常类型显示不同的消息。

问题似乎是,{controller}/{action}/{id}的标准默认路由捕获了所有内容,因此无法到达最后一条路由。我认为,如果找不到控制器,将对下一条路线进行评估。HandleUnknownAction仅适用于未关闭的操作。如果路由匹配但找不到结果控制器,该怎么办