忽略ASP.NET MVC4 CustomErrors DefaultRedirect

the*_*ors 13 asp.net-mvc asp.net-mvc-3 asp.net-mvc-4

我有一个MVC 4应用程序,使用自定义HandleErrorAttribute来处理自定义异常.我想截取默认的404和其他非500错误页面,并用更有吸引力的东西替换它们.为此,我在Web.config中添加了以下内容:

<system.web>
    <customErrors mode="On" defaultRedirect="~/Error/Index" />
...
</ system.web>
Run Code Online (Sandbox Code Playgroud)

我有一个带有索引方法和相应视图的错误控制器,但我仍然得到默认的404错误页面.我也试过设置我defaultRedirect的静态html文件无济于事.我已经尝试添加特定于404内部的错误处理<customErrors>,我甚至尝试以编程方式修改路由,所有这些都没有结果.我错过了什么?为什么ASP忽略我的默认错误处理?

注意:我之前注意到我无法在本地测试我的CustomHandleErrorAttribute,即使是<customErrors mode="On".当我在我的服务器上从我的开发盒中点击它时它确实有效...不确定这是否相关. 这家伙有同样的问题.

Nir*_*edi 14

这应该工作:

1. Web.Config

<customErrors mode="On"
   defaultRedirect="~/Views/Shared/Error.cshtml">

  <error statusCode="403"
    redirect="~/Views/Shared/UnauthorizedAccess.cshtml" />

  <error statusCode="404"
    redirect="~/Views/Shared/FileNotFound.cshtml" />

</customErrors>
Run Code Online (Sandbox Code Playgroud)

2.将FilterleErrorAttribute注册为FilterConfig类中的全局操作过滤器,如下所示

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new CustomHandleErrorAttribute());
        filters.Add(new AuthorizeAttribute());
    }
Run Code Online (Sandbox Code Playgroud)

如果那不起作用,请尝试通过检查状态代码(例如Global.asax中的以下内容)来转移响应:至少它必须工作.

void Application_EndRequest(object sender, EventArgs e)
{
    if (Response.StatusCode == 401)
    {
        Response.ClearContent();
        Server.Transfer("~/Views/Shared/UnauthorizedAccess.cshtml");
    }
}
Run Code Online (Sandbox Code Playgroud)


Ima*_*ani 6

我的主题很少.我认为解释这一点有点重要.

在此输入图像描述

如果你注意上面突出显示的部分.我已经指定了Action Filter的顺序.这基本上描述了Action Filter的执行顺序.当您通过Controller/Action Method实现多个Action Filters时,就会出现这种情况

在此输入图像描述

这张照片只是表明你有两个动作过滤器.OnActionExecution将开始执行优先级,OnActionExecuted并将从底部到顶部开始.这意味着如果OnActionExecuted动作过滤器具有最高顺序将首先执行,并且如果OnActionExecuting动作过滤器具有最低顺序将首先执行.以下示例.

public class Filter1 : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
Run Code Online (Sandbox Code Playgroud)

//执行将从这里开始 - 1

        base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
Run Code Online (Sandbox Code Playgroud)

//执行将移到这里 - 5

        base.OnActionExecuted(filterContext);
    }
}

public class Filter2 : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
Run Code Online (Sandbox Code Playgroud)

//执行将移到这里 - 2

        base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
Run Code Online (Sandbox Code Playgroud)

//执行将移到这里 - 4

        base.OnActionExecuted(filterContext);
    }
}

[HandleError]
public class HomeController : Controller
{
    [Filter1(Order = 1)]
    [Filter2(Order = 2)]
    public ActionResult Index()
    {
Run Code Online (Sandbox Code Playgroud)

//执行将移到这里 - 3

        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

您可能已经意识到MVC框架中有不同类型的过滤器.它们列在下面.

  1. 授权过滤器

  2. 动作过滤器

  3. 响应/结果过滤器

  4. 异常过滤器

在每个过滤器中,您可以指定Order属性.这基本上描述了动作过滤器的执行顺序.

回到原始查询

这适合我.这非常简单,无需考虑Web.Config中的任何更改或在Global.asax文件中注册Action Filter.

好.所以,首先我要创建一个简单的动作过滤器.这将处理Ajax和非Ajax请求.

public class MyCustomErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        filterContext.ExceptionHandled = true;
        var debugModeMsg = filterContext.HttpContext.IsDebuggingEnabled
                               ? filterContext.Exception.Message +
                                 "\n" +
                                 filterContext.Exception.StackTrace
                               : "Your error message";
Run Code Online (Sandbox Code Playgroud)

// 当您需要处理Ajax请求时就是这种情况

        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.Result = new JsonResult
            {
                JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                Data = new
                {
                    error = true,
                    message = debugModeMsg
                }
            };
        }
Run Code Online (Sandbox Code Playgroud)

// 处理非Ajax请求时就是这种情况

        else
        {
            var routeData = new RouteData();
            routeData.Values["controller"] = "Error";
            routeData.Values["action"] = "Error";
            routeData.DataTokens["area"] = "app";
            routeData.Values["exception"] = debugModeMsg;
            IController errorsController = new ErrorController();
            var exception = HttpContext.Current.Server.GetLastError();
            var httpException = exception as HttpException;
            if (httpException != null)
            {
                Response.StatusCode = httpException.GetHttpCode();
                switch (System.Web.HttpContext.Current.Response.StatusCode)
                {
                    case 404:
                        routeData.Values["action"] = "Http404";
                        break;
                }
            }

            var rc = new RequestContext
                         (
                             new HttpContextWrapper(HttpContext.Current),
                             routeData
                         );
            errorsController.Execute(rc);
        }
        base.OnException(filterContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以在Controller上以及仅在Action上实现此Action Filter.示例:

在此输入图像描述

希望这对你有帮助.