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

.NET Core 7 Minimal API:通用过滤器中如何区分服务与POST请求体

问题描述

我正在使用.NET Core 7 Minimal API,需要记录POST请求的请求体。当前代码通过给请求体DTO添加自定义RequestBodyAttribute来识别请求体,但这种方式容易因遗漏标记出错;通过参数位置判断也有风险;想通过检查[FromBody]特性来识别,但不知道在过滤器中如何获取该信息。现有代码如下:

端点配置

var endpoints = app.MapGroup("api/v1")
    .AddEndpointFilter<RequestResponseLogFilter>();

endpoints.MapPost("/endpoint", async ([FromServices] ServiceA serviceA, [FromServices] ServiceB serviceB, [FromBody] MyRequest request) =>
    await MyEndpoint.DoSomething(serviceA, serviceB, request));

自定义特性与DTO

public class RequestBodyAttribute : Attribute
{
}

[RequestBody]
public class MyRequest
{
}

现有日志过滤器

public class RequestResponseLogFilter : IEndpointFilter
{
    public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
    {
        var httpContext = context.HttpContext;
        var logger = httpContext.RequestServices.GetService<ILogger>()!;

        object? requestBody = context.Arguments.FirstOrDefault(a => a?.GetType().GetCustomAttribute<RequestBodyAttribute>() != null);

        logger.Information("{@Request}", LogHelper.PrepareRequest(httpContext, requestBody));

        var stopwatch = Stopwatch.StartNew();
        var result = await next(context);
        stopwatch.Stop();

        logger.Information("{@Response}", LogHelper.PrepareResponse(httpContext, result, stopwatch.Elapsed));
        return result;
    }
}
解决方案

可以通过EndpointFilterInvocationContext的MethodInfo获取端点方法的参数元数据,结合[FromBody]特性精准定位请求体参数,无需额外标记或依赖参数位置。修改后的过滤器代码如下:

using Microsoft.AspNetCore.Mvc;
using System.Reflection;

public class RequestResponseLogFilter : IEndpointFilter
{
    public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
    {
        var httpContext = context.HttpContext;
        var logger = httpContext.RequestServices.GetService<ILogger>()!;

        // 获取方法参数信息,匹配带[FromBody]特性的参数
        var methodParams = context.MethodInfo.GetParameters();
        object? requestBody = null;
        for (int i = 0; i < methodParams.Length; i++)
        {
            if (methodParams[i].GetCustomAttribute<FromBodyAttribute>() != null)
            {
                requestBody = context.Arguments[i];
                break; // 通常POST请求只有一个FromBody参数,找到后直接跳出
            }
        }

        logger.Information("{@Request}", LogHelper.PrepareRequest(httpContext, requestBody));

        var stopwatch = Stopwatch.StartNew();
        var result = await next(context);
        stopwatch.Stop();

        logger.Information("{@Response}", LogHelper.PrepareResponse(httpContext, result, stopwatch.Elapsed));
        return result;
    }
}

说明

  • 利用context.MethodInfo.GetParameters()获取端点方法的所有参数元数据,遍历每个参数检查是否带有[FromBody]特性
  • 通过参数索引对应到context.Arguments中的实参,精准获取请求体对象
  • 无需给DTO添加任何自定义特性,也不依赖参数位置,完全基于ASP.NET Core原生的参数绑定特性判断,避免遗漏或位置错误的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 01:20:23