开始

解决上节课put和delete的问题

上节课的小尾巴没讲的put和delete的问题。
image.png
后端这里也放开
image.png
之前不能访问的原因是由于不能跨域,加上传输的数据格式不对,就会发生put和delete不能访问的问题。
现在我们把跨域和apiController都加上了。
加上断点测试。
image.png
上节课已经设置了跨域
image.png
put
image.png
进入断点
image.png
delete也进入断点了
image.png

httpGet请求传多个参数

image.png
image.png
1和ace
image.png
image.png

image.png
参数和参数之间用横线也是可以的
image.png
image.png

image.png

路由Route加到action上

image.png
image.png
输入home/16
image.png
image.png
把最上面的Route注释掉,只用第一个Action的Route
image.png
把其他方法都注释掉。以免引起错误。
image.png
image.png
路径后面直接传一个1
image.png

这样就传过来了
image.png

本节课开始-过虑器

过滤器的本质是AOP,面向切面编程

创建测试项目

image.png
image.png
image.png
image.png
双击Form。在Form加载时候使用
image.png
在form加载时使用,直接拿过来
image.png
i小于10才能弹窗。这样无疑给我的getInfo方法增加了权限的配置。这样对getInfo方法单一的职责产生了污染。本来职责就是弹个窗
image.png
不希望getInfo单一的逻辑产生污染。那就在没有到getInfo的时候先做判断。
image.png

aop的注册方式

有3中注册方式。
1,方法上注册
2.类上面注册
3.全局注册、
创建Filters文件夹
image.png
创建类
image.png
实现接口Attribute,只有加上这个接口,我的类才可以在方法或者类上面加这个特性。
image.png
这样就可以做为一个特性加到方法上面去了。
image.png
再继承IActionFilter才可以面向切面。
image.png
实现里面的接口
image.png

打开另外一个演示demo

继承了这俩之后,
image.png
image.png
权限的判断,如果没有权限就显示Form4
image.png
Form4里面
image.png
label改成您没有权限
image.png
启动程序测试
image.png
弹出了Form4。Form2就没法再打开了。
image.png
注释掉这句话
image.png
image.png
点击按钮打开就是Form2
image.png

继续

下面我们要做日志的输出
image.png
运行测试,报错
image.png
这里的action已经加上了这个Attribute
image.png
移到最下面
image.png
路由也先去掉了。
image.png
运行程序测试,还是有这个错误
image.png
把Route路由再放开注释,
image.png
因为下面的这些方法都没有加路由,所以必须要有一个路由。
image.png
image.png
image.png

控制台没有输出
image.png
这里加上断点
image.png
再来测试
image.png
进入了断点。
image.png
走过了console的代码
image.png
用cmd窗体那种启动项目的方式会输出到控制台,因为我们这里不是在控制台,所以看不到输出的信息,
后面我们应写日志的方式输出。

类上使用

在类上使用无论是调用哪个Action都会进入filter
image.png
image.png
进入了断点。OnActionExecuting方法内。
image.png
然后会进入Action的方法内。
image.png
方法再走完,会进入到OnActionExecuted方法内。
image.png
对我们的delte方法同样有用。
image.png
因为我们的特性直接加载Controller上的,所以里面所有方法都可以使用这个Attribute
image.png

中间件中注册Aop

注册服务是对全局使用
在AddControllers里面注册,使用o.FIlters.Add 里面不能直接写我们的Filter
image.png
里面接收的是一个FilterType
image.png
所以这里我们要写上typeof里面是我们的filter
image.png
测试。这样无论访问哪个方法都会触发
启动测试,打开默认的页面时候就触发了。
image.png

image.png
因为我们在项目最初调用的就是这个,在这个里面会重定向到我们的swagger里面。
image.png
走完filter里面两个方法后,才会进去swagger页面。
image.png
在注册aop的filter的顺序是什么?
方法、类、全局注册。

先走到全局、再走到类里面、再走到中间方法里面。

image.png

创建全局Filter

添加一个Global的
image.png
把我们之前的filter的代码 全复制过来。
image.png
把Global的Filter全局注册。
image.png
原来的还是在Controller里面使用。
image.png
分别在这两个Filter上加上断点
image.png

image.png
启动程序,默认就走到了全局这里
image.png
全局走完打开了首页。
image.png

image.png
先走的全局
image.png
然后到了普通的filter的 OnActionExecuting
image.png
再走,到了具体的action方法
image.png
走完之后到了。普通的filter的OnActionExecuted
image.png
再走到了全局的OnActionExecuted
image.png

