我有这样一个接口,现在我想对sex做入参验证,但是类型转换的时候直接返回 Could not convert string to integer: ss. Path ‘sex’, line 8, position 13. 我现在应该怎么拦截类型转换的异常?使得提示信息更加本地化。
[HttpPost] public async Task AddUser([FromBody] UserAddReq user) { await Task.Run(() => { return true; }); } public class UserAddReq { /// <summary> /// 昵称 /// </summary> [Required] public string NickName { get; set; } = string.Empty; /// <summary> /// 生日 /// </summary> [Required] [DisplayName("生日")] [JsonConverter(typeof(DateTimeJsonConvert), "yyyy-MM-dd")] public DateTime Birthday { get; set; } /// <summary> /// 性别0-女1-男 /// </summary> [DisplayName("性别")] [Range(1, 3)] public int Sex { get; set; } /// <summary> /// 职业 /// </summary> public string Occupation { get; set; } = string.Empty; /// <summary> /// 手机 /// </summary> [Phone] public string Mobile { get; set; } = string.Empty; /// <summary> /// 状态0冻结1正常 /// </summary> [JsonIgnore] public int State { get; set; } = 1; } public class DateTimeJsonConvert : IsoDateTimeConverter { public DateTimeJsonConvert(string dateTimeFormat) { this.DateTimeFormat = dateTimeFormat; } }
我实际想得到的是我自定义的异常信息,例如:
目前做了以下处理: 1.模型绑定错误消息自定义 services.AddControllers(o => { //A value for the ‘{0}’ parameter or property was not provided o.ModelBindingMessageProvider.SetMissingBindRequiredValueAccessor((x) => $”未 提供’{x}’ 参数或属性的值”); //A value is required o.ModelBindingMessageProvider.SetMissingKeyOrValueAccessor(() => $”需要一个值”); //A non-empty request body is required o.ModelBindingMessageProvider.SetMissingRequestBodyRequiredValueAccessor(() => $”需要非空的请求正文”); //The value ‘{0}’ is invalid o.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor((x) => $”值’{x}’无效,不能为Null”); //The value ‘{0}’ is not valid for {1}. o.ModelBindingMessageProvider.SetAttemptedValueIsInvalidAccessor((x, y) => $”值’{x}’对参数’{y}’无效”); //The value ‘{0}’ is not valid. o.ModelBindingMessageProvider.SetNonPropertyAttemptedValueIsInvalidAccessor((x) => $”值’{x}’无效”); //The supplied value is invalid for {0}. o.ModelBindingMessageProvider.SetUnknownValueIsInvalidAccessor((x) => $”提供的值对参数’{x}’无效”); //The supplied value is invalid. o.ModelBindingMessageProvider.SetNonPropertyUnknownValueIsInvalidAccessor(() => $”提供的值无效”); //The value ‘{0}’ is invalid. o.ModelBindingMessageProvider.SetValueIsInvalidAccessor((x) => $”值’{x}’无效”); //The field {0} must be a number o.ModelBindingMessageProvider.SetValueMustBeANumberAccessor((x) => $”字段’{x}’ 必须是数字”); //The field must be a number. o.ModelBindingMessageProvider.SetNonPropertyValueMustBeANumberAccessor(() => $”字段必须是数字”); })
2.ModeState错误信息统一处理 services.Configure(options => { options.InvalidModelStateResponseFactory = actionContext => { //ModelState验证顺序并不是按参数顺序验证 var param = actionContext.ModelState.Keys; var errors = actionContext.ModelState .Where(s => s.Value != null && s.Value.ValidationState == ModelValidationState.Invalid) .FirstOrDefault().Value!.Errors.ToList().Select(e => e.ErrorMessage).ToList(); //.SelectMany(s => s.Value!.Errors.ToList()) //.Select(e => new { e.ErrorMessage}) //.ToList(); var result = new MessageModel() { Status = StatusCodes.Status400BadRequest, Msg = string.Format(“数据验证不通过!” + “参数{0}输入有误,{1}”, param.FirstOrDefault(), errors[0]), IsSuccess = false, }; return new BadRequestObjectResult(result); }; });
在 ASP.NET Core 中,如果你希望对模型绑定过程中的类型转换异常进行自定义处理,以便能够给出本地化的错误信息,可以通过以下几个步骤来实现:
IModelBinder
ASP.NET Core 允许你通过实现自定义的 IModelBinder 来控制模型绑定的过程,包括类型转换。这样可以在绑定阶段捕获并处理异常。
首先,创建一个自定义的 IModelBinder:
public class CustomIntModelBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { if (bindingContext == null) { throw new ArgumentNullException(nameof(bindingContext)); } var modelName = bindingContext.ModelName; var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName); if (valueProviderResult == ValueProviderResult.None) { return Task.CompletedTask; } bindingContext.ModelState.SetModelValue(modelName, valueProviderResult); var valueAsString = valueProviderResult.FirstValue; if (string.IsNullOrEmpty(valueAsString)) { return Task.CompletedTask; } if (!int.TryParse(valueAsString, out int parsedValue)) { bindingContext.ModelState.TryAddModelError( modelName, $"The value '{valueAsString}' is not a valid integer for {modelName}."); return Task.CompletedTask; } bindingContext.Result = ModelBindingResult.Success(parsedValue); return Task.CompletedTask; } }
在 Startup.cs 的 ConfigureServices 方法中注册自定义的 IModelBinder:
Startup.cs
ConfigureServices
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(options => { options.ModelBinderProviders.Insert(0, new BinderTypeModelBinderProvider(typeof(int), new CustomIntModelBinder())); }); }
这样,当 ASP.NET Core 在模型绑定时遇到 int 类型的参数时,会使用我们自定义的 CustomIntModelBinder 来进行绑定,从而可以在其中添加自定义的验证逻辑和错误消息。
int
CustomIntModelBinder
通过上述方式,你可以在 CustomIntModelBinder 中添加适当的逻辑来处理类型转换异常。在 BindModelAsync 方法中,我们通过 int.TryParse 来尝试将字符串转换为整数。如果转换失败,我们使用 bindingContext.ModelState.TryAddModelError 来添加自定义的错误消息到模型状态中。
BindModelAsync
int.TryParse
bindingContext.ModelState.TryAddModelError
最后,你可以在控制器的方法参数中使用自定义的 IModelBinder,例如:
[HttpPost] public IActionResult AddUser([FromBody] UserAddReq user) { if (!ModelState.IsValid) { return BadRequest(ModelState); } // 如果 ModelState 验证通过,继续处理逻辑 // ... return Ok(); }
在 UserAddReq 类中的 Sex 属性上,可以使用 Range 属性来定义范围,并且通过上述自定义的 IModelBinder 来确保输入符合预期的整数范围,同时能够捕获和处理类型转换异常,以便给出本地化的错误消息。
UserAddReq
Sex
Range
这样,你就能够在 ASP.NET Core 中有效地处理模型绑定过程中的类型转换异常,并且提供自定义的错误信息,以更好地与前端交互和用户沟通。