ASP.NET MVC 404错误处理

可能重复:
我如何正确处理ASP.NET MVC中的404?

我已经在Asp.Net MVC(RC 5)中的404 Http错误处理程序中进行了修改,并且仍然收到标准的404错误页面。 我需要在IIS中更改某些内容吗?


又一个解决方案。

添加ErrorControllers或静态页面到404错误信息。

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

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

或者在静态页面的情况下

<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));
        }
    }
}

ErrorsController:

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。

  • 目标

  • (A)给用户显示一个自定义的404错误页面。

  • (B)在客户端响应中维护404状态码(对于SEO尤其重要)。

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

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

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

    此解决方案的问题:

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

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

    此解决方案的问题:

  • 只适用于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"/>
        </customError>
    </system.web>
    

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

    此解决方案的问题:

  • 只适用于IIS 7+。
  • 不符合目标(B)自动。 它必须手动编程。
  • 不符合情景(2),(3),(5)中的目标(C)。
  • 之前曾经困扰过这个问题的人甚至试图创建自己的库(参见http://aboutcode.net/2011/02/26/handling-not-found-with-asp-net-mvc3.html)。 但是之前的解决方案似乎涵盖了所有场景,而没有使用外部库的复杂性。


    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);
            }
        }
    

    并在我的ErrorManagerController里面:

            public void Fire404Error(HttpException exception)
        {
            //you can place any other error handling code here
            throw new PageNotFoundException("page or resource");
        }
    

    现在,在我的Action中,我抛出了我创建的自定义异常。 我的控制器继承自我创建的基于自定义控制器的类。 自定义基本控制器是为了覆盖错误处理而创建的。 这是我的自定义基础控制器类:

    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使用Model的视图

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

    链接地址: http://www.djcxy.com/p/58299.html

    上一篇: ASP.NET MVC 404 Error Handling

    下一篇: comprehensible modulo calculation