ASP.NET MVC 404error handling

可能重复:
我怎样才能正确处理ASP.NET MVC中的404?

我已经在Asp.Net MVC(RC 5)中的404 Httperror handling程序进行了修改,我仍然得到标准的404错误页面。 我需要改变IIS中的东西吗?

又一个解决scheme。

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

修改你的web.config(在控制器的情况下)。

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

或者在静态页面的情况下

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

这将处理错过的路线和错过的行动。

我已经调查了如何在MVC (特别是MVC3)中正确pipe理404的很多 ,而这,恕我直言,是我提出的最好的解决scheme:

在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),则应使用以下命令创build控制器:

 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应用程序可以生成404s的位置。

由ASP.NET生成:

  • 场景1: URL与路由表中的路由不匹配。

由ASP.NET MVC生成:

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

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

手动生成:

  • scheme4:一个操作通过使用方法HttpNotFound()返回一个HttpNotFoundResult。

  • 场景5:一个动作抛出一个带有状态码404的HttpExceptionexception。

  • scheme6:一个操作手动将Response.StatusCode属性修改为404。

目标

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

  • (B)维护客户端响应中的404状态码(对于search引擎优化尤为重要)。

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

解决scheme尝试:自定义错误

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

这个解决scheme的问题:

  • 不符合情景(1),(4),(6)中的目标(A)。
  • 不符合目标(B)自动。 必须手动编程。
  • 不符合目标(C)。

解决scheme尝试:HTTP错误

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

这个解决scheme的问题:

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

解决方法尝试:replaceHTTP错误

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

这个解决scheme的问题:

  • 只适用于IIS 7+。
  • 不符合目标(B)自动。 必须手动编程。
  • 它掩盖了应用程序级别的httpexception。 例如不能使用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> 

这个解决scheme的问题:

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

之前曾经困扰过这个问题的人甚至试图创build自己的库(参见http://aboutcode.net/2011/02/26/handling-not-found-with-asp-net-mvc3.html )。 但是,以前的解决scheme似乎涵盖了所有情况,没有使用外部库的复杂性。

Marco的回应是最好的解决scheme。 我需要控制我的error handling,我的意思是真的控制它。 当然,我已经扩展了这个解决scheme,创build了一个完整的错误pipe理系统来pipe理一切。 我也在其他博客上看过这个解决scheme,大多数高级开发人员似乎都非常接受。

这是我正在使用的最终代码:

 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中,我抛出了一个我创build的自定义exception。 而我的控制器inheritance自我创build的一个自定义的基于Controller的类。 自定义基本控制器被创build来覆盖error handling。 这是我的自定义基本控制器类:

 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的视图

我的解决scheme完美地工作,我能够处理我的网站上的任何错误,并显示不同的消息基于任何exceptiontypes。

看起来这是抓住一切的最好方法。

我怎样才能正确处理ASP.NET MVC中的404?

我可以推荐的是看FilterAttribute。 例如MVC已经有HandleErrorAttribute。 你可以自定义它来处理只有404。回复,如果你是分歧我会看看例子。

BTW

您在前面的问题中接受的解决scheme(包含最后一个路线)在很多情况下都不起作用。 HandleUnknownAction的第二个解决scheme将工作,但需要在每个控制器中进行此更改或具有单个基本控制器。

我的select是HandleUnknownAction的解决scheme。

在IIS中,您可以根据错误代码指定redirect到“特定”页面。 在你的例子中,你可以configuration404 – >你自定义的404错误页面。