如何在MVC 5中使用异常过滤器

时间:2014-06-13 09:17:06

标签: asp.net asp.net-mvc-5 visual-studio-2013

我如何在MVC5中实现异常过滤器。

我想将异常抛给NLog,并将页面重定向到默认错误页面,显示"出错了"

我有一个Filter类,如下所示

using System;
using System.Diagnostics;
using System.Security.Policy;
using System.Web.Mvc;
using System.Web.Mvc.Filters;
using System.Web.Routing;
using System.Web.UI.WebControls;
using Delivros.UI.Controllers;
using Delivros.UI.Areas.User.ViewModel;
using System.Web;

namespace Delivros.UI.Filters
{

public class CustomAuthenticationFilter : IAuthenticationFilter
{
    public void OnAuthentication(AuthenticationContext filterContext)
    {

    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {
        Debug.WriteLine("OnAuthenticationChallenge : MyAuthenticationFilter");
    }
}
 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MyAuthorizationFilter : AuthorizeAttribute
{
     public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Request.Cookies[System.Configuration.ConfigurationManager.AppSettings[Convert.ToString(CookieField.cookieName)]] == null)
        {

        }
        else
{
            filterContext.Result = new RedirectToRouteResult(
            new RouteValueDictionary 
    {
                { "controller", "User" }, 
                { "action", "UserRegistration" } ,
                {"Area","User"}
            });

        }
    }
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CustomActionFilter : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false);
        filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        filterContext.HttpContext.Response.Cache.SetNoStore();
        base.OnResultExecuted(filterContext);
        filterContext.Result = new RedirectToRouteResult(
              new RouteValueDictionary 
            { 
                { "controller", "User" }, 
                { "action", "UserRegistration" } ,
                {"Area","User"}
            });
        // ActionResult home = new HomeController().Index();           
    }
}

public class MyResultFilter : IResultFilter
{
    public void OnResultExecuting(ResultExecutingContext filterContext)
    {

    }

    public void OnResultExecuted(ResultExecutedContext filterContext)
    {

    }
}

public class MyExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        filterContext.Result = new RedirectToRouteResult(
              new RouteValueDictionary 
            { 
                { "controller", "User" }, 
                { "action", "UserLogOut" } ,
                {"Area","User"}
            });

    }
}

}

但没有任何内容重定向到页面......

4 个答案:

答案 0 :(得分:20)

您可以派生自己的HandleErrorAttribute

public class NLogExceptionHandlerAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        // log error to NLog
        base.OnException(filterContext);
    }
}

然后全局注册

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

默认情况下,HandleErrorAttribute会显示位于Error文件夹中的~/Views/Shared视图,但如果您想要显示特定视图,则可以设置View属性属性。

答案 1 :(得分:1)

我认为应该是这段代码:

salary

}

您可以添加额外的" if(!filterContext.ExceptionHandled)"在记录结果中的值之前的语句,以确保暂时未处理异常。

答案 2 :(得分:0)

仅当在操作方法内引发未处理的异常时,才运行异常过滤器。如您所问,这是一个异常时重定向到另一个页面的示例:

public class MyExceptionAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        if(!filterContext.ExceptionHandled)
        {
            filterContext.Result = new RedirectResult("~/Content/ErrorPage.html");
            filterContext.ExceptionHandled = true;
        }    
    }
}

现在,要将此过滤器应用于控制器或单个动作,请在其上放置[MyException]。

您可能需要检查if子句中特定异常的发生。 例如:

if(... && filterContext.Excaption is ArgumentOutOfRangeException)

要返回“视图作为异常响应”:

filterContext.Result = new RedirectResult("/Home/ErrorAction");

您可能会使用的其他替代方法是:

  • 新的RedirectToRouteResult {...}
  • 新的ViewResult {...}

答案 3 :(得分:0)

以下为我工作。需要注意的几件事1)RedirectResult指向控制器动作,而不是视图2)您需要设置filterContext.ExceptionHandled = true;否则您的例外视图/页面将不会显示。

public class ErrorAttribute : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        Log.Logger.Error(filterContext.Exception, "An Unhandled exeption occured durring the execution of a request");

        filterContext.Result = new RedirectResult("~/MyControler/MyErrorAction");
        filterContext.ExceptionHandled = true;
    }

}

当然,您还需要使用Global.asax中的GlobalFilters对象注册Error属性,如下所示。

 protected void Application_Start()
 {
     GlobalFilters.Filters.Add(new ErrorAttribute());           
     ...
 }