不同的过滤器类型会在执行管道的不同阶段运行,因此他们各自有一套自己的应用场景。可以根据不同的业务需求和在请求管道中的执行位置来选择合适创建的过滤器。运行与MVC Action调用管道内的过滤器有时候被称为过滤管道,当MVC选择要执行哪一个Action的时候,就会调用当前Action上的过滤器。
过滤器作用域
过滤器有三个作用域
1、Action过滤器,可以在Action上增加过滤器,那么过滤器将会针对当前的Action有效;
2、Controllers过滤器,可以在Controllers控制器上增加过滤器,那么过滤器将会针对当前控制器下的所有Action有效
3、全局过滤器,在你配置 MVC 的时候在 Startup 的 ConfigureServices 如下方法,将会在全局生效
过滤器可以通过类型添加,也可以通过实例添加。如果通过实例添加,改实例将会被用于每一个请求。如果通过类型添加,则将会 type-activated(意思是说每次请求都会创建一个实例,其所有构造函数依赖项都将通过 DI 来填充)
////配置全局过滤器 services.AddMvc(options => { //ResourceFilter为过滤器名 //通过类型添加 options.Filters.Add(typeof(ResourceFilter)); //通过实例添加 options.Filters.Add(new ResourceFilter()); });
对于.netCore来说过滤器大概分为以下5种
1、授权过滤器:用于确定当前用户是否合法,常用作用户登录及其权限处理。Authorize
在具体的控制器方法上面增加特性Authorize,然后需要在Startup.cs文件中的ConfigureServices方法中启动授权过滤器(因为默认是不启动的),
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); //启动授权过滤器,并且设置存储数据为cookie,如果cookie失效则跳转到登录页面 services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme). AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o => { //如果cookie失效则跳转到登录页面 o.LoginPath = new PathString("/Home/Login"); }); }
在登录时,需要将用户信息存储在授权cookie中去
public IActionResult DoLogin() { /* * 登录以后获取token, * 获取传递的token,去用户信息 * */ string token = "123456"; string name = "张三"; ClaimsIdentity identity = new ClaimsIdentity("Forms"); identity.AddClaim(new Claim(ClaimTypes.Sid, token)); identity.AddClaim(new Claim(ClaimTypes.Name, name)); //将用户信息存储在授权cookie中 ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(identity); HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,claimsPrincipal); return Content("登录成功"); }
在需要进行授权验证的控制器或者Action方法上面增加授权特性,当用户没有cookie授权时,就会跳转到登录页面
//登录授权验证 [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] public IActionResult Index() { //业务逻辑 UserModel user = new UserModel() { Name = "张三" }; ViewBag.Sex = "男"; return View(user); }
2、资源过滤器:是授权之后第一个用来处理请求的过滤器,也是最后一个接触到请求的过滤器(因为之后就会离开过滤器管道)。在性能方面,自愿过滤器在实现缓存或者短路过滤器管道尤其有用。继承:IResourceFitter或者异步IAsyncResourceFilter
使用时将当前过滤器以特性的方式增加在控制器或者Action方法上: [ResourceFilter]
public class ResourceFilter : Attribute, IResourceFilter { /// <summary> /// 管道调用后执行 /// </summary> /// <param name="context"></param> public void OnResourceExecuted(ResourceExecutedContext context) { } /// <summary> /// 管道调用前执行 /// </summary> /// <param name="context"></param> public void OnResourceExecuting(ResourceExecutingContext context) { // context.Result = new ContentResult() { Content="结束执行"}; } }
异步资源过滤器
public class ResourceFilter : Attribute, IAsyncResourceFilter { /// <summary> /// 在Action执行前后调用 /// </summary> /// <param name="context"></param> /// <param name="next"></param> /// <returns></returns> public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) { await next(); } }
3、Action过滤器:包装了对单个action方法的调用,可以将参数传递给action并从中获得actionresult。继承:IActionFitter或者异步IAsyncActionFilter
使用时将当前过滤器以特性的方式增加在控制器或者Action方法上: [ActionFilter]
public class ActionFilter : Attribute, IActionFilter { /// <summary> /// 管道调用后执行 /// </summary> /// <param name="context"></param> public void OnActionExecuted(ActionExecutedContext context) { } /// <summary> /// 管道调用前执行 /// </summary> /// <param name="context"></param> public void OnActionExecuting(ActionExecutingContext context) { context.Result = new ContentResult() { Content="方法执行没有权限" }; } }
异步Action过滤器
public class ActionFilter : Attribute, IAsyncActionFilter { /// <summary> /// 管道调用后执行 /// </summary> /// <param name="context"></param> public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { await next(); } }
4、异常过滤器:为MVC应用程序未处理异常应用策略。继承:ExceptionFitterAttribute或者异步IAsyncExceptionFilter
使用时将当前过滤器以特性的方式增加在控制器或者Action方法上: [ExceptionFilter]
public class ExceptionFilter: ExceptionFilterAttribute { public override void OnException(ExceptionContext context) { // context.Result = new ContentResult() { Content = "系统发生错误" }; } }
异步异常过滤器
public class ExceptionFilter: Attribute, IAsyncExceptionFilter { public async Task OnExceptionAsync(ExceptionContext context) { await next(); } private Task next() { throw new NotImplementedException(); } }
5、结果过滤器:包装了单个actionresult的执行,当且仅当action方法成功执行完毕后才能运行。他们是理想的围绕视图执行或格式处理的逻辑(所在之处)。继承:IResultFilter或者异步IAsyncResultFilter
结果过滤器适用于任何需要直接环绕 View 或格式化处理的逻辑
public class ResultFiter : IResultFilter { public void OnResultExecuted(ResultExecutedContext context) { } public void OnResultExecuting(ResultExecutingContext context) { } }
异步执行如下
public class ResultFiter : IAsyncResultFilter { public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) { await next(); } }
不同的过滤器在管道的位置也不同,像授权过滤器执行的就比较靠前,具体顺序如下所示: