Быстрый ответ / TL; DR
Для ленивых людей:
Install-Package MagicalUnicornMvcErrorToolkit -Version 1.0
Затем удалите эту строку из global.asax
GlobalFilters.Filters.Add(new HandleErrorAttribute());
И это только для IIS7 + и IIS Express.
Если вы используете Кассини .. ну .. эм .. эээ ... неловко ...
Long, explained answer
I know this has been answered. But the answer is REALLY SIMPLE (cheers to Дэвид Фаулер и Дамиан Эдвардс за искренний ответ на этот вопрос).
нет необходимости делать что-либо нестандартное .
Для ASP.NET MVC3
все биты и кусочки есть.
Шаг 1 -> Обновите ваш web.config в двух местах.
<system.web>
<customErrors mode="On" defaultRedirect="/ServerError">
<error statusCode="404" redirect="/NotFound" />
</customErrors>
и
<system.webServer>
<httpErrors errorMode="Custom">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="/NotFound" responseMode="ExecuteURL" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="500" path="/ServerError" responseMode="ExecuteURL" />
</httpErrors>
...
<system.webServer>
...
</system.web>
Теперь внимательно обратите внимание на МАРШРУТЫ, которые я решил использовать. Вы можете использовать что угодно, но мои маршруты
/NotFound
<- для 404 не найдено, страница ошибки. </li>
/ServerError
<- для любой другой ошибки, включите ошибки, которые происходят в моем коде. это 500 внутренняя ошибка сервера </li>
Посмотрите, как в первом разделе <system.web>
есть только одна настраиваемая запись? Запись statusCode="404"
? Я перечислил только один код состояния, потому что все остальные ошибки, включая 500 Server Error
(то есть те неприятные ошибки, которые возникают, когда в вашем коде возникает ошибка и происходит сбой запроса пользователя) ... все остальные ошибки обрабатываются настройкой defaultRedirect="/ServerError"
.. где написано, что если страница 404 не найдена, то пройдите по маршруту /ServerError
.
Ok. это вне пути .. теперь к моим маршрутам, перечисленным в global.asax
Шаг 2 - Создание маршрутов в Global.asax
Вот мой полный раздел маршрута ..
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*favicon}", new {favicon = @"(.*/)?favicon.ico(/.*)?"});
routes.MapRoute(
"Error - 404",
"NotFound",
new { controller = "Error", action = "NotFound" }
);
routes.MapRoute(
"Error - 500",
"ServerError",
new { controller = "Error", action = "ServerError"}
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Home", action = "Index", id = UrlParameter.Optional}
);
}
Это список двух маршрутов игнорирования -> axd's
и favicons
(ооо! Бонус игнорировать маршрут, для вас!)
Тогда (и порядок здесь ИМПЕРАТИВНЫЙ), у меня есть два моих явных маршрута обработки ошибок ..., за которыми следуют любые другие маршруты. В этом случае по умолчанию. Конечно, у меня есть больше, но это особенное для моего веб-сайта. Просто убедитесь, что маршруты ошибок находятся вверху списка. Заказ является обязательным .
Наконец, пока мы находимся в нашем файле global.asax
, мы НЕ регистрируем глобально атрибут HandleError. Нет, нет, нет, сэр. Nadda. Нету. Nien. Negative. Noooooooooo ...
Удалить эту строку из global.asax
GlobalFilters.Filters.Add(new HandleErrorAttribute());
Шаг 3 - Создать контроллер с методами действия
Теперь .. мы добавляем контроллер с двумя методами действия ...
public class ErrorController : Controller
{
public ActionResult NotFound()
{
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View();
}
public ActionResult ServerError()
{
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
// Todo: Pass the exception into the view model, which you can make.
// That's an exercise, dear reader, for -you-.
// In case u want to pass it to the view, if you're admin, etc.
// if (User.IsAdmin) // <-- I just made that up :) U get the idea...
// {
// var exception = Server.GetLastError();
// // etc..
// }
return View();
}
// Shhh .. secret test method .. ooOOooOooOOOooohhhhhhhh
public ActionResult ThrowError()
{
throw new NotImplementedException("Pew ^ Pew");
}
}
Хорошо, давайте проверим это. Прежде всего, здесь есть атрибут NO [HandleError]
. Зачем? Поскольку встроенный ASP.NET
фреймворк уже обрабатывает ошибки И мы указали все дерьмо, которое нам нужно сделать, чтобы обработать ошибку :) Именно в этом методе!
Далее у меня есть два метода действия. Ничего сложного там нет. Если вы хотите показать информацию об исключении, вы можете использовать Server.GetLastError()
, чтобы получить эту информацию.
Бонус WTF: Да, я сделал третий метод действия, чтобы проверить обработку ошибок.
Шаг 4 - Создание представлений
И наконец, создайте два представления. Поместите их в обычное место просмотра для этого контроллера.
Бонусные комментарии
- Вам не нужно
Application_Error(object sender, EventArgs e)
- Все вышеперечисленные шаги прекрасно работают на Elmah . Elmah Fraking Wroxs!
И это, друзья мои, должно быть.
Теперь, поздравляю с этим большим чтением и получаю единорога в качестве приза!