【问题标题】:ASP.net MVC - Custom HandleError Filter - Specify View based on Exception TypeASP.net MVC - 自定义 HandleError 过滤器 - 根据异常类型指定视图
【发布时间】:2011-11-15 23:37:11
【问题描述】:

我在我的 MVC 应用程序中继承了 HandleErrorAttribute,因此我可以记录错误:

public class HandleAndLogErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        base.OnException(filterContext);

        if( filterContext.Exception != null )
        {
            // log here
        }
    }
}

我将其添加为全局过滤器:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleAndLogErrorAttribute());
}

是否也可以为特定的异常类型指定自定义视图?例如:

if( filterContext.Exception is DivideByZeroException )
{
    // how do i specify that the view should be DivideByZero?
}

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-3


    【解决方案1】:
    1. 创建一个继承HandleErrorAttribute的新过滤器(或直接实现IExceptionFilter)
    2. 在 global.asax 中注册(替换filters.Add(new HandleError());):

    这是我创建的一个过滤器,它试图根据特定的 HTTP 状态代码查找视图:

    public class MyErrorHandler : FilterAttribute, IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {
            if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
                return;
    
            var statusCode = (int) HttpStatusCode.InternalServerError;
            if (filterContext.Exception is HttpException)
            {
                statusCode = filterContext.Exception.As<HttpException>().GetHttpCode();
            }
            else if (filterContext.Exception is UnauthorizedAccessException)
            {
                //to prevent login prompt in IIS
                // which will appear when returning 401.
                statusCode = (int)HttpStatusCode.Forbidden; 
            }
            _logger.Error("Uncaught exception", filterContext.Exception);
    
            var result = CreateActionResult(filterContext, statusCode);
            filterContext.Result = result;
    
            // Prepare the response code.
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.Clear();
            filterContext.HttpContext.Response.StatusCode = statusCode;
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
        }
    
        protected virtual ActionResult CreateActionResult(ExceptionContext filterContext, int statusCode)
        {
            var ctx = new ControllerContext(filterContext.RequestContext, filterContext.Controller);
            var statusCodeName = ((HttpStatusCode) statusCode).ToString();
    
            var viewName = SelectFirstView(ctx,
                                           "~/Views/Error/{0}.cshtml".FormatWith(statusCodeName),
                                           "~/Views/Error/General.cshtml",
                                           statusCodeName,
                                           "Error");
    
            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),
                             };
            result.ViewBag.StatusCode = statusCode;
            return result;
        }
    
        protected string SelectFirstView(ControllerContext ctx, params string[] viewNames)
        {
            return viewNames.First(view => ViewExists(ctx, view));
        }
    
        protected bool ViewExists(ControllerContext ctx, string name)
        {
            var result = ViewEngines.Engines.FindView(ctx, name, null);
            return result.View != null;
        }
    }
    

    【讨论】:

    • 这会处理哪些 HTTP 状态代码?我的印象是 404 永远不会被错误过滤器捕获,您需要使用 来捕获它们。
    • 所有通过 HttpException 生成的。
    • 不错的解决方案 - 我特别喜欢它保留有关违规控制器和操作的信息。发送!
    • 您说“1. 创建一个继承 HandleErrorAttribute 的新过滤器”,但这不是您在示例中所做的。
    • 我不是要侮辱或争论,我只是认为您应该编辑您的帖子,因为从技术上讲,您不是从 HandleErrorAttribute 继承的。 IExceptionFilter 不继承自 HandleErrorAttribute
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多