.NET 5 REST API如何配置让ModelState错误的Exception字段非空?
解决.NET 5 REST API中ModelState错误无Exception字段的问题
方法一:替换默认类型转换错误消息提供器
.NET默认模型绑定在类型转换失败时,只会生成错误消息,不会把底层异常(比如FormatException)附加到ModelState的Error项里。你可以通过替换ModelBindingMessageProvider的类型转换错误提供器,手动把异常关联进去。
在Startup.cs的ConfigureServices里添加以下配置:
services.AddControllers(options => { options.ModelBindingMessageProvider.SetTypeConversionErrorMessageProvider(context => { var conversionException = context.ValueProviderResult.Exception; if (conversionException != null) { // 把异常作为第三个参数传入,给ModelStateError附加Exception字段 context.ModelState.TryAddModelError( context.ModelName, $"无法将值转换为{context.ModelMetadata.Name}类型", conversionException); // 返回空字符串,避免默认错误消息重复添加 return string.Empty; } return context.ModelBindingMessageProvider.GetTypeConversionErrorMessage(context.ModelMetadata.Name); }); });
这个方法会全局生效,所有类型转换失败的场景都会自动把异常绑定到ModelStateError中。
方法二:自定义模型绑定器(针对特定类型)
如果只需要处理某几种特定类型的转换异常,可以自定义IModelBinder,在转换失败时手动添加带异常的错误。
比如针对整数类型的绑定器实现:
public class IntWithExceptionBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); if (valueResult == ValueProviderResult.None) { return Task.CompletedTask; } bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueResult); try { var intValue = int.Parse(valueResult.FirstValue, CultureInfo.InvariantCulture); bindingContext.Result = ModelBindingResult.Success(intValue); } catch (FormatException ex) { bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, "输入不是有效的整数", ex); } catch (OverflowException ex) { bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, "输入的整数超出范围", ex); } return Task.CompletedTask; } }
然后在Startup.cs里注册这个绑定器(全局生效):
services.AddControllers(options => { options.ModelBinderProviders.Insert(0, new BinderTypeModelBinderProvider(typeof(IntWithExceptionBinder))); });
或者只在特定模型属性上使用:
public class UserRequest { [ModelBinder(BinderType = typeof(IntWithExceptionBinder))] public int Age { get; set; } }
验证效果
配置完成后,当传入错误类型的数据触发转换失败时,在你的HttpErrorHandlerAttribute的OnActionExecuting方法中,遍历ModelState.Values.SelectMany(v => v.Errors)就能拿到带有Exception字段的错误项,之后就可以按异常类型(比如FormatException、OverflowException)做过滤处理。
内容的提问来源于stack exchange,提问作者K.W
相关产品推荐
相关产品推荐

