在.net framework mvc 中有四种过滤器,授权过滤器(authorize)、action 过滤器、结果过滤器(result)、异常过滤器(exception)四种过滤器。在.net core mvc中,有五种过滤器,授权过滤器、action过滤器、异常过滤器、结果过滤器、资源过滤器,新增了资源过滤器。

.net core mvc和.net framework mvc在基本使用上差别不大,主要的还是框架的差别。其中路由是个很重要的东西,参考文章:

action过滤器、结果过滤器、exception,三个特性,没有什么变化。在exceptionfilter多了个order参数,就是用来排序的。

 

 

结果过滤器,包装了单个action result的执行,当且晋档action方法成功执行完毕后才运行。它们是理想的围绕视图执行或格式处理的逻辑(所在之处)。继承attribute,iresultfilter

 /// <summary>
 /// result的filter
 /// </summary>
 public class customresultfilterattribute : attribute, iresultfilter
 {
     //private logger logger = logger.createlogger(typeof(customresultfilterattribute));
     public void onresultexecuted(resultexecutedcontext context)
     {
         console.writeline("onresultexecuted executed!");
         //logger.info("onresultexecuted executed!");
     }

     public void onresultexecuting(resultexecutingcontext context)
     {
         console.writeline("onresultexecuting executing!");
         //logger.info("onresultexecuting executing!");
     }
 }

异常过滤器,为mvc隐藏程序为处理异常应用全局策略。继承exceptionfilterattribute

 /// <summary>
 /// 异常处理的filter
 /// </summary>
 public class customexceptionfilterattribute : exceptionfilterattribute
 {
     private readonly ihostingenvironment _hostingenvironment;
     private readonly imodelmetadataprovider _modelmetadataprovider;
     //private logger logger = logger.createlogger(typeof(customexceptionfilterattribute));

     /// <summary>
     /// ioc来的
     /// </summary>
     /// <param name="hostingenvironment"></param>
     /// <param name="modelmetadataprovider"></param>
     public customexceptionfilterattribute(
         ihostingenvironment hostingenvironment,
         imodelmetadataprovider modelmetadataprovider)
     {
         _hostingenvironment = hostingenvironment;
         _modelmetadataprovider = modelmetadataprovider;
     }

     /// <summary>
     /// 没有处理的异常,就会进来
     /// </summary>
     /// <param name="filtercontext"></param>
     public override void onexception(exceptioncontext filtercontext)
     {
         if (!filtercontext.exceptionhandled)//异常有没有被处理过
         {
             string controllername = (string)filtercontext.routedata.values["controller"];
             string actionname = (string)filtercontext.routedata.values["action"];
             string msgtemplate = "在执行 controller[{0}] 的 action[{1}] 时产生异常";
             //logger.error(string.format(msgtemplate, controllername, actionname), filtercontext.exception);
             if (this.isajaxrequest(filtercontext.httpcontext.request))//检查请求头
             {
                 filtercontext.result = new jsonresult(
                      new
                      {
                          result = false,
                          promptmsg = "系统出现异常,请联系管理员",
                          debugmessage = filtercontext.exception.message
                      }//这个就是返回的结果
                 );
             }
             else
             {
                 var result = new viewresult { viewname = "~/views/shared/error.cshtml" };
                 result.viewdata = new viewdatadictionary(_modelmetadataprovider, filtercontext.modelstate);
                 result.viewdata.add("exception", filtercontext.exception);
                 filtercontext.result = result;
             }
             filtercontext.exceptionhandled = true;
         }
     }


     private bool isajaxrequest(httprequest request)
     {
         string header = request.headers["x-requested-with"];
         return "xmlhttprequest".equals(header);
     }
 }

定义完exceptionfilter,该怎么注册到全局呢?在stratup.cs中configureserver中,进行注册

services.addmvc(o =>
{
    o.filters.add(typeof(customexceptionfilterattribute));// 这里就是全局注册filter

}).setcompatibilityversion(compatibilityversion.version_2_2);

