ASP.NET Core MVC中的Filter作用是在请求处理管道的某些阶段之前或之后可以运行特定的代码。

Filter特性在之前的ASP.NET MVC中已经出现,但过去只有Authorization,Exception,Action,Result四种类型,现在又增加了一种Resource类型。所以共计五种。

Resource类型Filter在Authorization类型Filter之后执行,但又在其它类型的Filter之前。且执行顺序也在Model Binding之前,所以可以对Model Binding产生影响。

ASP.NET Core MVC框架中可以看到有ConsumesAttribute及FormatFilter两种实现IResourceFilter接口的类。

ConsumesAttribute会按请求中的Content-Type(内容类型)进行过滤,而FormatFilter能对路由或路径中设置了format值的请求作过滤。

一旦不符合要求,就对ResourceExecutingContext的Result属性设置,这样可以达到短路效果,阻止进行下面的处理。

ConsumesAttribute类的例子:

public void OnResourceExecuting(ResourceExecutingContext context)
{
... // Only execute if the current filter is the one which is closest to the action.
// Ignore all other filters. This is to ensure we have a overriding behavior.
if (IsApplicable(context.ActionDescriptor))
{
var requestContentType = context.HttpContext.Request.ContentType; // Confirm the request's content type is more specific than a media type this action supports e.g. OK
// if client sent "text/plain" data and this action supports "text/*".
if (requestContentType != null && !IsSubsetOfAnyContentType(requestContentType))
{
context.Result = new UnsupportedMediaTypeResult();
}
}
}

Filter在ASP.NET Core MVC里除了保留原有的包含同步方法的接口,现在又增加了包含异步方法的接口。

同步

  • IActionFilter
  • IAuthorizationFilter
  • IExceptionFilter
  • IResourceFilter
  • IResultFilter

异步

  • IAsyncActionFilter
  • IAsyncAuthorizationFilter
  • IAsyncExceptionFilter
  • IAsyncResourceFilter
  • IAsyncResultFilter

新的接口不像旧有的接口包含两个同步方法,它们只有一个异步方法。但可以实现同样的功能。

public class SampleAsyncActionFilter : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
// 在方法处理前执行一些操作
var resultContext = await next();
// 在方法处理后再执行一些操作。
}
}

Attribute形式的Filter,其构造方法里只能传入一些基本类型的值,例如字符串:

public class AddHeaderAttribute : ResultFilterAttribute
{
private readonly string _name;
private readonly string _value; public AddHeaderAttribute(string name, string value)
{
_name = name;
_value = value;
} public override void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Add(
_name, new string[] { _value });
base.OnResultExecuting(context);
}
} [AddHeader("Author", "Steve Smith @ardalis")]
public class SampleController : Controller

如果想要在其构造方法里引入其它类型的依赖,现在可以使用ServiceFilterAttribute,TypeFilterAttribute或者IFilterFactory方式。

ServiceFilterAttribute需要在DI容器中注册:

public class GreetingServiceFilter : IActionFilter
{
private readonly IGreetingService greetingService; public GreetingServiceFilter(IGreetingService greetingService)
{
this.greetingService = greetingService;
} public void OnActionExecuting(ActionExecutingContext context)
{
context.ActionArguments["param"] =
this.greetingService.Greet("James Bond");
} public void OnActionExecuted(ActionExecutedContext context)
{ }
} services.AddScoped<GreetingServiceFilter>(); [ServiceFilter(typeof(GreetingServiceFilter))]
public IActionResult GreetService(string param)

TypeFilterAttribute则没有必要:

public class GreetingTypeFilter : IActionFilter
{
private readonly IGreetingService greetingService; public GreetingTypeFilter(IGreetingService greetingService)
{
this.greetingService = greetingService;
} public void OnActionExecuting(ActionExecutingContext context)
{
context.ActionArguments["param"] = this.greetingService.Greet("Dr. No");
} public void OnActionExecuted(ActionExecutedContext context)
{ }
} [TypeFilter(typeof(GreetingTypeFilter))]
public IActionResult GreetType1(string param)

IFilterFactory也是不需要的:

public class GreetingFilterFactoryAttribute : Attribute, IFilterFactory
{
public bool IsReusable => false; public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
var logger = (IGreetingService)serviceProvider.GetService(typeof(IGreetingService));
return new GreetingFilter(logger);
} private class GreetingFilter : IActionFilter
{
private IGreetingService _greetingService;
public GreetingFilter(IGreetingService greetingService)
{
_greetingService = greetingService;
}
public void OnActionExecuted(ActionExecutedContext context)
{
} public void OnActionExecuting(ActionExecutingContext context)
{
context.ActionArguments["param"] = _greetingService.Greet("Dr. No");
}
}
} [GreetingFilterFactory]
public IActionResult GreetType1(string param)

Filter有三种范围:

  • Global
  • Controller
  • Action

后两种可以通过Attribute的方式附加到特定Action方法或者Controller类之上。对于Global,则要在ConfigureServices方法内部添加。

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
// by instance
options.Filters.Add(new AddDeveloperResultFilter("Tahir Naushad")); // by type
options.Filters.Add(typeof(GreetDeveloperResultFilter));
}); }

顾名思义,Global将对所有Controller及Action产生影响。所以务必对其小心使用。

