zoukankan      html  css  js  c++  java
  • ASP.NET MVC IActionFilter IResultFilter IExceptionFilter/HandleError

    一、IActionFilter

    1、基本定义

      在action的执行前后进行AOP拦截。

    IActionFilter接口定义如下:
    public interface IActionFilter
    {
      //执行方法之前   
    void OnActionExecuted(ActionExecutedContext filterContext);   //----> ActionInvoke(xxxx) <-----执行Actin方法   
      //执行方法之后
      void OnActionExecuting(ActionExecutingContext filterContext);
    }

    2、实现方式

    (1)、控制器重写IActionFilter实现方法

      控制器已经实现了接口IActionFilter,每次请求都会创建一个Controller实例,而且只执行一个Action方法,所以可以在控制器层次进行拦截,这样重载了的控制器的每个Action都会被拦截,Controller的定义如下:

      public abstract class Controller : ControllerBase, IActionFilter, IAuthenticationFilter, IAuthorizationFilter, IDisposable,IExceptionFilter, IResultFilter, IAsyncController, IController, IAsyncManagerContainer

      所以,我们只需要重写已经实现的IActionFilter的两个方法,如下:

    protected override void OnActionExecuting(ActionExecutingContext filterContext)
            {
                var contrllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
    
                var actionName = filterContext.ActionDescriptor.ActionName;
    
                var parameter = filterContext.ActionDescriptor.GetParameters();
    
                filterContext.HttpContext.Response.Write(contrllerName + "_" + actionName);
    
                base.OnActionExecuting(filterContext);
            }
    
            protected override void OnActionExecuted(ActionExecutedContext filterContext)
            {
                base.OnActionExecuted(filterContext);
            }

    (2)、定义一个FilterAttribute

      定义Attribute放到不同的Action

     public class MyCustomAttribute : FilterAttribute, IActionFilter
        {
            public void OnActionExecuted(ActionExecutedContext filterContext)
            {
    
            }
    
            public void OnActionExecuting(ActionExecutingContext filterContext)
            {
                //1.如果result不为空,那么就return了。不执行递归。。。
                filterContext.Result = new ViewResult()
                {
                    ViewName = "Error"
                };
            }
        }

    (3)、Global全局注入

      每一个action上面加特性,比较麻烦,我们可以选择进行全局的注入。

    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    
            public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                filters.Add(new HandleErrorAttribute());
    
                filters.Add(new MyCustomAttribute());
            }

    二、IResultFilter

    1、基本概念

      Action的返回值有几下几种,他们都是继承自ActionResult,其主要作用是对Action的执行结果进行转换,如利用内容协商,把结果数据序列化为指定格式的数据。

      ActionView、 ViewResult、JsonResult、ContentResult

      

      ActionResult定义如下:

      public abstract class ActionResult
      {
            public abstract void ExecuteResult(ControllerContext context);
      }

      在ActionResult的执行(调用ExecuteResult方法)前后进行AOP拦截。

      接口定义如下:

    public interface IResultFilter
        {
            void OnResultExecuted(ResultExecutedContext filterContext);
            void OnResultExecuting(ResultExecutingContext filterContext);
        }

     2、实现方式

      同IActionFilter一样,有三种方式

      (1)、Controller上Override的

      public abstract class Controller : ControllerBase, IActionFilter, IAuthenticationFilter, IAuthorizationFilter, IDisposable,IExceptionFilter, IResultFilter, IAsyncController,     IController, IAsyncManagerContainer

       public class HomeController : Controller
        {
            protected override void OnResultExecuting(ResultExecutingContext filterContext)
            {
               base.OnResultExecuting(filterContext);
            }
    
            protected override void OnResultExecuted(ResultExecutedContext filterContext)
            {
                base.OnResultExecuted(filterContext);
            }
        }

      (2)、继承FilterAttribute,IResultFilter或ActionFilterAtrribute

    public class MyActionFilterAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
              base.OnResultExecuting(filterContext);
         }
    
         public override void OnResultExecuted(ResultExecutedContext filterContext)
         {
               base.OnResultExecuted(filterContext);
        }

      (3)、GlobleFilters 全局的注册

      同IActionFilter

    三、 IExceptionFilter HandleError

    1、基本概念

      IExceptionFilter定义如下

    public interface IExceptionFilter
        {
            void OnException(ExceptionContext filterContext);
        }

      public abstract class Controller : ControllerBase, IActionFilter, IAuthenticationFilter, IAuthorizationFilter, IDisposable,IExceptionFilter, IResultFilter, IAsyncController,     IController, IAsyncManagerContainer

      Controller抽象类,接口IExceptionFilter的实现,空的

      protected virtual void OnException(ExceptionContext filterContext)
      {
      }

      HandleError是IExceptionFilter在MVC中的默认实现,也是默认注册在全局 

     public class FilterConfig
        {
            public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                filters.Add(new HandleErrorAttribute());
            }
        }

      HandleError当出现异常时候,转到一个错误页面,其源代码如下:

    public virtual void OnException(ExceptionContext filterContext)
        {
          if (filterContext == null)
            throw new ArgumentNullException(nameof (filterContext));
          if (filterContext.IsChildAction || filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
            return;
          Exception exception = filterContext.Exception;
          if (new HttpException((string) null, exception).GetHttpCode() != 500 || !this.ExceptionType.IsInstanceOfType((object) exception))
            return;
          string controllerName = (string) filterContext.RouteData.Values["controller"];
          string actionName = (string) filterContext.RouteData.Values["action"];
          HandleErrorInfo model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
          ExceptionContext exceptionContext = filterContext;
        //构造一个ViewResult,跳转到其对应View页面 ViewResult viewResult1
    = new ViewResult(); viewResult1.ViewName = this.View; viewResult1.MasterName = this.Master; viewResult1.ViewData = (ViewDataDictionary) new ViewDataDictionary<HandleErrorInfo>(model); viewResult1.TempData = filterContext.Controller.TempData; ViewResult viewResult2 = viewResult1; exceptionContext.Result = (ActionResult) viewResult2;
        //ExceptionHandled标记已经处理 filterContext.ExceptionHandled
    = true; filterContext.HttpContext.Response.Clear();
        //定义500错误 filterContext.HttpContext.Response.StatusCode
    = 500; filterContext.HttpContext.Response.TrySkipIisCustomErrors = true; }
        public string View
        {
          get
          {
         //view为空就是Error页面,Share文件夹下的Error.cshtml
    if (string.IsNullOrEmpty(this._view)) return "Error"; return this._view; } set { this._view = value; } }

      

    2、扩展例子

      不仅要错误页面,还要记录日志到数据库

     public class MyHandleErrorAttribute : FilterAttribute, IExceptionFilter// HandleErrorAttribute
        {
            public void OnException(ExceptionContext filterContext)
            {
                //记录日志。。。。my logic
                filterContext.ExceptionHandled = true;
            
    //这个要设置为true,要不会继续抛出异常
    base.OnException(filterContext); } }

      

       public class HomeController : Controller
        {
            [MyHandleError]
            public ActionResult Index()
            {
                throw new Exception("");
                return View();
            }
    }

       配置Web.config

      <configuration>
      <system.web>
             <customErrors mode="On"/>
      </system.web>
      </configuration>

      可以直接跳到错误页面,要不直接显示红色的错误,黄色页。

  • 相关阅读:
    loj2042 「CQOI2016」不同的最小割
    loj2035 「SDOI2016」征途
    luogu2120 [ZJOI2007]仓库建设
    luogu3195 [HNOI2008]玩具装箱TOY
    51nod 1069 Nim游戏 + BZOJ 1022: [SHOI2008]小约翰的游戏John(Nim游戏和Anti-Nim游戏)
    HDU 5723 Abandoned country(最小生成树+边两边点数)
    BZOJ 1497: [NOI2006]最大获利(最大权闭合图)
    51nod 1615 跳跃的杰克
    SPOJ 839 Optimal Marks(最小割的应用)
    UVa 11107 生命的形式(不小于k个字符串中的最长子串)
  • 原文地址:https://www.cnblogs.com/shawnhu/p/8417560.html
Copyright © 2011-2022 走看看