筛选器Filter

参考:https://learn.microsoft.com/zh-cn/aspnet/core/mvc/controllers/filters?view=aspnetcore-6.0

1、什么是筛选器

通过使用 ASP.NET Core 中的筛选器,可在请求处理管道中的特定阶段之前或之后运行代码。

可以创建自定义筛选器,用于处理横切关注点。 横切关注点的示例包括错误处理、缓存、配置、授权和日志记录。 筛选器可以避免复制代码。 

(1)The request is processed through Other Middleware, Routing Middleware, Action Selection, and the Action Invocation Pipeline. The request processing continues back through Action Selection, Routing Middleware, and various Other Middleware before becoming a response sent to the client.(2)The request is processed through Authorization Filters, Resource Filters, Model Binding, Action Filters, Action Execution and Action Result Conversion, Exception Filters, Result Filters, and Result Execution. On the way out, the request is only processed by Result Filters and Resource Filters before becoming a response sent to the client.

工作原理:筛选器在 ASP.NET Core 操作调用管道(有时称为筛选器管道)内运行。筛选器管道在 ASP.NET Core 选择了要执行的操作之后运行,如图(1)所示。

5种筛选器:每种筛选器类型都在筛选器管道中的不同阶段执行:授权筛选器AuthorizationFilter、资源筛选器Resource Filter、操作筛选器Action Filter、异常筛选器Exception Filter、结果筛选器Result Filter。图(2)展示了筛选器类型在筛选器管道中的交互方式。

实现:所有的Filter都实现接口IFilterMetadata,根据不同的业务类型,派生出了五个接口,分别对应五大类Filter,如下图所示:

筛选器通过不同的接口定义支持同步和异步实现。

同步筛选器在其管道阶段之前和之后运行。 例如,OnActionExecuting 在调用操作方法之前调用。 OnActionExecuted 在操作方法返回之后调用:

public class SampleActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Do something before the action executes.
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Do something after the action executes.
    }
}

异步筛选器定义 OnActionExecutionAsync 方法:

public class SampleAsyncActionFilter : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(
        ActionExecutingContext context, ActionExecutionDelegate next)
    {
        // Do something before the action executes.
        await next();
        // Do something after the action executes.
    }
}

异常筛选器的同步实现OnException和异步实现OnExceptionAsync

 

2、异常筛选器——Exception Filter

在向响应正文写入任何内容之前,对未经处理的异常应用全局策略。

builder.Services.Configure<MvcOptions>(options =>
{
    options.Filters.Add<SampleExceptionFilter>();
});

自定义同步异常筛选器:

public class SampleExceptionFilter : IExceptionFilter
{
    private readonly IHostEnvironment _hostEnvironment;

    public SampleExceptionFilter(IHostEnvironment hostEnvironment) =>
        _hostEnvironment = hostEnvironment;

    public void OnException(ExceptionContext context)
    {
        if (!_hostEnvironment.IsDevelopment())
        {
            // Don't display exception details unless running in Development.
            return;
        }

        context.Result = new ContentResult//返回给客户端的值
        {
            StatusCode = 500,        
            Content = context.Exception.ToString()
        };
        context.ExceptionHandled = true;//为true时,其他ExceptionFilter不会再执行
    }
}

 以下代码测试异常筛选器:

[ApiController]
[Route("[controller]/[action]")]
public class ExceptionController : ControllerBase
{
    public void Index() =>System.IO.File.ReadAllText("D:\\A.txt");//读取不存在的文件
}

异常筛选器:

  • 非常适合捕获发生在操作中的异常。
  • 并不像错误处理中间件那么灵活。

建议使用中间件处理异常。 基于所调用的操作方法,仅当错误处理不同时,才使用异常筛选器。

 

3、操作筛选器——Action Filter

  • 实现 IActionFilter 或 IAsyncActionFilter 接口。
  • 在调用操作方法之前和之后立即运行。
  • 可以更改传递到操作中的参数。
  • 可以更改从操作返回的结果。
  • 不可在 Razor Pages 中使用。

全局筛选器服务注入到容器:

builder.Services.Configure<MvcOptions>(options =>
{
    options.Filters.Add<MyActionFilter1>();
    options.Filters.Add<MyActionFilter2>();
});

自定义异步操作筛选器:

/*ActionExecutingContext 提供以下属性:
ActionArguments - 用于读取操作方法的输入。
Controller - 用于处理控制器实例。
Result - 设置 Result 会使操作方法和后续操作筛选器的执行短路。*/
public class MyActionFilter1 : IAsyncActionFilter
{
	public async Task OnActionExecutionAsync(ActionExecutingContext context, 
		ActionExecutionDelegate next)
	{
		Console.WriteLine("MyActionFilter 1:开始执行");
		ActionExecutedContext r = await next();
		if (r.Exception != null)
		{
			Console.WriteLine("MyActionFilter 1:执行失败");
		}
		else
		{
			Console.WriteLine("MyActionFilter 1:执行成功");
		}
	}
}

public class MyActionFilter2 : IAsyncActionFilter
{
	public async Task OnActionExecutionAsync(ActionExecutingContext context, 
		ActionExecutionDelegate next)
	{
		Console.WriteLine("MyActionFilter 2:开始执行");
		ActionExecutedContext r = await next();
		if (r.Exception != null)
		{
			Console.WriteLine("MyActionFilter 2:执行失败");
		}
		else
		{
			Console.WriteLine("MyActionFilter 2:执行成功");
		}
	}
}

  以下代码测试操作筛选器:

[ApiController]
[Route("[controller]/[action]")]
[TypeFilter(typeof(MyActionFilter1))]//必须加
[TypeFilter(typeof(MyActionFilter2))]
public class ActionController : ControllerBase
{
    [HttpGet]
    public string GetData()
    {
        Console.WriteLine("执行GetData");
        return "yzk";
    }
}

////执行结果,控制台输出以下结果
//MyActionFilter1,开始执行
//MyActionFilter2,开始执行
//执行GetData控制器方法
//MyActionFilter2,执行成功
//MyActionFilter1,执行成功

 

posted @ 2024-03-15 18:43  茜茜87  阅读(2)  评论(0编辑  收藏  举报