类似于这个结构,最上面是全局的Executing 最下面是全局的Executed。
中间生菜 上面生菜是类的Executing ,下面生菜是类的Executed。
最中间的肉是action方法。

image.png

这个是dotnet的mvc和webapi的管道模型。
image.png

dotnetCore的管道模型
image.png
要结合着下面这个来看。下面这个是中间件。中间件类似一个俄罗斯套娃。先进去后出。
image.png
Config里面有很多的app.Use 这些都是中间件。
image.png
中间件的顺序也是 先进去,最后再出来。先进的后出。
image.png
跨域一定要写在Routing的下面。如果写在前面,路由还在没加载呢 就要跨域肯定是没用的。
image.png

image.png
Module binding是controller控制器的实例化
image.png
资源加载器的根结尾,Result filter
image.png

Exception Filter

Exception Filter用来捕获异常。

创建认证的Filter
image.png
前面在家一个Ctm
image.png
image.png
创建Exception的Filter
image.png
实现接口,并加断点。
image.png
创建资源管理的Filter:CtmResourceFilterAttribute
image.pngimage.png
加上断点
image.png
在HomeController里面把这几个Filter都加上
image.png
来看下执行的顺序
image.png
先到了认证的Filter
image.png
然后进入Resource
image.png
进入了ActionFilter
image.png
到了action里面
image.png

action的Executed
image.png
resource的Executed
image.png
走完。

这里之前加过action的Filter
image.png
image.png

会发现一个问题,从头到尾没有走Exception的Filter。它是用来捕获异常的
ExceptionFilter在权限和资源的Filter的下面。那么在ExceptionFilter下面的内容我们都可以捕获。上面的权限认证和资源的Filter可能捕获不到。
image.png
下面来验证我们上面的猜想。
手动的在action里面抛出一个异常。
image.png
测试下。
image.png
顺序还是先走的权限。
image.png

直到走到action里面,手动的抛出异常的代码了
image.png

异常出现了
image.png
再往下走
image.png

image.png
再走。到了异常的Filter。这个时候就捕获到了异常信息。
image.png

异常放到ActionFilter里面。

image.png
image.png

逐步的走到达异常的地方
image.png
发生异常
image.png
发生错误后,再往下走
image.png
到了ExceptionFilter
image.png

异常放在ResourceFilter

image.png
再来测试
image.png
显示认证的
image.png
image.png
发生错误
image.png
发生错误后,再往下走
image.png
直接跳到页面上了。因为Resource加载时间优于Exception。ExceptionFilter还没有加载呢,所以肯定是捕获不到的。
image.png

异常放在权限里面

image.png
再来测试
image.png
报错了,继续往下走
image.png
再走还是跳到了首页
image.png

异常放在Resource的Executed里面

image.png

image.png

image.png
报错了继续往下走
image.png
也是捕获不到。
image.png

比喻成一个面包。上下两层,手拿着捏面包,只有中间的才会漏出来,被异常捕获。虽然是上下两层,但是它是一个递归。Resource整体还是在Exception之前执行。
image.png

继续-演示winForm里面的aop

dotnetFramework的aop的形式
之前创建的AopDemo
image.png
这里启动 Form1
image.png
添加一个窗体
image.png
image.png
在Form1的窗体上,加一个按钮上去。然后双击写代码
image.png

添加一个文件夹Filters
image.png
添加一个类。
image.png
静态类。
image.png
image.png如果我们要给他增加一个特性
image.png
image.png
继承Attribute
image.png
这个aop就是在加载窗体的时候改变窗体的Text的值。
image.png
这里要对传入的对象进行查找
image.png
获取Form的Type
image.png
type是否包含FormFilterAttribute
image.png
true表示是否查找它的派生类。 这就是我们判断这个类上面有没有我们需要的FormFilter的Attribute
image.png
获取它的Attribute
image.png
前面需要强制转换成(FormFilterAttribute)
image.png
attribute里面有个Executing方法,把form传进去。
image.png
这块代码就可以从我们的Form的类里面获取Filter,并且调用Filter里面的数据。
image.png
没个调用form表单的地方替换掉。
image.png
image.png
form1的类上面加上attribute
image.png
需要传个参数。
image.png
启动测试
image.png
这里加个断点
image.png
运行后,进入到了这里
image.png
继续往下走。这样我们的表头就改变了。
image.png
扩展几个方法。
image.png
直接调用showWithAop传入当前的form2
image.png
方法改成showDialogWithAop
image.png
image.png
image.png
点击按钮
image.png
进入到了这里
image.png
往下走,调用了Form2
image.png
判断form的name不是form1就Dispose不展示,
image.png
再来新建一个窗体
image.png
新建叫做form3
image.png

