如何在Minimal APIs中复刻Web API的[FromBody]必填字段校验功能?
在Minimal APIs中复刻Web API的[FromBody]必填字段校验行为
方案一:使用内置数据注解与ModelState校验
传统Web API的自动必填校验依赖ModelState和数据注解,Minimal APIs默认不会自动触发,但可以通过以下步骤快速启用:
1. 给实体类字段添加必填注解
对字符串等引用类型字段添加[BindRequired]注解;值类型(如int)默认视为必填,无需额外注解(若需语义更明确也可添加):
using Microsoft.AspNetCore.Mvc; public class SomeObject { [BindRequired] public string Subject { get; set; } [BindRequired] public string Body { get; set; } public int Priority { get; set; } // 值类型默认必填 }
2. 在端点中启用ModelState校验
可以通过端点过滤器自动完成校验,无需手动编写检查逻辑:
app.MapPost("/doSomething", async ([FromBody] SomeObject request) => { // 业务逻辑实现 return Results.Ok(); }) .AddEndpointFilter<ValidateModelStateFilter>(); // 自动校验ModelState,无效时返回400 BadRequest
如果需要自定义错误响应格式,也可以手动检查ModelState:
app.MapPost("/doSomething", async ([FromBody] SomeObject request, HttpContext context) => { if (!context.ModelState.IsValid) { return Results.BadRequest(context.ModelState); // 返回包含错误详情的400响应 } // 业务逻辑实现 return Results.Ok(); });
方案二:编写通用泛型扩展实现自动校验
如果需要跨多个端点复用校验逻辑,可以编写泛型扩展方法,通过反射自动检查所有必填字段:
1. 实现通用校验扩展
using Microsoft.AspNetCore.Mvc; using System.Reflection; public static class MinimalApiValidationExtensions { // 泛型MapPost扩展,自动校验必填字段 public static RouteHandlerBuilder MapPostWithValidation<T>(this WebApplication app, string pattern, Func<T, Task<IResult>> handler) where T : class, new() { return app.MapPost(pattern, async ([FromBody] T request, HttpContext context) => { ValidateRequiredFields(request, context.ModelState); if (!context.ModelState.IsValid) { return Results.BadRequest(context.ModelState); } return await handler(request); }); } // 反射校验必填字段的核心逻辑 private static void ValidateRequiredFields<T>(T model, ModelStateDictionary modelState) where T : class { var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in properties) { // 判断字段是否为必填:非可空值类型,或带有[BindRequired]注解 bool isRequired = !prop.PropertyType.IsNullableValueType() && prop.PropertyType.IsValueType; isRequired |= prop.GetCustomAttributes(typeof(BindRequiredAttribute), inherit: true).Any(); if (isRequired) { var value = prop.GetValue(model); // 检查值是否为空(字符串额外检查空白内容) if (value == null || (prop.PropertyType == typeof(string) && string.IsNullOrWhiteSpace((string)value))) { modelState.AddModelError(prop.Name, $"字段 {prop.Name} 为必填项。"); } } } } // 辅助方法:判断是否为可空值类型 private static bool IsNullableValueType(this Type type) { return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); } }
2. 使用泛型扩展创建端点
只需指定实体类型,即可自动启用必填字段校验,无需重复编写校验代码:
app.MapPostWithValidation<SomeObject>("/doSomething", async (request) => { // 业务逻辑实现 return Results.Ok(); });
内容的提问来源于stack exchange,提问作者user4779
相关产品推荐
相关产品推荐