action 过滤器,包装了对单个action方法的调用,可以将参数传递给action并从中获得action result。继承iactionfilter

 /// <summary>
 /// action的filter`
 /// </summary>
 public class customactionfilterattribute : attribute, iactionfilter
 {
     private ilogger<customactionfilterattribute> _logger = null;
     public customactionfilterattribute(ilogger<customactionfilterattribute> logger)
     {
         this._logger = logger;
     } 
     public void onactionexecuted(actionexecutedcontext context)
     {
         //context.httpcontext.response.writeasync("actionfilter executed!");
         console.writeline("actionfilter executed!");
         //this._logger.logdebug("actionfilter executed!");
     } 
     public void onactionexecuting(actionexecutingcontext context)
     {
         //context.httpcontext.response.writeasync("actionfilter executing!");
         console.writeline("actionfilter executing!");
         //this._logger.logdebug("actionfilter executing!");
     }
 }

在startup.cs中configureservices进行注册

 //允许使用servicefilter 标记特性
 services.addscoped<customactionfilterattribute>();

标记到controller的actionfilter

/// <summary>
/// 标记到controller
/// </summary>
public class customcontrolleractionfilterattribute : attribute, iactionfilter
{
    private ilogger<customcontrolleractionfilterattribute> _logger = null;
    public customcontrolleractionfilterattribute(ilogger<customcontrolleractionfilterattribute> logger)
    {
        this._logger = logger;
    }
    public void onactionexecuted(actionexecutedcontext context)
    {
        //context.httpcontext.response.writeasync("actionfilter executed!");
        console.writeline("actionfilter executed!");
        //this._logger.logdebug("actionfilter executed!");
    }
    public void onactionexecuting(actionexecutingcontext context)
    {
        //context.httpcontext.response.writeasync("actionfilter executing!");
        console.writeline("actionfilter executing!");
        //this._logger.logdebug("actionfilter executing!");
    }
}
 [typefilter(typeof(customcontrolleractionfilterattribute),order =-1)]
 public class thirdcontroller : controller
 {
}

注册到全局的actionfilter

public class customglobalactionfilterattribute : attribute, iactionfilter
{
    private ilogger<customglobalactionfilterattribute> _logger = null;
    public customglobalactionfilterattribute(ilogger<customglobalactionfilterattribute> logger)
    {
        this._logger = logger;
    }
    public void onactionexecuted(actionexecutedcontext context)
    {
        //context.httpcontext.response.writeasync("actionfilter executed!");
        console.writeline("actionfilter executed!");
        //this._logger.logdebug("actionfilter executed!");
    }
    public void onactionexecuting(actionexecutingcontext context)
    {
        //context.httpcontext.response.writeasync("actionfilter executing!");
        console.writeline("actionfilter executing!");
        //this._logger.logdebug("actionfilter executing!");
    }
}

还是要在startup中进行全局的注册

services.addmvc(o =>
{
    o.filters.add(typeof(customglobalactionfilterattribute));// 这里就是全局注册filter

}).setcompatibilityversion(compatibilityversion.version_2_2);

分别对全局、控制器、action注册了actionfilter默认执行顺序:

  全局onactionexecuting===》控制器的onactionexecuting====》action的onactionexecuting====》执行action ====》action的onactionexecuted====》控制器的onactionexecuted====》全局的onactionexecuted。类似于一个俄罗斯套娃,也可以说是一个洋葱模型。

资源过滤器,是授权之后第一个用来处理请求的过滤器,也是最后一个接触到请求的过滤器(因为之后就会离开过滤器管道)。在性能方面,资源过滤器在实现缓存或短路过滤器管道尤其有用。继承iresourcefilter

 /// <summary>
 /// 自定义的资源filter
 /// </summary>
 public class customresourcefilterattribute : attribute, iresourcefilter
 {
     private static readonly dictionary<string, object> _cache = new dictionary<string, object>();
     private string _cachekey;
     /// <summary>
     /// 控制器实例化之前
     /// </summary>
     /// <param name="context"></param>
     public void onresourceexecuting(resourceexecutingcontext context)
     {
         _cachekey = context.httpcontext.request.path.tostring();
         if (_cache.containskey(_cachekey))
         {
             var cachedvalue = _cache[_cachekey] as viewresult;
             if (cachedvalue != null)
             {
                 context.result = cachedvalue;
             }
         }
     }
     /// <summary>
     /// 把请求都处理完的
     /// </summary>
     /// <param name="context"></param>
     public void onresourceexecuted(resourceexecutedcontext context)
     {
         if (!string.isnullorempty(_cachekey) &&
             !_cache.containskey(_cachekey))
         {
             var result = context.result as viewresult;
             if (result != null)
             {
                 _cache.add(_cachekey, result);
             }
         }
     }
 }