本文内容来自书籍: Marinko Spasojevic - Ultimate ASP.NET Core Web API - From Zero To Six-Figure Backend Developer (2nd edition)
缓存
和性能
很有用action
的前后执行这个章节只介绍Action filter
要创建Action filter
,有几种不同实现
如果是同步方式实现,需要实现OnActionExecuting
和OnActionExecuted
public class ActionFilterExample : IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { // our code before action executes } public void OnActionExecuted(ActionExecutedContext context) { // our code after action executes } }
如果是异步方式实现,需要实现OnActionExecutionAsync
public class AsyncActionFilterExample : IAsyncActionFilter { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // execute any code before the action executes var result = await next(); // execute any code after the action executes } }
过滤器有几种范围
// Program.cs builder.Services.AddControllers(config => { config.Filters.Add(new GlobalFilterExample()); });
// Program.cs builder.Services.AddScoped<ActionFilterExample>(); builder.Services.AddScoped<ControllerFilterExample>(); // Controller [ServiceFilter(typeof(ControllerFilterExample))] [Route("api/[controller]")] [ApiController] public class TestController : ControllerBase { [HttpGet] [ServiceFilter(typeof(ActionFilterExample))] public IEnumerable<string> Get() { return new string[] { "example", "data" }; } }
这是默认的执行顺序,也可以通过添加order
属性,来改变执行顺序
[ServiceFilter(typeof(ControllerFilterExample), Order = 2)] [Route("api/[controller]")] [ApiController] public class TestController : ControllerBase { [HttpGet] [ServiceFilter(typeof(ActionFilterExample), Order = 1)] public IEnumerable<string> Get() { return new string[] { "example", "data" }; } }
前面的章节介绍过,我们的业务逻辑代码中,没有try-catch
块,都提取到全局异常处理的中间件了,但是现在可以使用Action filter
来更进一步处理
现在从POST
和PUT
的逻辑代码中,可以看到相似的验证逻辑
if (company is null) return BadRequest("CompanyForUpdateDto object is null"); if (!ModelState.IsValid) return UnprocessableEntity(ModelState);
然后我们可以将验证逻辑提取出来,重复使用
public class ValidationFilterAttribute : IActionFilter { public ValidationFilterAttribute() { } public void OnActionExecuting(ActionExecutingContext context) { var action = context.RouteData.Values["action"]; var controller = context.RouteData.Values["controller"]; var param = context.ActionArguments .SingleOrDefault(x => x.Value.ToString().Contains("Dto")).Value; if (param is null) { context.Result = new BadRequestObjectResult($"Object is null. Controller:{controller}, action: {action}"); return; } if (!context.ModelState.IsValid) context.Result = new UnprocessableEntityObjectResult(context.ModelState); } public void OnActionExecuted(ActionExecutedContext context) { } }