Атрибут HandleErrorAttribute не работает - PullRequest
5 голосов
/ 24 января 2012

Я запустил проект шаблона MVC 3 в VS10 и изменил global.asax.cs следующим образом:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute { ExceptionType = typeof(DivideByZeroException), View = "DivideByZeroException", Order = 1 });
    filters.Add(new HandleErrorAttribute { View = "AllOtherExceptions", Order = 2 });
}

К web.config я добавил:

<customErrors mode="On">

Затем создалсоответствующие представления и, наконец, добавили DivideByZero-throw к одному из действий.

Результат: представление AllOtherExceptions отображается.

Ответы [ 3 ]

21 голосов
/ 06 февраля 2012

Хотя я ненавижу не соглашаться ни с чем, что говорит Дарин, он ошибается в этом.

Нет проблем с настройкой свойств (это то, как вы должны сделать это).

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

См. MSDN :

OnActionExecuting (ActionExecutingContext), OnResultExecuting (ResultExecutingContext) и Фильтры OnAuthorization (AuthorizationContext) работают в прямом порядке. OnActionExecuted (ActionExecutedContext), OnResultExecuting (ResultExecutingContext) и Фильтры OnException (ExceptionContext) работают в обратном порядке.

Таким образом, ваш общий AllOtherExceptions фильтр должен быть самым низким Order числом, а не самым высоким.

Надеюсь, это поможет в следующий раз.

8 голосов
/ 24 января 2012

Вы не должны устанавливать свойства при регистрации глобального фильтра действий.Вы можете написать собственный фильтр ошибок дескриптора:

public class MyHandleErrorAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        if (!filterContext.IsChildAction && (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled))
        {
            Exception innerException = filterContext.Exception;
            if ((new HttpException(null, innerException).GetHttpCode() == 500))
            {
                var viewName = "AllOtherExceptions";
                if (typeof(DivideByZeroException).IsInstanceOfType(innerException))
                {
                    viewName = "DivideByZeroException";
                }

                string controllerName = (string)filterContext.RouteData.Values["controller"];
                string actionName = (string)filterContext.RouteData.Values["action"];
                HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
                ViewResult result = new ViewResult
                {
                    ViewName = viewName,
                    ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
                    TempData = filterContext.Controller.TempData
                };
                filterContext.Result = result;
                filterContext.ExceptionHandled = true;
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.StatusCode = 500;
                filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
            }
        }
    }
}

и затем зарегистрировать его:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new MyHandleErrorAttribute());
}
0 голосов
/ 26 января 2012

Проверьте ответ страха ниже. Конечно, проще, если это работает.

Так как это произошло через несколько недель, вот как мой фильтр наконец-то прописал, используя ответ Дарина и включив отчеты Элмы, с кодом из этой темы.

Я до сих пор не знаю, почему нельзя установить свойства для глобального фильтра действий.

public class MyHandleErrorAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        if (!filterContext.IsChildAction &&
            (!filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled))
        {
            var innerException = filterContext.Exception;
            if ((new HttpException(null, innerException).GetHttpCode() == 500))
            {
                var viewName = "GeneralError";
                if (typeof (HttpAntiForgeryException).IsInstanceOfType(innerException))
                    viewName = "SecurityError";

                var controllerName = (string) filterContext.RouteData.Values["controller"];
                var actionName = (string) filterContext.RouteData.Values["action"];
                var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
                var result = new ViewResult
                                        {
                                            ViewName = viewName,
                                            ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
                                            TempData = filterContext.Controller.TempData
                                        };

                filterContext.Result = result;
                filterContext.ExceptionHandled = true;
                filterContext.HttpContext.Response.Clear();
                filterContext.HttpContext.Response.StatusCode = 500;
                filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;

 //From here on down, this is all code for Elmah-reporting.
                var version = Assembly.GetExecutingAssembly().GetName().Version;
                filterContext.Controller.ViewData["Version"] = version.ToString();

                var e = filterContext.Exception;
                if (!filterContext.ExceptionHandled // if unhandled, will be logged anyhow
                    || RaiseErrorSignal(e) // prefer signaling, if possible
                    || IsFiltered(filterContext)) // filtered?
                    return;

                LogException(e);
            }
        }
    }

    private static bool RaiseErrorSignal(Exception e)
    {
        HttpContext context = HttpContext.Current;
        if (context == null)
            return false;
        var signal = ErrorSignal.FromContext(context);
        if (signal == null)
            return false;
        signal.Raise(e, context);
        return true;
    }

    private static bool IsFiltered(ExceptionContext context)
    {
        var config = context.HttpContext.GetSection("elmah/errorFilter")
                     as ErrorFilterConfiguration;

        if (config == null)
            return false;

        var testContext = new ErrorFilterModule.AssertionHelperContext(
            context.Exception, HttpContext.Current);

        return config.Assertion.Test(testContext);
    }

    private static void LogException(Exception e)
    {
        HttpContext context = HttpContext.Current;
        ErrorLog.GetDefault(context).Log(new Error(e, context));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...