Обрабатывайте ошибки с помощью ErrorController, а не прямого просмотра
-
10-07-2019 - |
Вопрос
Я пытаюсь разобраться в обработке ошибок в MVC.То, что я ищу, - это централизованный способ улавливать ошибки, регистрировать их, по возможности устранять, при необходимости предпринимать другие действия и, наконец, показывать пользователю правильное представление.
Я думаю, что могу использовать фильтр [HandleError] для этого, но я не вижу никакого способа перенаправить его на контроллер / Действие.Единственный вариант, который я вижу, - это указать его непосредственно на вид.
Решение
HandleErrorAttribute , который поставляется с MVC, является довольно простой IExceptionFilter.
У вас есть несколько вариантов для достижения того, что, я думаю, вам нужно.
Вы можете использовать [HandleError (Type = typeof (MyException), View = " ErrorView ")] на действиях / контроллерах или реализовать свой собственный
HandleErrorAttribute не очень сложен. Я думаю, что MS рекомендует вам скопировать этот код и изменить его в соответствии с вашими требованиями.
Переопределение OnException дает вам доступ ко всей той информации, которая вам может понадобиться - контролер, действие, данные маршрута и т. д. - через ExceptionContext.
Не забудьте установить ExceptionHandled. Затем вы можете установить для filterContext.Result новый экземпляр RedirectToAction, который перенаправляет на ваш ErrorController и действие - очевидно, вы можете выставить конкретный контроллер и действие со свойствами.
Другие советы
Леппи, если вы хотите отправить результат действия, вы можете определить действие и контроллер для перенаправления при ошибке. Это хороший пример, но лично мне не нравится не использовать пользовательские страницы или http-коды для кодов
Вот и пример моего IExtenptionFilter. Мой базовый контроллер имеет IExceptionFilter по умолчанию для обработки всех не контролируемых ошибок.
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
Justification = "This attribute is AllowMultiple = true and users might want to override behavior.")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class GenericExceptionHandlerFilter : ActionFilterAttribute, IExceptionFilter
{
public Type ExceptionType { get; set;}
public string RedirectToAction { get; set;}
public string RedirectToController { get; set;}
protected bool ApplyFilter(ExceptionContext filterContext)
{
Type lExceptionType = filterContext.Exception.GetType();
return (ExceptionType == null ||
lExceptionType.Equals(ExceptionType));
}
#region IExceptionFilter Members
public void OnException(ExceptionContext filterContext)
{
if (ApplyFilter(filterContext))
{
IbfControllerLogger.Log(filterContext.Exception);
filterContext.ExceptionHandled = true;
#region Calculate Action Controller Error
RouteValueDictionary lRoutes = new RouteValueDictionary(new
{
action = RedirectToAction,
controller = String.IsNullOrEmpty(RedirectToController) ? (string)filterContext.RouteData.Values["controller"] : RedirectToController
});
UrlReWriterUtils.UrlReWriter(filterContext.Controller.ViewData, lRoutes);
#endregion
filterContext.Controller.TempData[TempDataName.C_TEMPDATA_EXCEPTIONERROR] = filterContext.Exception;
filterContext.Result = new RedirectToRouteResult(lRoutes);
}
}
#endregion
Почему бы не создать свой собственный ErrorResult, производный от ActionResult?
То, что я делаю (что может быть или не быть хорошей практикой), заключается в следующем:
При возникновении ошибки:
- Если я ожидал этого и могу с этим справиться, я это делаю (регистрирую это с помощью ELMAH).
- Если я ожидал этого и не могу с этим справиться, я регистрирую это в ELMAH и возвращаю ViewResult, который является моей страницей ошибок
- Включите описание ошибки, стандартное сообщение и ссылку на то, что я делал
- Если я этого не ожидал, мое переопределение onError в моем базовом классе контроллера выполняет предыдущий шаг
- Все остальные ошибки, которые не могут быть обработаны, автоматически регистрируются ELMAH и желтыми экранами запроса
Большая часть моей общей обработки ошибок выполняется в базовом классе для всех моих контроллеров.Единственная проблема заключается в том, что мне приходится вручную устанавливать контроллер и значение действия в базовом классе, чтобы он мог сгенерировать ActionLink для перенаправления на странице ошибки.