ASP.NET Core Filter

ASP.NET Core Filter

  • Filter 简介
  • ExceptionFilter
  • ActionFilter
  • ActionFilter 实现请求限流
  • UseExceptionHandler —— 中心化全局异常处理

Filter 简介

1、切面编程机制,在 ASP.NET Core 特定的位置执行我们的自定义的代码
2、ASP.NET Core 中的 Filter 的五种类型:Authorization filter、Resource filter、Action filter、Exception filter、Result filter
3、所有筛选器一般有同步和异步两个版本

ExceptionFilter

ExceptionFilter 实现异常处理,是利用切面编程编程机制,通过builder.Services.Configure() 在适当的时机切入。需要实现 IAsyncExceptionFilter 接口。

支持链式执行

public class MyExceptionFilter : IAsyncExceptionFilter
{
    private readonly IWebHostEnvironment _webHostEnvironment;

    public MyExceptionFilter(IWebHostEnvironment webHostEnvironment)
    {
        _webHostEnvironment = webHostEnvironment;
    }

    public Task OnExceptionAsync(ExceptionContext context)
    {
        // context.Exception 代表异常信息对象
        // 如果给 context.ExceptionHandled 赋值为 true,则其他 ExceptionFilter 不再执行
        // context.Result 的值会被返回给客户端

        // 判断是否为开发模式
        string message = _webHostEnvironment.IsDevelopment() ? context.Exception.ToString() : "服务器发生未处理异常";
        
        ObjectResult result = new(new
        {
            code = 500,
            message = message
        });
        context.Result = result;
        context.ExceptionHandled = true;

        return Task.CompletedTask;
    }
}
  • 在 Program.cs 中配置 MvcOptions 添加 MyExceptionFilter

通过下面的方式注入的代码处于DI管理当中,所有 MyExceptionFilter 中是可以注入我们需要的服务的。

builder.Services.Configure<MvcOptions>(option =>
{
	// 如果类型设置了 ExceptionHandled 为 true 需要注意 Add 的顺序先加入的后执行
    option.Filters.Add<MyExceptionFilter>();
});

ActionFilter

ActionFilter 与 ExceptionFilter 不同的是 ActionFilter 实在 Controller 中的每一个 action 方法执行前或执行后都可以执行。
ActionFilter 是可以在每一个执行之前和执行之后,执行自定义代码的机制。
多个 ActionFilter 也是可以进行链式执行。

ActionFilter 具有两段代码称为 前代码后代码
顺序,先执行前代码,再执行真正的ActionFilter中的自定义代码,再执行后代码

public class MyActionFilter : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        Console.WriteLine("ActionFilter 前代码");
        ActionExecutedContext result = await next();
        if (result.Exception != null)
        {
            Console.WriteLine("ActionFilter:发生异常");
        }
        else
        {
            Console.WriteLine("ActionFilter:执行成功");
        }
    }
}
[Route("[controller]/[action]")]
[ApiController]
public class TestController : ControllerBase
{
    [HttpGet]
    public string Test1()
    {
        //string str = System.IO.File.ReadAllText("f:/1.txt");
        Console.WriteLine("action 代码");
        return "123";
    }
}

ASP.NET Core Filter_第1张图片

ActionFilter 实现请求限流

请求限流在实际情况中还是很常见的,最常见的就是防止恶意爬虫导致的服务器宕机。

/// 
/// 请求限流器
/// 
public class RateLimitActionFilter : IAsyncActionFilter
{
    private readonly IMemoryCache _memoryCache;

    public RateLimitActionFilter(IMemoryCache memoryCache)
    {
        _memoryCache = memoryCache;
    }

    public Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        string removeIP = context.HttpContext.Connection.RemoteIpAddress.ToString();
        string cachKey = $"LastVisitTick_{removeIP}";
        long? lastTick = _memoryCache.Get<long?>(cachKey);

        if (lastTick is null || Environment.TickCount64 - lastTick > 1000)
        {
            _memoryCache.Set(cachKey, Environment.TickCount64, TimeSpan.FromSeconds(5));
            return next();
        }

        context.Result = new ContentResult { StatusCode = StatusCodes.Status429TooManyRequests };
        return Task.CompletedTask;
    }
}

UseExceptionHandler —— 中心化全局异常处理

UseExceptionHandler 扩展方法能够将 ExceptionHandler 中间件注册到 Asp.net Core 的 请求处理管道 中,然后在 IExceptionHandlerFeature 接口的实例中获取异常对象。

public class ErrorMessage
{
    /// 
    /// 错误消息
    /// 
    public string? Message { get; set; }
    /// 
    /// 堆栈跟踪信息
    /// 
    public string? Stacktrace { get; set; }
}
using Microsoft.AspNetCore.Diagnostics;
using ServiceExceptionHandling;
using System.Net;
using System.Text.Json;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseExceptionHandler(builder =>
{
    builder.Run(async context =>
    {
        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        context.Response.ContentType = "application/json";

        var exception = context.Features.Get<IExceptionHandlerFeature>();
        if (exception is not null)
        {
            ErrorMessage error = new()
            {
                Message = exception.Error.Message,
                Stacktrace = exception.Error.StackTrace
            };
            string errorOjb = JsonSerializer.Serialize(error);

            await context.Response.WriteAsync(errorOjb).ConfigureAwait(false);
        }
    });
});

app.UseAuthorization();

app.MapControllers();

app.Run();

你可能感兴趣的:(#,.NET,Core,asp.net,core,C#,过滤器,filter,mvc)