ASP.NET Core中的Filter可以讓程式碼在Request pipeline中的特定階段之前或之後執行
Filter用起來跟 Middleware 有點相似,
ASP.NET Core 預設有五種Filter,分別是:
ASP.NET Core的每個Request都會先通過Middleware之後才會進入Filter,進入Filter之後的流程如下圖
圖片來源:MSDN
接下來示範如何自訂義Filter
實作 IActionFilter 或 IAsyncActionFilter 介面。
執行會包圍Action的執行。
建立SampleActionFilter.cs
,並加入以下內容
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FilterSample.Filters
{
//同步
public class SampleActionFilter : Attribute ,IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Response.WriteAsync("Sample Action in \r\n");
}
public void OnActionExecuted(ActionExecutedContext context)
{
context.HttpContext.Response.WriteAsync("Sample Action out \r\n");
}
}
//非同步
public class SampleAsyncActionFilter : Attribute, IAsyncActionFilter
{
public async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
await context.HttpContext.Response.WriteAsync("Async Sample Action in \r\n");
var resultContext = await next();
await context.HttpContext.Response.WriteAsync("Async Sample Action out \r\n");
}
}
}
ActionExecutingContext 提供下列屬性:
OnActionExecuting 動作篩選條件可以用來:
OnActionExecuted 方法會在動作方法之後執行:
實作 IResourceFilter 或 IAsyncResourceFilter 介面。
執行會包裝大部分的篩選條件管線。
只有AuthorizationFilter會在ResourceFilter之前執行。
SampleResourceFilter.cs
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FilterSample.Filters
{
public class SampleResourceFilter : Attribute ,IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
context.HttpContext.Response.WriteAsync("Sample Resource in \r\n");
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
context.HttpContext.Response.WriteAsync("Sample Resource out \r\n");
}
}
public class SampleAsyncResourceFilter : Attribute, IAsyncResourceFilter
{
public async Task OnResourceExecutionAsync(
ResourceExecutingContext context,
ResourceExecutionDelegate next)
{
await context.HttpContext.Response.WriteAsync("Async Sample Resource in \r\n");
var resultContext = await next();
await context.HttpContext.Response.WriteAsync("Async Sample Resource out \r\n");
}
}
}
ResourceFilter很適合用來縮短大部分的pipeline。比方說,caching filter可以避免快取後其餘pipeline繼續執行。
實作介面:
IResultFilter 或 IAsyncResultFilter
IAlwaysRunResultFilter 或 IAsyncAlwaysRunResultFilter
執行會包圍Action的執行。
SampleResultFilter.cs
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FilterSample.Filters
{
public class SampleResultFilter : Attribute ,IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
// Do something before the Result executes.
context.HttpContext.Response.WriteAsync("Sample Result in \r\n");
}
public void OnResultExecuted(ResultExecutedContext context)
{
context.HttpContext.Response.WriteAsync("Sample Result out \r\n");
}
}
public class SampleAsyncResultFilter : Attribute, IAsyncResultFilter
{
public async Task OnResultExecutionAsync(
ResultExecutingContext context,
ResultExecutionDelegate next)
{
await context.HttpContext.Response.WriteAsync("Async Sample Result in \r\n");
var resultContext = await next();
await context.HttpContext.Response.WriteAsync("Async Sample Result out \r\n");
}
}
}
ResultFilter只會在Action或ActionFilter產生動作結果時執行。當下列情況時,不會執行ResultFilter:
AuthorizationFilter或ResourceFilter會對pipeline行較短的線路。
ExceptionFilter會產生ActionResult來處理例外狀況。
上列的範例因為繼承了Attribute類別,所以可以用Attribute的方式套用在Action或是Controller上
例如:
namespace FilterSample.Controllers
{
[ApiController]
[Route("[controller]")]
public class FilterDemoController : ControllerBase
{
[SampleAsyncActionFilter]
[HttpGet]
public void Get()
{
Response.WriteAsync("Action in! \r\n");
}
}
}
輸出的結果就會為
Async Sample Action in
Action in!
Async Sample Action out