Filter是延续ASP.NET MVC的产物,一样保留了五种的Filter,分别是Authorization Filter、Resource Filter、Action Filter、Exception Filter及Result Filter。
经过不一样的Filter能够有效处理封包进出的加工,本篇将介绍ASP.NET Core的五种Filter运做方式。git
Filter的做用是在Action 执行前或执行后作一些加工处理。
某种程度来看,会跟Middleware很像,但执行的顺序略有不一样,用对Filter不只能够减小代码,还能够提升执行效率。github
ASP.NET Core 有如下五种Filter 可使用:bash
ASP.NET Core的每一个Request都会先通过已注册的Middleware接着才会执行Filter,除了会依照上述的顺序外,同类型的Filter预设都会以先进后出的方式处里封包。
Response在某些Filter并不会作处理,会直接被pass。Request及Response的运做流程以下图:mvc
ASP.NET Core的Filter基本上跟ASP.NET MVC的差很少。
上述的五种Filter范例分别以下:async
AuthorizationFilter.csspa
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
namespace MyWebsite.Filters
{
public class AuthorizationFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
}
}
}
非同步的方式:code
// ...
public class AuthorizationFilter : IAsyncAuthorizationFilter
{
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
}
}
ResourceFilter.csblog
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
namespace MyWebsite.Filters
{
public class ResourceFilter : IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
}
}
}
非同步的方式:继承
// ...
public class ResourceFilter : IAsyncResourceFilter
{
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
{
await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
await next();
await context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
}
}
ActionFilter.csget
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
namespace MyWebsite.Filters
{
public class ActionFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
}
public void OnActionExecuted(ActionExecutedContext context)
{
context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
}
}
}
非同步的方式:
// ...
public class ActionFilter : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
await next();
await context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
}
}
ResultFilter.cs
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
namespace MyWebsite.Filters
{
public class ResultFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
}
public void OnResultExecuted(ResultExecutedContext context)
{
context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
}
}
}
非同步的方式:
// ...
public class ResultFilter : IAsyncResultFilter
{
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
await context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
await next();
await context.HttpContext.Response.WriteAsync($"{GetType().Name} out. \r\n");
}
}
ExceptionFilter.cs
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
namespace MyWebsite.Filters
{
public class ExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
context.ExceptionHandled = true; // 代表异常已处理,客户端可获得正常返回
context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
}
}
}
非同步的方式:
// ...
public class ExceptionFilter : IAsyncExceptionFilter
{
public Task OnExceptionAsync(ExceptionContext context)
{
context.ExceptionHandled = true;// 代表异常已处理,客户端可获得正常返回
context.HttpContext.Response.WriteAsync($"{GetType().Name} in. \r\n");
return Task.CompletedTask;
}
}
Filter有两种注册方式,一种是全局注册,另外一种是用[Attribute]局部
注册的方式,只套用在特定的Controller或Action。
在Startup.ConfigureServices
的MVC服务中注册Filter,这样就能够套用到全部的Request。以下:
// ...
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(config =>
{
config.Filters.Add(new ResultFilter());
config.Filters.Add(new ExceptionFilter());
config.Filters.Add(new ResourceFilter());
});
}
}
ASP.NET Core在局部注册Filter的方式跟ASP.NET MVC有一点不同,要经过[TypeFilter(type)]
。
在Controller或Action上面加上[TypeFilter(type)]
就能够局部注册Filter。以下:
// ...
namespace MyWebsite.Controllers
{
[TypeFilter(typeof(AuthorizationFilter))]
public class HomeController : Controller
{
[TypeFilter(typeof(ActionFilter))]
public void Index()
{
Response.WriteAsync("Hello World! \r\n");
}
[TypeFilter(typeof(ActionFilter))]
public void Error()
{
throw new System.Exception("Error");
}
}
}
[TypeFilter(type)]
用起来有点冗长,想要像过去ASP.NET MVC用[Attribute]
注册Filter的话,只要将Filter继承Attribute
便可。以下:
public class AuthorizationFilter : Attribute, IAuthorizationFilter
{
// ...
}
public class ActionFilter : Attribute, IActionFilter
{
// ...
}
[Attribute]
注册就能够改为以下方式:
// ...
namespace MyWebsite.Controllers
{
[AuthorizationFilter]
public class HomeController : Controller
{
[ActionFilter]
public void Index()
{
Response.WriteAsync("Hello World! \r\n");
}
[ActionFilter]
public void Error()
{
throw new System.Exception("Error");
}
}
}
http://localhost:5000/Home/Index
输出结果以下:
AuthorizationFilter in.
ResourceFilter in.
ActionFilter in.
Hello World!
ActionFilter out.
ResultFilter in.
ResultFilter out.
ResourceFilter out.
http://localhost:5000/Home/Error
输出结果以下:
AuthorizationFilter in.
ResourceFilter in.
ActionFilter in.
ActionFilter out.
ExceptionFilter in.
ResourceFilter out.
预设注册同类型的Filter 是以先进后出的方式处里封包,注册层级也会影响执行顺序。
但也能够经过实现 IOrderedFilter 更改执行顺序。例如:
public class ActionFilter : Attribute, IActionFilter, IOrderedFilter
{
public string Name { get; set; }
public int Order { get; set; } = 0;
public void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Response.WriteAsync($"{GetType().Name}({Name}) in. \r\n");
}
public void OnActionExecuted(ActionExecutedContext context)
{
context.HttpContext.Response.WriteAsync($"{GetType().Name}({Name}) out. \r\n");
}
}
在注册Filter 时带上Order,数值越小优先权越高。
// ...
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(config =>
{
config.Filters.Add(new ActionFilter() { Name = "Global", Order = 3 });
});
}
}
// ...
namespace MyWebsite.Controllers
{
[ActionFilter(Name = "Controller", Order = 2)]
public class HomeController : Controller
{
[ActionFilter(Name = "Action", Order = 1)]
public void Index()
{
Response.WriteAsync("Hello World! \r\n");
}
}
}
变动执行顺序后的输出内容:
ActionFilter(Action) in.
ActionFilter(Controller) in.
ActionFilter(Global) in.
Hello World!
ActionFilter(Global) out.
ActionFilter(Controller) out.
ActionFilter(Action) out.
老司机发车啦:https://github.com/SnailDev/SnailDev.NETCore2Learning