这三种范围的执行顺序在设计程序的时候也需要多作考虑:

  1. Global范围的前置处理代码
  2. Controller范围的前置处理代码
  3. Action范围的前置处理代码
  4. Action范围的后置处理代码
  5. Controller范围的后置处理代码
  6. Global范围的后置处理代码

典型的前置处理代码如常见的OnActionExecuting方法,而常见的后置处理代码,则是像OnActionExecuted方法这般的。

.NET Core开发日志——Filter的更多相关文章

  1. .NET Core开发日志——Entity Framework与PostgreSQL

    Entity Framework在.NET Core中被命名为Entity Framework Core.虽然一般会用于对SQL Server数据库进行数据操作,但其实它还支持其它数据库,这里就以Po ...

  2. .NET Core开发日志——RequestDelegate

    本文主要是对.NET Core开发日志--Middleware的补遗,但是会从看起来平平无奇的RequestDelegate开始叙述,所以以其作为标题,也是合情合理. RequestDelegate是 ...

  3. C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志

    C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...

  4. .NET Core开发日志——从搭建开发环境开始

    .NET Core自2016年推出1.0版本开始,到目前已是2.1版本,在其roadmap计划里明年更会推出3.0版本,发展不可不谓之迅捷.不少公司在经过一个谨慎的观望期后,也逐步开始将系统升级至最新 ...

  5. .NET Core开发日志——Model Binding

    ASP.NET Core MVC中所提供的Model Binding功能简单但实用,其主要目的是将请求中包含的数据映射到action的方法参数中.这样就避免了开发者像在Web Forms时代那样需要从 ...

  6. .NET Core开发日志——OData

    简述 OData,即Open Data Protocol,是由微软在2007年推出的一款开放协议,旨在通过简单.标准的方式创建和使用查询式及交互式RESTful API. 类库 在.NET Core中 ...

  7. .NET Core开发日志——结构化日志

    在.NET生态圈中,最早被广泛使用的日志库可能是派生自Java世界里的Apache log4net.而其后来者,莫过于NLog.Nlog与log4net相比,有一项较显著的优势,它支持结构化日志. 结 ...

  8. .NET Core开发日志——Edge.js

    最近在项目中遇到这样的需求:要将旧有系统的一部分业务逻辑集成到新的自动化流程工具中.这套正在开发的自动化工具使用的是C#语言,而旧有系统的业务逻辑则是使用AngularJS在前端构建而成.所以最初的考 ...

  9. .NET Core开发日志——Linux版本的SQL Server

    SQL Server 2017版本已经可以在Linux系统上安装,但我在尝试.NET Core跨平台开发的时候使用的是Mac系统,所以这里记录了在Mac上安装SQL Server的过程. 最新的SQL ...

随机推荐

  1. 详解CentOS设置163的yum源的过程

    转自启动CentOS系统,打开火狐浏览器,如下图所示: 2 登录“mirrors.163.com”,如下图所示: 3 点击centos后面的“centos使用帮助”,如下图所示: 4 可以看到设置和使 ...

  2. 如何在 Github 上发现优秀的开源项目?

    之前发过一系列有关 GitHub 的文章,有同学问了,GitHub 我大概了解了,Git 也差不多会使用了,但是还是搞不清 GitHub 如何帮助我的工作,怎么提升我的工作效率? 问到点子上了,Git ...

  3. 安装SQL Server For Linux(Install SQL Server)

    SQL Server on Ubuntu——Ubuntu上的SQL Server(全截图) 1.      安装SQL Server 官网安装指南:https://docs.microsoft.com ...

  4. Boinx FotoMagico for Mac(电子相册制作工具)破解版安装

    1.软件简介    FotoMagico 是 macOS 系统上一款非常好用的电子视频相册制作工具,FotoMagico 被誉为 Mac 上的「会声会影」,我们可以使用这款软件快速的制作出精美的音乐视 ...

  5. [Aaronyang] 写给自己的WPF4.5 笔记10[层次数据需求处理,TreeView绿色文章1/4]

     我的文章一定要做到对读者负责,否则就是失败的文章  ---------   www.ayjs.net    aaronyang技术分享 AY留言: 文章根据难易,我根据游戏的规则进行了分色,希望读者 ...

  6. 11G新特性 -- OLTP Table Compression

    之前的版本中,只能在批量加载操作时,比如direct load.create table as select 操作,才能压缩数据.在dml操作期间是无法压缩数据的. 在11g中,oracle将表压缩扩 ...

  7. Hexo NexT 博客本地搭建指南

    0x01 写在前面的话 第一次见到这个这个Hexo主题,是在查找lucene学习指南时看到了阿里中间件博客,文章写的自然不错,但博客程序主题更是令我喜欢不已. 于是我便萌生了也想撸一个的冲动. 既然想 ...

  8. 译: 6. RabbitMQ Spring AMQP 之 RPC

    Remote procedure call (RPC) 在第二篇教程中,我们学习了如何使用工作队列在多个工作人员之间分配耗时的任务. 但是如果我们需要在远程计算机上运行一个函数并等待结果呢?嗯,这是一 ...

  9. Android studio的主题颜色修改

    1.选择喜欢的主题 http://color-themes.com/?view=index 好几十款,总有一款你喜欢 2.下载你喜欢的主题,注意是jar文件 .File -> Import Se ...

  10. pythn os

    获取文件所在路径 import os os.path.dirname(__file__)  获取当前文件的所在路径 print (os.path.dirname(os.path.dirname(__f ...