You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在请求抵达WebAPI控制器前统一处理SomeId字段?

问题背景

现有ASP.NET Core Api控制器代码如下:

[ApiController]
[Route("v1/[controller]/[action]")]
public class AccountController : Controller
{
        private readonly IClient _client;
        public AccountController(IClient client)
        {
            _client = client;
        }

        [HttpPost]
        public async Task<IActionResult> SomeAction([FromBody] SomeRequestModel request)
        {
            if (_client.SomeId == null) return BadRequest("Something could not be resolved");
            request.SomeId = _client.SomeId.Value;

            // Do further processing
        }
}

对应的请求模型:

public class SomeRequestModel 
{
    public long SomeId;
    // other fields
}

现状与需求:

  • 存在约100个不同Action,对应100个独立请求模型
  • 所有模型均包含SomeId字段,但未继承统一基类,且因来自外部项目无法修改
  • 需要统一实现逻辑:检查_client.SomeId是否已解析,未解析则返回BadRequest;已解析则为请求模型的SomeId字段赋值
  • 不想在每个Action中重复编写相同代码,曾考虑用System.Web.Http.AuthorizeAttribute解析JSON修改值,但认为效率极低,寻求最优方案

最优解决方案:异步Action过滤器

使用ASP.NET Core原生的异步Action过滤器,在Action执行前统一完成检查与赋值逻辑,完全消除重复代码:

1. 实现自定义异步过滤器

public class SomeIdActionFilter : IAsyncActionFilter
{
    private readonly IClient _client;

    public SomeIdActionFilter(IClient client)
    {
        _client = client;
    }

    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        // 检查SomeId是否已解析
        if (_client.SomeId == null)
        {
            context.Result = new BadRequestObjectResult("Something could not be resolved");
            return;
        }

        // 遍历Action参数,为含SomeId字段的模型赋值
        foreach (var parameter in context.ActionArguments.Values)
        {
            if (parameter == null) continue;
            
            var someIdField = parameter.GetType().GetField("SomeId", BindingFlags.Public | BindingFlags.Instance);
            if (someIdField != null && someIdField.FieldType == typeof(long))
            {
                someIdField.SetValue(parameter, _client.SomeId.Value);
            }
        }

        // 继续执行原Action逻辑
        await next();
    }
}

2. 注册过滤器

根据需求选择全局或局部注册方式:

全局注册(所有Api控制器生效)

在Program.cs中配置:

builder.Services.AddControllers(options =>
{
    options.Filters.Add<SomeIdActionFilter>();
});

局部注册(指定控制器/Action生效)

  • 控制器级别:
[ApiController]
[Route("v1/[controller]/[action]")]
[ServiceFilter(typeof(SomeIdActionFilter))]
public class AccountController : Controller
{
    // 控制器代码
}
  • Action级别:
[HttpPost]
[ServiceFilter(typeof(SomeIdActionFilter))]
public async Task<IActionResult> SomeAction([FromBody] SomeRequestModel request)
{
    // 直接编写业务逻辑,无需重复检查赋值代码
}

方案优势

  • 完全消除重复代码,统一维护逻辑
  • 基于ASP.NET Core原生机制,性能远优于解析JSON的方式
  • 反射仅针对SomeId字段,性能开销可忽略
  • 注册方式灵活,适配不同场景需求

内容的提问来源于stack exchange,提问作者ertucode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:25:30