Я исследовал МНОГО о том, как правильно управлять в 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;
}
}
Редактировать :
Если вы используете 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 могут генерировать 404s.
Порожденных ASP.NET:
- Сценарий 1: URL не соответствует маршрут в таблице маршрутизации.
порожденных ASP.NET MVC:
Сценарий 2: URL соответствует маршруту, но указывает контроллер, который не существует.
Сценарий 3: URL-адрес соответствует маршруту, но указывает действие, которое не существует.
генерируется вручную:
Сценарий 4: Действие возвращает HttpNotFoundResult с помощью метода HttpNotFound().
Сценарий 5: действие бросает HttpException с кодом состояния 404.
Сценарий 6: An действия вручную изменяет свойство Response.StatusCode к 404.
Цели
(A) Показать пользовательскую страницу ошибки 404 пользователю.
(B) Поддержание кода статуса 404 при ответе клиента (особенно важно для SEO).
(C) Отправить ответ напрямую, без привлечения перенаправления 302.
Решение Попытка: Пользовательские ошибки
<system.web>
<customErrors mode="On">
<error statusCode="404" redirect="~/Errors/NotFound"/>
</customError>
</system.web>
Проблемы с этим раствором:
- не соответствует объективному (A) в сценариях (1), (4), (6).
- Не соответствует объективу (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).
- Не соответствует объективу (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 и т. д. Он может не только показывать общие страницы ошибок.
Решения ПОПЫТКА CustomErrors и Ошибка 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) автоматически. Он должен быть запрограммирован вручную.
- Не соответствует объективному (C) в сценариях (2), (3), (5).
Люди, которые обеспокоены этим, даже пытались создать свои собственные библиотеки (см. http://aboutcode.net/2011/02/26/handling-not-found-with-asp-net-mvc3.html). Но предыдущее решение, похоже, охватывает все сценарии без сложности использования внешней библиотеки.
Это хороший прочтение на эту тему @ [Как эффективно справляться с ошибками 404 Not Found с помощью ASP.NET MVC 4] (http://yassershaikh.com/how-to-handle-404-not-found-errors -effectively-with-asp-net-mvc-4 /) – Yasser