image.png
启动测试,报错
image.png
这里加个断点
image.png
首先进来的是form1
image.png
Name是Form
image.png
我们要获取的是它对象的名称
image.png
改成大写的Form1
image.png
再来测试,还是报错
image.png
这里改成不等于
image.png
点击
image.png
image.png
走到了这里
image.pngimage.png

image.png
上面的写法就是正常的dotnetFramework的aop的Filter反编译过来就是这么个展现形式
和现在dotnetCore的aop比起来比较low

讲解

先去找存不存在继承的接口的方法,如果找到了继承接口的方法,这个时候就从我的这个类上面找到AttributeFilter。那么就开始读取Filter并调用Filter里面的Executing方法。
image.png
然后把这个方法写到我要显示Control的委托的上面。
image.png
让它执行我这个control或者执行action的时候,先执行我们的aop的method
传进去的是一个control和一个上下文。我们可以根据上下文对控制器或者action进行判断,判断是否符合我们的规范或者权限。没有权限就跳转到无权限的页面。
image.png

打断点来看下顺序

image.png
这里再加个断点
image.png
启动测试
image.png

启动先进这里
image.png
往里走
image.png
逐过程,到了这里
image.png

在这里加个断点
image.png
重新启动程序。
image.png
image.png
这里再加个断点
image.png
然后就直接跳到这里了,RunApp
image.png
image.png
获取Form1的type类型,这里是反射。
image.png
image.png
看下这个类上,存不存在一个叫做FormFilterAttribute的特性。
image.png
存在就往下走了
image.png
获取自定义的特性。FormFilterAttribute是我们自己写的,也就是我们自定义的特性。
image.png
获取到这个特性之后,需要强制转换为FormFilterAttribute
image.png
因为我们的FOrmFilterAttribute继承自我们的Attribute
image.png
那么就可以获取里面的Executing方法。
image.png
然后就进入我们的Execuiting方法。
image.png
最终展现出来title被替换了。
image.png

当点击button1

触发了事件
image.png
image.png

image.png
image.png
我们当前是form2
image.png

最终展现的就是Form3
image.png

回到WebApiDemo

F12进入IResourceFilter
image.png
image.png
接口里面有两个没有实现的方法
image.png
IFilterMetadata作为标记,还作为一个集合去使用。
image.png
我们后台这么多的Filter都存放在哪呢?他是存在IFilterMetaData的数组里面,
它可以作为一个容器去使用,把我们所有的Filter全部获取到,放到IFilterMetaData这样的一个数组里面。作为一个集合去使用,作为一个容器去使用。
image.png
只要继承了IFilterMetaData它必然就是一个过滤器。在这里它是作为一个标记去使用的。
在aop filter框架里面,它又作为集合去使用,所以只要是过滤器,它都要继承IFilterMetadata。

再次回到winFormDemo

这里先都注释掉
image.png
先来做几个Filter
image.png
命名空间加上Core把RunWithAop移到Core的文件夹下。
image.png
CtmActionFilterAttribute也移动到Filters的文件夹下。
image.png
加上命名空间
image.png
在Core下面创建接口
image.png
image.png
再来创建一个IResourceFilter
image.png
再来创建IFilterMatedata
image.png
接口内什么不写,作为标记和容器使用
image.png
IActionFilter继承IFilterMatedata
image.png
IResourceMatedata也继承IFilterMatedata
image.png
接口内创建两个方法
image.png
内也是加俩方法,和dotnetcore里面的filter方法很类似。
image.png
那么我们的CtmActionFilterAttribute就继承Attribute和IActionFilter
image.png
然后实现IActionFilter内的接口方法
image.png
再来添加一个CtxResourceAttribute
image.png
image.png
继承这俩并实现接口。
image.png
这样我们两个AOP就搞定了。和webApiDemo里面的AOP是一样的

准备写核心代码

上面就是准备工作做好了,下面开始写核心的代码了。
添加类FilterInvoke。在这里实现所有核心的代码。
image.png
首先来确认下流程大概是什么样的
下面是要执行的流程。如果读过源码的就知道它是用switch的语句来执行顺序的走向。
image.png
新建枚举,理想中有这四个环节就够了
image.png
下一步通过构造方法传入我们所必要的数据

凡是用到Filter特性,必然用到反射,反射根据什么获取到特性呢?就是跟我们的标记位。
说白了就是凡是有这个IFilterMateData接口的都是Filter,反射的时候会根据这个标志位来判断。标志位既是作为查找Filter的使用,也是作为存储标志位的使用。即作为容器也作为标记。
image.png

后续下一节课。

结束