.NET 8 Kestrel中间件如何获取Post/Put请求的入参类类型?
获取.NET 8最小API中POST/PUT请求的入参类型
在.NET 8的Kestrel环境下,要在中间件中获取POST/PUT请求对应的入参类类型,可以通过**端点元数据(Endpoint Metadata)**实现,具体方案如下:
核心思路
最小API的端点配置信息会被封装到RouteHandlerActionDescriptor元数据中,我们可以从HttpContext中拿到当前请求对应的端点,再从中提取带有[FromBody]特性的参数类型。
中间件实现代码
修改你的ValidateModelMiddleware的InvokeAsync方法:
public async Task InvokeAsync(HttpContext context, RequestDelegate next) { if (context.Request.Method is "POST" or "PUT") { var endpoint = context.GetEndpoint(); if (endpoint != null) { // 获取最小API的路由处理程序描述符 var actionDescriptor = endpoint.Metadata.GetMetadata<RouteHandlerActionDescriptor>(); if (actionDescriptor != null) { // 筛选出带有[FromBody]特性的参数 var bodyParam = actionDescriptor.Parameters .FirstOrDefault(p => p.ParameterInfo.GetCustomAttributes(typeof(FromBodyAttribute), inherit: true).Any()); if (bodyParam != null) { Type requestBodyType = bodyParam.ParameterType; // 此时requestBodyType即为当前请求对应的入参类型(比如MyObject) // 重置请求体流位置,确保可以正常读取 context.Request.Body.Position = 0; var requestBodyJson = await new StreamReader(context.Request.Body).ReadToEndAsync(); // 反序列化为目标类型 var model = JsonSerializer.Deserialize(requestBodyJson, requestBodyType); // 这里添加你的自定义验证逻辑 } } } } await next(context); }
关键注意事项
- 请求体流处理:如果中间件在模型绑定之后执行,请求体流可能已被读取到末尾,需要先重置流位置;或者在中间件管道最前面启用请求体缓冲,避免流无法重复读取:
// 在Program.cs中添加,放在UseMiddleware之前 app.Use(async (context, next) => { context.Request.EnableBuffering(); await next(); });
- 兼容控制器场景:如果项目同时包含控制器风格的API,只需把
RouteHandlerActionDescriptor替换为ControllerActionDescriptor,逻辑通用:
var controllerActionDescriptor = endpoint.Metadata.GetMetadata<ControllerActionDescriptor>(); if (controllerActionDescriptor != null) { var bodyParam = controllerActionDescriptor.Parameters .FirstOrDefault(p => p.BindingInfo?.BindingSource == BindingSource.Body); // 后续反序列化、验证逻辑与最小API一致 }
内容的提问来源于stack exchange,提问作者ashlar64
相关产品推荐
相关产品推荐

