欢迎光临
我们一直在努力

【ASP.NET CORE】 5. 面向切面编程

本系列专栏基于杨中科老师的《ASP.NET Core技术内幕与项目实战》,本人记录梳理的学习笔记,有部分的增补和省略。更全面系统的讲解,请看杨老师的视频课:【.NET教程,.Net Core视频教程,杨中科主讲】。

一、Filter 概述

1. 概念

Filter(筛选器 / 过滤器)是 ASP.NET Core 内置的 AOP(面向切面编程)机制,允许我们在请求处理管道的特定阶段,插入自定义逻辑,而无需修改控制器、Action 的原有代码。

特点:

  • 横切关注点统一处理(异常、日志、权限、缓存、事务、限流)
  • 代码解耦、复用、易维护
  • 不侵入业务核心逻辑

2. Filter 五大类型

ASP.NET Core 提供 5 种内置筛选器,按固定顺序执行:

  • Authorization Filter(授权筛选器)最先执行,用于身份验证、权限校验,不满足则直接拒绝请求。
  • Resource Filter(资源筛选器)授权后、模型绑定前执行,可实现缓存、性能监控。
  • Action Filter(行为筛选器)执行 Action 方法前后执行,最常用。
  • Exception Filter(异常筛选器)全局捕获未处理异常,统一返回格式。
  • Result Filter(结果筛选器)Action 执行完毕、返回结果前后执行。
  • 3. 同步与异步 Filter

    Filter 都提供同步和异步两套接口,推荐优先使用异步,避免阻塞线程。

    功能同步接口异步接口
    行为筛选 IActionFilter IAsyncActionFilter
    异常筛选 IExceptionFilter IAsyncExceptionFilter
    资源筛选 IResourceFilter IAsyncResourceFilter
    结果筛选 IResultFilter IAsyncResultFilter

    二、Filter 实战

    1. 异常筛选器 Exception Filter

    作用:全局捕获控制器 / Action 抛出的未处理异常,统一返回格式、记录日志,避免程序崩溃。

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.Filters;

    /// <summary>
    /// 全局异步异常筛选器
    /// </summary>
    public class MyExceptionFilter : IAsyncExceptionFilter
    {
    private readonly ILogger<MyExceptionFilter> _logger;
    private readonly IHostEnvironment _env;

    // 依赖注入(Filter 支持构造函数注入)
    public MyExceptionFilter(ILogger<MyExceptionFilter> logger, IHostEnvironment env)
    {
    _logger = logger;
    _env = env;
    }

    public Task OnExceptionAsync(ExceptionContext context)
    {
    // 1. 获取异常对象
    Exception exception = context.Exception;

    // 2. 记录错误日志(包含异常堆栈)
    _logger.LogError(exception, "全局捕获到未处理异常");

    // 3. 根据环境返回不同提示信息
    string errorMsg = _env.IsDevelopment()
    ? exception.ToString()
    : "服务器繁忙,请稍后重试";

    // 4. 构造统一响应结果
    var result = new ObjectResult(new
    {
    Code = 500,
    Message = errorMsg,
    Success = false
    })
    {
    StatusCode = StatusCodes.Status500InternalServerError
    };

    // 5. 赋值给上下文,表示异常已处理
    context.Result = result;
    context.ExceptionHandled = true;

    return Task.CompletedTask;
    }
    }

    注册使用(Program.cs)

    // 全局注册异常筛选器(所有控制器生效)
    builder.Services.Configure<MvcOptions>(options =>
    {
    options.Filters.Add<MyExceptionFilter>();
    });

    2. 行为筛选器 Action Filter

    作用:在 Action 方法执行前和执行后运行自定义代码。

    • 执行前:参数校验、权限、限流、事务开启
    • 执行后:结果包装、日志记录、事务提交

    // 异步 Action 筛选器核心方法
    public async Task OnActionExecutionAsync(
    ActionExecutingContext context, // 执行前上下文
    ActionExecutionDelegate next) // 执行 Action 的委托
    {
    // 1. Action 执行前逻辑

    // 2. 执行 Action 方法
    var executedContext = await next();

    // 3. Action 执行后逻辑
    }

    三、Filter 执行顺序

    1. 优先级

    Action 上的 Filter > 控制器上的 Filter > 全局注册的 Filter

    2. 多层 Filter 执行流程

    以 ActionFilter 为例:

  • 全局 Filter 执行前代码
  • 控制器 Filter 执行前代码
  • Action Filter 执行前代码
  • 执行 Action 方法
  • Action Filter 执行后代码
  • 控制器 Filter 执行后代码
  • 全局 Filter 执行后代码
  • 先进后出,类似栈结构 / 嵌套包裹执行

    四、案例 1:自动事务 Filter(TransactionScopeFilter)

    需求

    对数据库操作自动开启事务,Action 无异常则提交,出现异常自动回滚,无需手动写 TransactionScope。

    实现代码

    步骤 1:定义忽略事务标记

    /// <summary>
    /// 标记 Action 不使用自动事务
    /// </summary>
    [AttributeUsage(AttributeTargets.Method)]
    public class NotTransactionalAttribute : Attribute
    {
    }

    步骤 2:实现事务筛选器

    using Microsoft.AspNetCore.Mvc.Controllers;
    using Microsoft.AspNetCore.Mvc.Filters;
    using System.Transactions;

    /// <summary>
    /// 自动事务管理 Filter
    /// </summary>
    public class TransactionScopeFilter : IAsyncActionFilter
    {
    public async Task OnActionExecutionAsync(
    ActionExecutingContext context,
    ActionExecutionDelegate next)
    {
    // 1. 判断是否标记 [NotTransactional],是则跳过事务
    bool isSkip = false;
    if (context.ActionDescriptor is ControllerActionDescriptor actionDesc)
    {
    isSkip = actionDesc.MethodInfo.IsDefined(typeof(NotTransactionalAttribute), true);
    }
    if (isSkip)
    {
    await next();
    return;
    }

    // 2. 创建异步事务范围(支持 async/await)
    using var txScope = new TransactionScope(
    TransactionScopeOption.Required,
    TransactionScopeAsyncFlowOption.Enabled);

    try
    {
    // 3. 执行 Action
    var executedContext = await next();

    // 4. 无异常则提交事务
    if (executedContext.Exception == null)
    {
    txScope.Complete();
    }
    }
    catch
    {
    // 事务会自动回滚(无需代码)
    throw;
    }
    }
    }

    步骤 3:注册(Program.cs)

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

    步骤 4:使用(控制器代码)

    [HttpPost]
    public async Task<string> TestTransaction(BookStoreDbContext ctx)
    {
    // 无需手动写 TransactionScope
    // Filter 自动开启 + 提交/回滚

    ctx.Books.Add(new Book { Name = "ASP.NET Core 实战", Price = 59 });
    await ctx.SaveChangesAsync();

    ctx.Persons.Add(new Person { Name = "张三", Age = 20 });
    await ctx.SaveChangesAsync();

    return "操作成功,事务已提交";
    }

    // 不需要事务的 Action
    [HttpPost]
    [NotTransactional]
    public async Task<string> TestNoTransaction()
    {
    return "跳过自动事务";
    }

    五、案例 2:IP 请求限流 Filter(RateLimitFilter)

    需求

    同一个 IP 1 秒内最多只能请求 1 次,防止恶意刷接口。

    实现代码

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.Filters;
    using Microsoft.Extensions.Caching.Memory;

    /// <summary>
    /// IP 请求限流筛选器(1秒1次)
    /// </summary>
    public class RateLimitFilter : IAsyncActionFilter
    {
    private readonly IMemoryCache _memCache;

    public RateLimitFilter(IMemoryCache memCache)
    {
    _memCache = memCache;
    }

    public async Task OnActionExecutionAsync(
    ActionExecutingContext context,
    ActionExecutionDelegate next)
    {
    // 1. 获取客户端 IP
    string ip = context.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";
    string cacheKey = $"RateLimit_{ip}";

    // 2. 判断是否在冷却时间内
    if (_memCache.TryGetValue(cacheKey, out _))
    {
    // 直接终止 Action 执行,返回 429
    context.Result = new ContentResult
    {
    StatusCode = StatusCodes.Status429TooManyRequests,
    Content = "请求过于频繁,请1秒后重试"
    };
    return;
    }

    // 3. 记录访问时间,缓存 1 秒
    _memCache.Set(cacheKey, DateTime.UtcNow, TimeSpan.FromSeconds(1));

    // 4. 正常执行 Action
    await next();
    }
    }

    注册使用

    // 注册内存缓存
    builder.Services.AddMemoryCache();

    // 注册限流过滤器
    builder.Services.Configure<MvcOptions>(options =>
    {
    options.Filters.Add<RateLimitFilter>();
    });

    六、Filter 三种注册方式

  • 全局注册(所有控制器 / Action 生效) options.Filters.Add<MyFilter>();
  • 控制器注册(当前控制器所有 Action 生效) [TypeFilter(typeof(MyFilter))]
    public class HomeController : Controller
  • Action 注册(仅当前方法生效) [TypeFilter(typeof(MyFilter))]
    public IActionResult Index()

  • 总结

  • Filter 是 ASP.NET  Core 官方 AOP 实现,无第三方依赖。异步 Filter(IAsyncXXX)性能更好,优先使用。
  • 执行顺序:授权 → 资源 → Action → 异常 → 结果。多个 Filter 按嵌套栈结构执行(先进后出)。
  • 典型应用:全局异常、自动事务、IP 限流、日志、权限、缓存。
  • 赞(0)
    未经允许不得转载:171主机测评 » 【ASP.NET CORE】 5. 面向切面编程
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址