Маршрутизация для пользовательской страницы ошибки ASP.NET MVC 404
Я пытаюсь создать пользовательскую страницу ошибки HTTP 404, когда кто-то вводит URL-адрес, который не вызывает допустимое действие или контроллер в ASP.NET MVC, вместо отображения общей ошибки ASP.NET "Ресурс не найден".
Я не хочу использовать web.config для этого.
Есть ли какая-нибудь магия маршрутизации, которую я могу сделать, чтобы поймать любые недействительные URL?
Обновление: я попытался дать ответ, однако я все еще получаю уродливое сообщение "Ресурс не найден".
Еще одно обновление: ок, видимо что-то изменилось в RC1. Я даже пытался специально ловить 404 на HttpException
и он по-прежнему просто дает мне страницу "Ресурс не найден".
Я даже использовал функцию ресурса MvcContrib и ничего - та же проблема. Есть идеи?
9 ответов
Просто добавьте команду catch all route в конец таблицы маршрутов и покажите с ней любую нужную страницу.
Я пытался включить пользовательские ошибки на производственном сервере в течение 3 часов, кажется, я нашел окончательное решение, как это сделать в ASP.NET MVC без каких-либо маршрутов.
Чтобы включить пользовательские ошибки в приложении ASP.NET MVC, нам нужно (IIS 7+):
Настроить пользовательские страницы в веб-конфигурации под
system.web
раздел:<customErrors mode="RemoteOnly" defaultRedirect="~/error"> <error statusCode="404" redirect="~/error/Error404" /> <error statusCode="500" redirect="~/error" /> </customErrors>
RemoteOnly
означает, что в локальной сети вы увидите реальные ошибки (очень полезно при разработке). Мы также можем переписать страницу ошибки для любого кода ошибки.Установите магический параметр Response и код состояния ответа (в модуле обработки ошибок или в атрибуте обработчика ошибок)
HttpContext.Current.Response.StatusCode = 500; HttpContext.Current.Response.TrySkipIisCustomErrors = true;
Установите другой магический параметр в веб-конфигурации под
system.webServer
раздел:<httpErrors errorMode="Detailed" />
Это была последняя вещь, которую я нашел, и после этого я могу увидеть пользовательские ошибки на рабочем сервере.
Я получил обработку ошибок, создав ErrorController, который возвращает представления в этой статье. Мне также пришлось добавить "Catch All" к маршруту в global.asax.
Я не вижу, как он попадет на любую из этих страниц с ошибками, если ее нет в файле Web.config..? Мой Web.config должен был указать:
customErrors mode="On" defaultRedirect="~/Error/Unknown"
а потом я также добавил:
error statusCode="404" redirect="~/Error/NotFound"
NotFoundMVC - предоставляет удобную для пользователя страницу 404 всякий раз, когда в приложении ASP.NET MVC3 не найден контроллер, действие или маршрут. Представление с именем NotFound отображается вместо страницы ошибки ASP.NET по умолчанию.
Вы можете добавить этот плагин через Nuget, используя: Install-Package NotFoundMvc
NotFoundMvc автоматически устанавливается при запуске веб-приложения. Он обрабатывает все различные способы, которыми 404 HttpException обычно генерируется ASP.NET MVC. Это включает в себя отсутствующий контроллер, действие и маршрут.
Пошаговое руководство по установке:
1 - Щелкните правой кнопкой мыши свой проект и выберите "Управление пакетами Nuget"...
2 - Поиск NotFoundMvc
и установите его.
3 - После завершения установки в ваш проект будут добавлены два файла. Как показано на скриншотах ниже.
4 - Откройте недавно добавленный NotFound.cshtml подарок в Views/Shared и измените его по своему желанию. Теперь запустите приложение и введите неправильный URL-адрес, и вас встретит страница 404, удобная для пользователя.
Нет больше, пользователи получат сообщение об ошибке, как Server Error in '/' Application. The resource cannot be found.
Надеюсь это поможет:)
PS: Спасибо Эндрю Дэйви за создание такого замечательного плагина.
Попробуйте это в web.config, чтобы заменить страницы ошибок IIS. Это лучшее решение, я думаю, и оно также отправляет правильный код состояния.
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="404" path="Error404.html" responseMode="File" />
<error statusCode="500" path="Error.html" responseMode="File" />
</httpErrors>
</system.webServer>
Больше информации от Tipila - Используйте пользовательские страницы ошибок ASP.NET MVC
Это решение не нуждается в изменениях файла web.config или трассировках всех типов.
Сначала создайте такой контроллер;
public class ErrorController : Controller
{
public ActionResult Index()
{
ViewBag.Title = "Regular Error";
return View();
}
public ActionResult NotFound404()
{
ViewBag.Title = "Error 404 - File not Found";
return View("Index");
}
}
Затем создайте представление в "Views/Error/Index.cshtml" as;
@{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<p>We're sorry, page you're looking for is, sadly, not here.</p>
Затем добавьте следующее в файл Global asax, как показано ниже:
protected void Application_Error(object sender, EventArgs e)
{
// Do whatever you want to do with the error
//Show the custom error page...
Server.ClearError();
var routeData = new RouteData();
routeData.Values["controller"] = "Error";
if ((Context.Server.GetLastError() is HttpException) && ((Context.Server.GetLastError() as HttpException).GetHttpCode() != 404))
{
routeData.Values["action"] = "Index";
}
else
{
// Handle 404 error and response code
Response.StatusCode = 404;
routeData.Values["action"] = "NotFound404";
}
Response.TrySkipIisCustomErrors = true; // If you are using IIS7, have this line
IController errorsController = new ErrorController();
HttpContextWrapper wrapper = new HttpContextWrapper(Context);
var rc = new System.Web.Routing.RequestContext(wrapper, routeData);
errorsController.Execute(rc);
Response.End();
}
Если после этого вы по-прежнему получаете пользовательскую страницу ошибок IIS, убедитесь, что следующие разделы закомментированы (или пусты) в файле веб-конфигурации:
<system.web>
<customErrors mode="Off" />
</system.web>
<system.webServer>
<httpErrors>
</httpErrors>
</system.webServer>
Если вы работаете в MVC 4, вы можете посмотреть это решение, оно сработало для меня.
Добавьте следующий метод Application_Error в мой Global.asax
:
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
Server.ClearError();
RouteData routeData = new RouteData();
routeData.Values.Add("controller", "Error");
routeData.Values.Add("action", "Index");
routeData.Values.Add("exception", exception);
if (exception.GetType() == typeof(HttpException))
{
routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
}
else
{
routeData.Values.Add("statusCode", 500);
}
IController controller = new ErrorController();
controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
Response.End();
Сам контроллер действительно прост:
public class ErrorController : Controller
{
public ActionResult Index(int statusCode, Exception exception)
{
Response.StatusCode = statusCode;
return View();
}
}
Проверьте полный исходный код Mvc4CustomErrorPage на GitHub.
Я расскажу о некоторых конкретных случаях,
если вы используете метод PageNotFound в HomeController, как показано ниже
[Route("~/404")]
public ActionResult PageNotFound()
{
return MyView();
}
это не сработает. Но вы должны очистить теги маршрута, как показано ниже,
//[Route("~/404")]
public ActionResult PageNotFound()
{
return MyView();
}
И если вы измените его как имя метода в web.config, он будет работать. Однако не забудьте сделать код, как показано ниже, в web.config
<customErrors mode="On">
<error statusCode="404" redirect="~/PageNotFound" />
*// it is not "~/404" because it is not accepted url in Route Tag like [Route("404")]*
</customErrors>
У меня была та же проблема, что вы должны сделать, вместо того, чтобы добавить атрибут customErrors в файле web.config в папке Views, вы должны добавить его в файл web.config в корневой папке ваших проектов
Вот верный ответ, который позволяет полностью настроить страницу ошибки в одном месте. Нет необходимости изменять web.config или создавать отдельный код.
Работает также в MVC 5.
Добавьте этот код в контроллер:
if (bad) {
Response.Clear();
Response.TrySkipIisCustomErrors = true;
Response.Write(product + I(" Toodet pole"));
Response.StatusCode = (int)HttpStatusCode.NotFound;
//Response.ContentType = "text/html; charset=utf-8";
Response.End();
return null;
}
Основано на http://www.eidias.com/blog/2014/7/2/mvc-custom-error-pages