【asp.net core 系列】10 实战之ActionFilter
0.前言
在上一篇中,我们提到了如何创建一个UnitOfWork并通过ActionFilter设置启用。这一篇我们将简单介绍一下ActionFilter以及如何利用ActionFilter,顺便补齐一下上一篇的工具类。
1. ActionFilter 介绍
ActionFilter全称是ActionFilterAttribute,我们根据微软的命名规范可以看出这是一个特性类,看一下它的声明:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class ActionFilterAttribute : Attribute, IActionFilter, IFilterMetadata, IAsyncActionFilter, IAsyncResultFilter, IOrderedFilter, IResultFilter
这是一个允许标注在类和方法上的特性类,允许多个标记,标注之后子类会继承父类的特性。然后,这个类是一个抽象类,所以我们可以通过继承ActionFilterAttribute来编写自己的ActionFilter。
1.1 ActionFilter的四个方法
对于一个ActionFilter而言,最重要的是它的四个方法:
public virtual void OnActionExecuted(ActionExecutedContext context);
public virtual void OnActionExecuting(ActionExecutingContext context);
public virtual void OnResultExecuted(ResultExecutedContext context);
public virtual void OnResultExecuting(ResultExecutingContext context);
上图是这四个方法在一次请求中执行的顺序。在一次请求真正执行之前,想要拦截这个请求,应该使用OnActionExecuting
。
为什么单独说这个呢?因为这个方法的出镜率很高,大多数时候都会使用这个方法进行请求过滤。
1.2 在ActionFilter中我们能做什么
我们来简单介绍一下,四个方法中的四种上下文类型,看一看里面有哪些我们可以利用的方法:
1.2.1 ActionExecutingContext
这是一个Action执行前的上下文,表示Action并未开始执行,但是已经获取到了控制器实例:
public class ActionExecutingContext : FilterContext
{
public virtual IDictionary<string, object> ActionArguments { get; }
public virtual object Controller { get; }
public virtual IActionResult Result { get; set; }
}
ActionExecutingContext继承自FilterContext,我们暂且不关注它的父类,只看一下它自己的属性。
- ActionArguments 表示Action的参数列表,这里面放着各种从用户接到请求参数以及其他中间处理程序添加的参数
- Controller 表示执行该请求的控制器,在之前我们提过,asp.net core 对于控制器的限制很小,所以控制器什么类型都可能,故而这里使用object作为控制器类型
- Result 执行结果,正常情况下,在此处获取这个属性的值没有意义。但是我们可以通过修改这个属性的值,来让我们拦截请求
1.2.2 ActionExecutedContext
ActionExecutedContext 表示Action执行完成后的上下文,这时候Action已经执行完成,我们可以通过这个获取Action执行结果:
public class ActionExecutedContext : FilterContext
{
public virtual bool Canceled { get; set; }
public virtual object Controller { get; }
public virtual Exception Exception { get; set; }
public virtual ExceptionDispatchInfo ExceptionDispatchInfo { get; set; }
public virtual bool ExceptionHandled { get; set; }
public virtual IActionResult Result { get; set; }
}
同样,继承自FilterContext,暂且忽略。
- Canceled 表示是否被设置短路
- Controller 处理请求的控制器
- Exception 执行过程中是否发生异常,如果有异常则 有值,否则为Null
- ExceptionHandled 异常是否被处理
- Result 此处对Result进行修改不会屏蔽执行的ActionResult,但是可以向用户隐藏对应的实现
1.2.3 ResultExecutingContext
这是在Result渲染之前执行的上下文,这时候Action已经执行完毕,正准备渲染Result:
public class ResultExecutingContext : FilterContext
{
public virtual bool Cancel { get; set; }
public virtual object Controller { get; }
public virtual IActionResult Result { get; set; }
}
- Cancel 取消当前结果执行以及后续筛选器的执行
- Controller 控制器
- Result 处理结果
1.2.4 ResultExecutedContext
Result已经执行完成了,获取执行结果上下文:
public class ResultExecutedContext : FilterContext
{
public virtual bool Canceled { get; set; }
public virtual object Controller { get; }
public virtual Exception Exception { get; set; }
public virtual ExceptionDispatchInfo ExceptionDispatchInfo { get; set; }
public virtual bool ExceptionHandled { get; set; }
public virtual IActionResult Result { get; }
}
这个类与 ActionExecutedContext类似,就不做介绍了。
1.2.5 FilterContext
在上面的四个上下文都继承自 FilterContext,那么我们来看一下FilterContext中有哪些属性或者方法:
public abstract class FilterContext : ActionContext
{
public virtual IList<IFilterMetadata> Filters { get; }
public TMetadata FindEffectivePolicy<TMetadata>() where TMetadata : IFilterMetadata;
}
可以看到FilterContext继承了另一个ActionContext的类。小伙伴们应该对这个类要有一定的概念,这个类是Action的上下文类。它完整存在于一个Action的生命周期,所以有时候可以通过ActionContext进行Action级的数据传递(不推荐)。
那么,继续让我们回过头来看看ActionContext里有什么:
public class ActionContext
{
public ActionDescriptor ActionDescriptor { get; set; }
public HttpContext HttpContext { get; set; }
public ModelStateDictionary ModelState { get; }
public RouteData RouteData { get; set; }
}
- ActionDescriptor 执行的Action描述信息,包括Action的显示名称、一些参数等,具体用到的时候,再为大伙详细说
- HttpContext 可以通过这个属性获取此次请求的Request和Response对象
- ModelState 模型校验信息, 这部分在后续再为小伙伴们细说
- RouteData 路由信息,asp.net core 在处理请求时解析出来的路由信息,包括在程序中修改的路由信息
2. 使用ActionFilter
在《【asp.net core 系列】9 实战之 UnitOfWork以及自定义代码生成》也就是上一篇中,介绍到了ActionFilter与普通特性类一致,可以通过标注控制器然后启用该ActionFilter。
因为大多数情况下,一个ActionFilter并不会仅仅局限于一个控制器,而是应用于多个控制器。所以这时候,我们通常会设置一个基础控制器,在这个控制器上进行标注,然后让子类继承这个控制器。通过这种方式来实现一次声明多次使用。
当然,在asp.net core 中添加了另外的一种使用ActionFilter的方式,Setup.cs中
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
}
默认是这样的,我们可以通过设置参数来添加一个全局应用的Filter,例如说我们上一篇中创建的 UnitOfWorkFilterAttribute:
services.AddControllersWithViews(options=>
{
options.Filters.Add<UnitOfWorkFilterAttribute>();
});
通过这种方式可以启用一个全局ActionFilter。如果需要使用asp.net core的默认依赖注入可以使用 AddService进行配置。(依赖注入的内容在后续会讲解)。
3. 工具类生成
继续上一篇遗留的内容:
public static void CreateEntityTypeConfig(Type type)
{
var targetNamespace = type.Namespace.Replace("Data.Models", "");
if (targetNamespace.StartsWith("."))
{
targetNamespace = targetNamespace.Remove(0);
}
var targetDir = Path.Combine(new[] { CurrentDirect, "Domain.Implements", "EntityConfigures" }.Concat(
targetNamespace.Split('.')).ToArray());
if (!Directory.Exists(targetDir))
{
Directory.CreateDirectory(targetDir);
}
var baseName = type.Name.Replace("Entity", "");
if (!string.IsNullOrEmpty(targetNamespace))
{
targetNamespace = $".{targetNamespace}";
}
var file = $"using {type.Namespace};" +
$"\r\nusing Microsoft.EntityFrameworkCore;" +
$"\r\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;" +
$"\r\nnamespace Domain.Implements.EntityConfigures{targetNamespace}" +
"\r\n{" +
$"\r\n\tpublic class {baseName}Config : IEntityTypeConfiguration<{type.Name}>" +
"\r\n\t{" +
"\r\n\t\tpublic void Configure(EntityTypeBuilder<SysUser> builder)" +
"\r\n\t\t{" +
$"\r\n\t\t\tbuilder.ToTable(\"{baseName}\");" +
$"\r\n\t\t\tbuilder.HasKey(p => p.Id);" +
"\r\n\t\t}\r\n\t}\r\n}";
File.WriteAllText(Path.Combine(targetDir, $"{baseName}Config.cs"), file);
}
工具类其实本质上就是一次文件写入的方法,本身没什么难度。
不过,这里还有有个小问题,每次调用都会覆盖原有的文件,还有就是这里面有很多可以优化的地方,小伙伴们可以自己试试去优化一下,让代码更好看一点。
4 总结
到目前为止,实战系列也有了几篇,很多小伙伴问我能提供一下源码吗?当然,能呀。不过不是现在,容我留个谜底。当主要框架功能完成之后,我就会给小伙伴们发代码的。
其实也是因为现在还没个完整的,开放给小伙伴们也没啥意义。当然了,跟着一块敲,也是能实现的哈。关键地方的代码都有。
更多内容烦请关注我的博客《高先生小屋》
【asp.net core 系列】10 实战之ActionFilter的更多相关文章
- asp.net core 系列 10 配置configuration (上)
一. ASP.NET Core 中的配置概述 ASP.NET Core 中的应用配置是基于键值对,由configuration 程序提供. configuration 将从各种配置源提供程序操作键 ...
- 【目录】asp.net core系列篇
随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...
- asp.net core 系列 16 Web主机 IWebHostBuilder
一.概述 在asp.net core中,Host主机负责应用程序启动和生存期管理.host主机包括Web 主机(IWebHostBuilder)和通用主机(IHostBuilder).Web 主机是适 ...
- 【asp.net core 系列】6 实战之 一个项目的完整结构
0. 前言 在<asp.net core 系列>之前的几篇文章中,我们简单了解了路由.控制器以及视图的关系以及静态资源的引入,让我们对于asp.net core mvc项目有了基本的认识. ...
- 【asp.net core 系列】8 实战之 利用 EF Core 完成数据操作层的实现
0. 前言 通过前两篇,我们创建了一个项目,并规定了一个基本的数据层访问接口.这一篇,我们将以EF Core为例演示一下数据层访问接口如何实现,以及实现中需要注意的地方. 1. 添加EF Core 先 ...
- 1.1专题介绍「深入浅出ASP.NET Core系列」
大家好,我是IT人张飞洪,专注于.NET平台十年有余. 工作之余喜欢阅读和写作,学习的内容包括数据结构/算法.网络技术.Linux系统原理.数据库技术原理,设计模式.前沿架构.微服务.容器技术等等…… ...
- asp.net core系列 40 Web 应用MVC 介绍与详细示例
一. MVC介绍 MVC架构模式有助于实现关注点分离.视图和控制器均依赖于模型. 但是,模型既不依赖于视图,也不依赖于控制器. 这是分离的一个关键优势. 这种分离允许模型独立于可视化展示进行构建和测试 ...
- asp.net core系列 39 Web 应用Razor 介绍与详细示例
一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor. 这样开发Web包括了MVC框架和Razor框架.对于Razor来说 ...
- asp.net core系列 36 WebAPI 搭建详细示例
一.概述 HTTP不仅仅用于提供网页.HTTP也是构建公开服务和数据的API强大平台.HTTP简单灵活且无处不在.几乎任何你能想到的平台都有一个HTTP库,因此HTTP服务可以覆盖广泛的客户端,包括浏 ...
随机推荐
- jpype2
# -*- coding: utf-8 -*-# @Time : 2020/5/21 0:04# 从环境变量获取jvm虚拟机安装路径,若为None则获取默认路径import os import jpy ...
- web自动化之执行js脚本
from selenium import webdriver from selenium.webdriver.support.wait import WebDriverWait from seleni ...
- 彻底理解JavaScript ES6中的import和export
0.前言 前端工程,在最早的时候是没有模块的概念的.随着前端工程的发展,前端开发也越来越规范化,更像是软件工程了.那么随之而来的,为了解决工程化的问题,就引入了模块的概念.但是在早期,因为ecmasc ...
- [SD心灵鸡汤]010.每月一则 - 2016.02
1.世上只有一种英雄主义,就是在认清生活真相之后依然热爱生活. 2.要想赢,就一定不能怕输.不怕输,结果未必能赢.但是怕输,结果则一定是输. 3.你要做的就是别人换不掉的,那你做不到怪谁,就是你自己没 ...
- GDI泄漏排查经验零散总结
1.GDI对象以及释放方法: GDI对象 产生方法 销毁方法 位图(HBITMAP) CreateBitmap,CreateBitmapIndirect, CreateCompatibleBitmap ...
- Beta冲刺——代码规范与计划
这个作业属于哪个课程 软件工程 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.代码规范 采用ShowDoc网站进行编 ...
- Rocket - tilelink - Atomics
https://mp.weixin.qq.com/s/TSwKL_qm-b-0e8x7r--hhg 简单介绍Atomics中数学运算.逻辑运算的实现. 1. io Atomics ...
- 利用jieba库画词云
from wordcloud import WordCloud import matplotlib.pyplot as plt import jieba # 生成词云 def create_word_ ...
- Java写算法题中那些影响你效率的细节(关于暴力破解算法题的细节处理)
QQ讨论群:99979568 多交流才能进步 暂时写到这里,有不懂的欢迎评论, 如果有什么其他提高效率的细节,欢迎评论或者私信我,小编一定努力学习,争取早日分享给大家 如果大家嫌三连累的话,可以看看这 ...
- Java实现 蓝桥杯VIP基础练习 矩形面积交
描述 平面上有两个矩形,它们的边平行于直角坐标系的X轴或Y轴.对于每个矩形,我们给出它的一对相对顶点的坐标,请你编程算出两个矩形的交的面积. 输入 输入仅包含两行,每行描述一个矩形. 在每行中,给出矩 ...