我已经研究过 A LOT 如何在MVC(特别是MVC3)中正确管理404s,而这一点,恕我直言是我提出的最好的解决方案:
在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;
}
}
Edit:
如果您正在使用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));
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");
}
6 回答
又一个解决方案 .
添加ErrorControllers或静态页面以及404错误信息 .
修改web.config(如果是控制器) .
或者在静态页面的情况下
这将处理错过的路线和错过的行动 .
我已经研究过 A LOT 如何在MVC(特别是MVC3)中正确管理404s,而这一点,恕我直言是我提出的最好的解决方案:
在global.asax中:
ErrorsController:
Edit:
如果您正在使用IoC(例如AutoFac),则应使用以下命令创建控制器:
代替
(可选的)
Explanation:
我可以想到有6个场景,ASP.NET MVC3应用程序可以生成404s .
由ASP.NET生成:
由ASP.NET MVC生成:
Scenario 2: URL匹配路由,但指定不存在的控制器 .
Scenario 3: URL匹配路由,但指定了不存在的操作 .
手动生成:
Scenario 4: 操作使用方法HttpNotFound()返回HttpNotFoundResult .
Scenario 5: 一个动作抛出一个状态码为404的HttpException .
Scenario 6: 操作手动将Response.StatusCode属性修改为404 .
Objectives
(A) 向用户显示自定义404错误页面 .
(B) 在客户端响应中维护404状态代码(对SEO特别重要) .
(C) 直接发送响应,不涉及302重定向 .
Solution Attempt: Custom Errors
此解决方案的问题:
不符合方案(1),(4),(6)中的目标(A) .
不自动符合目标(B) . 必须手动编程 .
不符合目标(C) .
Solution Attempt: HTTP Errors
此解决方案的问题:
仅适用于IIS 7 .
不符合方案(2),(3),(5)中的目标(A) .
不自动符合目标(B) . 必须手动编程 .
Solution Attempt: HTTP Errors with Replace
此解决方案的问题:
仅适用于IIS 7 .
不自动符合目标(B) . 必须手动编程 .
它模糊了应用程序级别的http异常 . 例如 . can 't use customErrors section, System.Web.Mvc.HandleErrorAttribute, etc. It can' t只显示通用错误页面 .
Solution Attempt customErrors and HTTP Errors
和
此解决方案的问题:
仅适用于IIS 7 .
不自动符合目标(B) . 必须手动编程 .
不符合方案(2),(3),(5)中的目标(C) .
那些曾经困扰过这个的人甚至试图创建自己的库(参见http://aboutcode.net/2011/02/26/handling-not-found-with-asp-net-mvc3.html) . 但是之前的解决方案似乎涵盖了所有场景,而没有使用外部库的复杂性 .
Marco的回应是最佳解决方案 . 我需要控制我的错误处理,我的意思是真的控制它 . 当然,我已经扩展了一点解决方案并创建了一个管理所有内容的完整错误管理系统 . 我也在其他博客中读到了这个解决方案,大多数高级开发人员似乎都接受了这个解决方案 .
这是我正在使用的最终代码:
在我的ErrorManagerController里面:
现在,在我的Action中,我正在抛出我创建的自定义异常 . 我的Controller继承自我创建的自定义Controller Based类 . 创建自定义基本控制器以覆盖错误处理 . 这是我的自定义基本控制器类:
上面代码中的“ErrorManager”只是一个使用基于ExceptionContext的Model的视图
我的解决方案完美无缺,我可以在我的网站上处理任何错误,并根据任何异常类型显示不同的消息 .
看起来这是捕捉一切的最佳方式 .
How can I properly handle 404 in ASP.NET MVC?
我可以推荐的是查看FilterAttribute . 例如,MVC已经有HandleErrorAttribute . 你可以自定义它只处理404.如果你是朋友,请回复我会看例子 .
BTW
您在上一个问题中接受的解决方案(使用最后一条路线)在大多数情况下都不起作用 . 使用 HandleUnknownAction 的第二个解决方案可以工作,但需要这样做更改每个控制器或具有单个基本控制器 .
我的选择是使用HandleUnknownAction的解决方案 .
在IIS中,您可以根据错误代码指定重定向到“特定”页面 . 在您的示例中,您可以配置404 - >您自定义的404错误页面 .