欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.Net Core MVC中过滤器简介

程序员文章站 2023-11-13 13:53:22
在.Net Framework MVC 中有四种过滤器,授权过滤器(Authorize)、Action 过滤器、结果过滤器(Result)、异常过滤器(Exception)四种过滤器。在.Net Core MVC中,有五种过滤器,授权过滤器、Action过滤器、异常过滤器、结果过滤器、资源过滤器,新 ......

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

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

.Net Core MVC中过滤器简介

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

 

.Net Core MVC中过滤器简介

 

结果过滤器,包装了单个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);
             }
         }
     }
 }