Обрабатывать ошибки с помощью ErrorController, а не прямого просмотра - PullRequest
6 голосов
/ 13 октября 2008

Я пытаюсь разобраться с обработкой ошибок в MVC. То, что я ищу, - это централизованный способ отлавливать ошибки, регистрировать их, если возможно, разрешать, если необязательные другие действия и, наконец, отображать правильное представление для пользователя.

Я думаю, что могу использовать фильтр [HandleError] для этого, но я не вижу способа направить его в контроллер / действие. Единственный вариант, который я вижу, - это указывать его непосредственно на представление.

Ответы [ 4 ]

4 голосов
/ 13 октября 2008

HandleErrorAttribute , поставляемый с MVC, является довольно простым IExceptionFilter.

У вас есть несколько вариантов для достижения того, что я думаю, вы хотите.

Вы можете использовать [HandleError (Type = typeof (MyException), View = "ErrorView")] на действиях / контроллерах или реализовать свой собственный

HandleErrorAttribute не очень сложен. Я думаю, что MS рекомендует вам скопировать этот код и изменить его в соответствии с вашими требованиями.

Переопределение OnException предоставляет вам доступ ко всей той информации, которая вам может понадобиться - контролер, действие, данные маршрута и т. Д. - через ExceptionContext.

Не забудьте установить ExceptionHandled. Затем вы можете установить filterContext.Result для нового экземпляра RedirectToAction, который перенаправляет ваш ErrorController и действие - очевидно, вы можете выставить конкретный контроллер и действие со свойствами.

2 голосов
/ 16 апреля 2009

Leppi, если вы хотите отправить в Action Result, вы можете определить Action и Controller для перенаправления в случае ошибки. Это хороший пример, но лично мне не нравится не использовать пользовательские страницы или 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
1 голос
/ 13 октября 2008

Почему бы не создать свой собственный ErrorResult, полученный из ActionResult?

0 голосов
/ 13 октября 2008

Что я делаю (что может или не может быть хорошей практикой) это:

При возникновении ошибки:

  • Если я ожидал этого и справлюсь с этим, я делаю (регистрируя это с помощью ELMAH)
  • Если я ожидал этого и не смог с этим справиться, я регистрирую его в ELMAH и возвращаю ViewResult, который является моей страницей с ошибкой
    • Включите описание ошибки, стандартное сообщение и ссылку на то, что я делал
  • Если я этого не ожидал, мое переопределение OnError в классе базового контроллера выполняет предыдущий шаг
  • Все другие ошибки, которые не могут быть обработаны, автоматически регистрируются ELMAH, и запрос отображает желтые экраны

Большая часть моей общей обработки ошибок идет в базовом классе для всех моих контроллеров. Единственная проблема заключается в том, что мне нужно вручную установить контроллер и значение действия в базовом классе, чтобы он мог генерировать ActionLink для перенаправления на странице ошибок.

...