如何在.NET 8 Minimal WebAPI中自定义枚举查询参数解析错误
.NET 8 Minimal WebAPI 自定义查询字符串枚举参数错误提示
查询字符串的枚举参数绑定不经过JSON转换器,默认错误提示不够友好,可通过以下几种方案实现自定义提示:
方案一:自定义枚举绑定器(推荐,精准控制单个参数)
实现IBinder接口,手动处理枚举转换逻辑,失败时添加自定义错误信息:
public class EnumBinder<TEnum> : IBinder where TEnum : struct, Enum { public Task BindModelAsync(ModelBindingContext bindingContext) { var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueProviderResult == ValueProviderResult.None) { return Task.CompletedTask; } bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult); var inputValue = valueProviderResult.FirstValue; if (!Enum.TryParse<TEnum>(inputValue, ignoreCase: true, out var enumResult) || !Enum.IsDefined(typeof(TEnum), enumResult)) { var validOptions = string.Join(", ", Enum.GetNames(typeof(TEnum))); bindingContext.ModelState.AddModelError( bindingContext.ModelName, $"无效的枚举值「{inputValue}」,可选值为:{validOptions}"); return Task.CompletedTask; } bindingContext.Result = ModelBindingResult.Success(enumResult); return Task.CompletedTask; } }
在Minimal API端点中指定绑定器:
// 假设存在自定义枚举MyStatusEnum app.MapGet("/api/query", async ([FromQuery, Bind(typeof(EnumBinder<MyStatusEnum>))] MyStatusEnum status) => { return Results.Ok(new { Status = status }); });
方案二:端点过滤器(复用性强,针对特定枚举)
通过IEndpointFilter拦截请求,验证枚举参数有效性:
public class EnumValidationFilter<TEnum> : IEndpointFilter where TEnum : struct, Enum { public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next) { var paramIndex = Array.FindIndex(context.MethodInfo.GetParameters(), p => p.ParameterType == typeof(TEnum)); if (paramIndex == -1) return await next(context); var inputValue = context.Arguments[paramIndex]; if (inputValue is TEnum enumVal && !Enum.IsDefined(typeof(TEnum), enumVal)) { var validOptions = string.Join(", ", Enum.GetNames(typeof(TEnum))); return Results.BadRequest(new { Error = $"无效的枚举值「{enumVal}」,可选值为:{validOptions}" }); } return await next(context); } }
注册过滤器到端点:
app.MapGet("/api/query", async ([FromQuery] MyStatusEnum status) => { return Results.Ok(new { Status = status }); }) .AddEndpointFilter<EnumValidationFilter<MyStatusEnum>>();
方案三:全局模型状态拦截(统一处理所有枚举错误)
通过中间件捕获400错误,替换默认的枚举绑定提示:
app.Use(async (context, next) => { await next(); if (context.Response.StatusCode == StatusCodes.Status400BadRequest) { var modelStateFeature = context.Features.Get<ModelStateFeature>(); if (modelStateFeature?.ModelState.IsValid == false) { var enumErrorMessages = modelStateFeature.ModelState.Values .SelectMany(v => v.Errors) .Where(e => e.ErrorMessage.Contains("枚举")) .Select(e => $"自定义提示:{e.ErrorMessage}") .ToList(); if (enumErrorMessages.Any()) { context.Response.ContentType = "application/json"; await context.Response.WriteAsJsonAsync(new { Errors = enumErrorMessages }); } } } });
内容的提问来源于stack exchange,提问作者Seva Alekseyev
相关产品推荐
相关产品推荐

