Asp.Net Core Filter 深入浅出的那些事-AOP
一、前言
在分享ASP.NET Core Filter 使用之前,先来谈谈AOP,什么是AOP 呢?
AOP全称Aspect Oriented Programming意为面向切面编程,也叫做面向方法编程,是通过预编译方式和运行期动态代理的方式实现不修改源代码的情况下给程序动态统一添加功能的技术。
AOP技术利用一种称为“横切”的技术,剖解开封装对象的内部,将影响多个类的公共行为封装到一个可重用的模块中,并将其命名为Aspect切面。所谓的切面,简单来说就是与业务无关,却为业务模块所共同调用的逻辑,将其封装起来便于减少系统的重复代码,降低模块的耦合度,有利用未来的可操作性和可维护性。
利用AOP可以对业务逻辑各个部分进行隔离,从而使业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高开发效率。
AOP的使用场景主要包括日志记录、性能统计、安全控制、事务处理、异常处理等。

二、Filter-过滤器
Filter是延续ASP.NET MVC的产物,同样保留了五种的Filter,分别是Authorization Filter、Resource Filter、Action Filter、Exception Filter及Result Filter。
通过不同的Filter可以有效处理封包进出的加工,本篇将介绍ASP.NET Core的五种Filter运作方式。
2.1 Filter 介绍
ASP.NET Core 有以下五种Filter 可以使用:
- Authorization Filter:
Authorization是五种Filter中优先级最高的,通常用于验证Request合不合法,不合法后面就直接跳过。 - Resource Filter:Resource是第二优先,会在Authorization之后,Model Binding之前执行。通常会是需要对Model加工处理才用。
 - Exception Filter:异常处理的Filter。
 - Action Filter:最常使用的Filter,封包进出都会经过它,使用上没什么需要特别注意的。跟Resource Filter很类似,但并不会经过Model Binding。
 - Result Filter:当Action完成后,最终会经过的Filter。

 
三、五大Filter 的应用
这一篇章主要来讲解Asp.Net Core 的五大过滤器的实现及用途.
3.1 Authonization Filter
权限控制过滤器
通过 Authonization Filter 可以实现复杂的权限角色认证、登陆授权等操作
实现事例代码如下:
    public class AuthonizationFilter :Attribute,IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            //这里可以做复杂的权限控制操作
            if (context.HttpContext.User.Identity.Name != "1") //简单的做一个示范
            {
                //未通过验证则跳转到无权限提示页
                RedirectToActionResult content = new RedirectToActionResult("NoAuth", "Exception", null);
                context.Result = content;
            }
        }
    }
3.2 Resource Filter
资源过滤器
可以通过Resource Filter 进行资源缓存、防盗链等操作。
使用Resource Filter 要求实现IResourceFilter 抽象接口
   public class ResourceFilter : Attribute,IResourceFilter
    {
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
            // 执行完后的操作
        }
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            // 执行中的过滤器管道
        }
    }
3.3 Exception Filter
通过Execption Filter 过滤器可以进行全局的异常日志收集 等操作。
使用Execption Filter 要求实现IExceptionFilter 抽象接口
IExceptionFilter接口会要求实现OnException方法,当系统发生未捕获异常时就会触发这个方法。OnException方法有一个ExceptionContext异常上下文,其中包含了具体的异常信息,HttpContext及mvc路由信息。系统一旦出现未捕获异常后,比较常见的做法就是使用日志工具,将异常的详细信息记录下来,方便修正调试。下面是日志记录的实现。  
  public class ExecptionFilter : Attribute, IExceptionFilter
  {
        private ILogger<ExecptionFilter> _logger;
        //构造注入日志组件
        public ExecptionFilter(ILogger<ExecptionFilter> logger)
        {
            _logger = logger;
        }
        public void OnException(ExceptionContext context)
        {
            //日志收集
            _logger.LogError(context.Exception, context?.Exception?.Message??"异常");
        }
    }
3.4 Action Filter
作用:可以通过ActionFilter 拦截 每个执行的方法进行一系列的操作,比如:执行操作日志、参数验证,权限控制 等一系列操作。
使用Action Filter 需要实现IActionFilter 抽象接口,IActionFilter 接口要求实现OnActionExecuted 和OnActionExecuting 方法
    public class ActionFilter : Attribute, IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context)
        {
            //执行完成....
        }
        public void OnActionExecuting(ActionExecutingContext context)
        {
            //执行中...
        }
    }
3.5 Result Filter
结果过滤器,可以对结果进行格式化、大小写转换等一系列操作。
使用Result Filter 需要实现IResultFilter 抽象接口,接口要求实现
OnResultExecuting 方法 和OnResultExecuted 方法
OnResultExecuting:Called before the action result executes. 在操作结果执行之前调用OnResultExecuted:Called after the action result executes. 在操作结果执行之后调用
具体代码实现代码如下:
public class ResultFilter : Attribute, IResultFilter
 {
        public void OnResultExecuted(ResultExecutedContext context)
        {
            // 在结果执行之后调用的操作...
        }
        public void OnResultExecuting(ResultExecutingContext context)
        {
            // 在结果执行之前调用的一系列操作
        }
    }
