我已经调查了很多关于如何正确地管理MVC中的404(特别是MVC3),这是我提出的最好的解决方案:
在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;
}
}
(可选)
解释:
AFAIK,有6种不同的情况,ASP。NET MVC3应用程序可以生成404。
(由ASP自动生成。净框架:)
(1)路由表中没有匹配的URL。
(由ASP自动生成。NET MVC框架:)
(2) URL在路由表中找到匹配,但是指定了一个不存在的控制器。
(3) URL在路由表中找到匹配,但是指定了一个不存在的动作。
(手动生成:)
一个动作通过使用HttpNotFound()方法返回一个HttpNotFoundResult。
动作抛出一个状态代码为404的HttpException。
(6)动作手动修改响应。StatusCode属性变为404。
通常情况下,你需要完成3个目标:
(1)向用户显示自定义404错误页面。
(2)维护客户端响应上的404状态代码(对SEO特别重要)。
(3)直接发送响应,不涉及302重定向。
有很多方法可以做到这一点:
(1)
<system.web>
<customErrors mode="On">
<error statusCode="404" redirect="~/Errors/NotFound"/>
</customError>
</system.web>
此解决方案存在的问题:
在情况(1)、(4)、(6)中不符合目标(1)。
不自动符合目标(2)。它必须手动编程。
不符合目标(3)。
(2)
<system.webServer>
<httpErrors errorMode="Custom">
<remove statusCode="404"/>
<error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
</httpErrors>
</system.webServer>
此解决方案存在的问题:
仅适用于iis7 +。
在情况(2)、(3)、(5)中不符合目标(1)。
不自动符合目标(2)。它必须手动编程。
(3)
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404"/>
<error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
</httpErrors>
</system.webServer>
此解决方案存在的问题:
仅适用于iis7 +。
不自动符合目标(2)。它必须手动编程。
它模糊了应用程序级别的http异常。例如,不能使用customErrors部分,System.Web.Mvc。HandleErrorAttribute等等。它不能只显示一般的错误页面。
(4)
<system.web>
<customErrors mode="On">
<error statusCode="404" redirect="~/Errors/NotFound"/>
</customError>
</system.web>
and
<system.webServer>
<httpErrors errorMode="Custom">
<remove statusCode="404"/>
<error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/>
</httpErrors>
</system.webServer>
此解决方案存在的问题:
仅适用于iis7 +。
不自动符合目标(2)。它必须手动编程。
在情况(2)、(3)、(5)中不符合目标(3)。
在此之前遇到麻烦的人甚至尝试创建自己的库(参见http://aboutcode.net/2011/02/26/handling-not-found-with-asp-net-mvc3.html)。但是前面的解决方案似乎涵盖了所有的情况,而没有使用外部库的复杂性。