四、Asp.Net Core 过滤器的注册方式
这一篇章主要来分析探讨Asp.Net Core 中过滤器的三种注册方式Action、Controller、全局 。
4.1 Action 注册方式
Action 注册方式是局部注册方式,针对控制器中的某个方法上标注特性的方式进行注册,代码如下:
 [AuthonizationFilter()]
 public IActionResult Index()
 {
            return View();
 }
4.2 Controller 注册方式
了解过Action 特性注册方式的同学,一定发现了它的不好之处就是我一个控制器里面需要使用同一套Filter 的时候,需要一个一个Action 标注特性注册,是不是很繁琐呢?有没有其他方式进行代替这些繁琐的操作呢?微软给我们提供了简便的控制器标注注册方式,代码如下:
 [AuthonizationFilter()]
 public class FirstController : Controller
  {
        private ILogger<FirstController> _logger;
        public FirstController(ILogger<FirstController> logger)
        {
            _logger = logger;
        }
        public IActionResult Index()
        {
            return View();
        }
 }
4.3 全局注册方式
现在有些同学考虑了一些全局的情况,比如我要全局处理系统中的异常,或者收集操作日志等,需要全局注册一个ExceptionFilter 来实现,就不需要每一个Controller 中进行代码注册,方便快捷。代码如下:
 public void ConfigureServices(IServiceCollection services)
  {
            //全局注册异常过滤器
            services.AddControllersWithViews(option=> {
                option.Filters.Add<ExecptionFilter>();
            });
            services.AddSingleton<ISingletonService, SingletonService>();
}
4.4 TypeFilter 和 ServiceFilter 注册方式
上面的五大过滤器中事例代码中其中有一个过滤器的代码比较特,再来回顾ExceptionFilter过滤器的实现代码:
    public class ExecptionFilter : Attribute, IExceptionFilter
    {
        private ILogger<ExecptionFilter> _logger;
        //构造注入日志组件
        public ExecptionFilter(ILogger<ExecptionFilter> logger)
        {
            _logger = logger;
        }
        public void OnException(ExceptionContext context)
        {
            //日志收集
            _logger.LogError(context.Exception, context?.Exception?.Message??"异常");
        }
    }
从上面的代码中可以发现 ExceptionFilter 过滤器实现中存在日志服务的构造函数的注入,也就是说该过滤器依赖于其他的日志服务,但是日志服务都是通过DI 注入进来的;再来回顾下上面Action 注册方式或者Controller 注册方式 也即Attribute 特性标注注册方式,本身基础的特性是不支持构造函数的,是在运行时注册进来的,那要解决这种本身需要对服务依赖的过滤器需要使用 TypeFilter 或者ServiceFilter 方式进行过滤器的标注注册。
TypeFilter 和ServiceFilter 的区别。
- ServiceFilter和TypeFilter都实现了IFilterFactory
 - ServiceFilter需要对自定义的Filter进行注册,TypeFilter不需要
 - ServiceFilter的Filter生命周期源自于您如何注册,而TypeFilter每次都会创建一个新的实例
 
TypeFilter 使用方式
代码如下:
[TypeFilter(typeof(ExecptionFilter))]
public IActionFilter Index2()
{
      return View();
}
通过上面的代码可以发现AuthonizationFilter 是默认的构造器,但是如果过滤器中构造函数中存在参数,需要注入服务那该怎么办呢?,比如上面的ExceptionFilter 代码,就不能使用这种方式进行注册,需要使用服务特性的方式,我们可以选择使用 代码如下:
[TypeFilter(typeof(ExecptionFilter))]
public IActionFilter Index2()
{
           return View();
}
ServiceFilter 使用方式
控制器中的代码如下:
[ServiceFilter(typeof(ExecptionFilter))]
public IActionFilter Index2()
{
           return View();
}
注册服务的代码如下:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
       Console.WriteLine("ConfigureServices");
       services.AddControllersWithViews();
       //services.AddControllersWithViews(option=> {
       //    option.Filters.Add<ExecptionFilter>();
       //});
        //注册过滤器服务,使用ServiceFilter 方式必须要注册 否则会报没有注册该服务的相关异常
        services.AddSingleton<ExecptionFilter>();
}
												
											Asp.Net Core Filter 深入浅出的那些事-AOP的更多相关文章
- [译]如何在ASP.NET Core中实现面向切面编程(AOP)
		
原文地址:ASPECT ORIENTED PROGRAMMING USING PROXIES IN ASP.NET CORE 原文作者:ZANID HAYTAM 译文地址:如何在ASP.NET Cor ...
 - ASP.NET Core Filter与IOC的羁绊
		
前言 我们在使用ASP.NET Core进行服务端应用开发的时候,或多或少都会涉及到使用Filter的场景.Filter简单来说是Action的拦截器,它可以在Action执行之前或者之后对请求信息进 ...
 - (7)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- 利用Polly+AOP+依赖注入封装的降级框架
		
创建简单的熔断降级框架 要达到的目标是: 参与降级的方法参数要一样,当HelloAsync执行出错的时候执行HelloFallBackAsync方法. public class Person { [H ...
 - ASP.NET Core 3.0 使用AspectCore-Framework实现AOP
		
AspectCore是适用于Asp.Net Core 平台的轻量级Aop(Aspect-oriented programming)解决方案,它更好的遵循Asp.Net Core的模块化开发理念,使用A ...
 - Asp.net Core Filter过滤器异常处理
		
本文旨在: 1 继承ExceptionFilterAttribute,重写Override OnException(ExceptionContext context)处理异常 2 在.netCore中 ...
 - ASP.NET Core 2.1的配置、AOP、缓存、部署、ORM、进程守护、Nginx、Polly【源码】
		
ps:废话不多说.直接上代码:源码地址:https://github.com/786744873/Asp.Net-Core-2.1-All-Demos/tree/master/src Configur ...
 - Asp.net Core 3.1基于AspectCore实现AOP,实现事务、缓存拦截器
		
最近想给我的框架加一种功能,就是比如给一个方法加一个事务的特性Attribute,那这个方法就会启用事务处理.给一个方法加一个缓存特性,那这个方法就会进行缓存. 这个也是网上说的面向切面编程AOP. ...
 - Asp.Net Core Endpoint 终结点路由之中间件应用
		
一.概述 这篇文章主要分享Endpoint 终结点路由的中间件的应用场景及实践案例,不讲述其工作原理,如果需要了解工作原理的同学, 可以点击查看以下两篇解读文章: Asp.Net Core EndPo ...
 - Asp.Net Core 进阶(四)—— 过滤器 Filters
		
一.介绍 Asp.Net Core Filter 使得可以在请求处理管道的特定阶段的前后执行代码,我们可以创建自定义的 filter 用于处理横切关注点. 横切关注点的示例包括错误处理.缓存.配置.授 ...
 
随机推荐
- 【shell基础】条件测试
			
例1 判断目录是否存在 #!/usr/bin/bash back_dir=/var/mysql_back if ! test -d $back_dir;then mkdir -p $back_dir ...
 - 00 - 准备 Anaconda 环境
			
Anaconda 环境 官方下载安装包:https://www.anaconda.com/download/ Anaconda Navigtor :用于管理工具包和环境的图形用户界面,后续涉及的众多管 ...
 - [HNOI2003]操作系统 优先队列用法
			
题:https://www.cometoj.com/problem/1046 #include<bits/stdc++.h> using namespace std; typedef lo ...
 - 【学习笔记】 Johnson 全源最短路
			
前置扯淡 一年多前学的最短路,当时就会了几个名词的拼写,啥也没想过 几个月之前,听说了"全源最短路"这个东西,当时也没说学一下,现在补一下(感觉实在是没啥用) 介绍 由于\(spf ...
 - Div水平垂直居中的三种方法
			
百度了很多种方法,很多是不起作用的.下面这些方法是我亲自试过的.希望对大家有帮助! 下面是一波代码水军. <!DOCTYPE html> <html lang="en&qu ...
 - iOS自定义弹出视图、收音机APP、图片涂鸦、加载刷新、文件缓存等源码
			
iOS精选源码 一款优秀的 聆听夜空FM 源码 zhPopupController 简单快捷弹出自定义视图 WHStoryMaker搭建美图(贴纸,涂鸦,文字,滤镜) iOS cell高度自适应 有加 ...
 - 分布式全局唯一ID与自增序列
			
包含时间顺序的ID 此场景最简单的实现方案,就是采用 twitter 的 Snowflake 算法.ID总长64位,第1位不可用,41位表示时间戳,10位表示生成机器的id,后12位表示序列号. 为什 ...
 - Horizon公司环境
 - 用户增删改查 django生命周期 数据库操作
			
一 django生命周期 1 浏览器输入一个请求(get/post)2 响应到django程序中3 执行到url,url通过请求的地址匹配到不同的视图函数4 执行对应的视图函数,此过程可以查询数据库, ...
 - CF-1110C-Meaningless Operations
			
题意: 输入q,然后输入q个a,对于每个a,找到一个b,使gcd(a ^ b, a & b)最大,输出这个最大的gcd: 思路: 用k表示a二进制最高位的二进制编号,1,2,4,8对应1,2, ...