我有这样一个接口,现在我想对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<ApiBehaviorOptions>(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);
};
});
国际化方案: https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/localization?view=aspnetcore-8.0
编辑好多语言的资源文件, 然后 services.AddLocalization / Configure<RequestLocalizationOptions> 配置.
public class MyModel
{
[Required(ErrorMessage = "ValidationResources.RequiredField")]
[StringLength(50, ErrorMessage = "ValidationResources.StringLength")]
public string Name { get; set; }
}
这可能不是我想要的,使用这种方式我需要已知所有的类型转换错误,再配置资源文件。我在想这种类型转换的异常,是否不返回过于具体的错误信息。
@空虚假面:
你这不叫本地化(通常叫国际化/i18n), 叫自定义错误信息.
你在InvalidModelStateResponseFactory 这里已经做好自定义了呀, 不对么?
@czd890: 是的,是自定义错误,我描述错了。InvalidModelStateResponseFactory能获取到这些异常并且自定义输出。
但是现在模型绑定的类型转换过程中,想要输出具体的错误信息,获取的是core本身的提示信息:像Could not convert string to integer。
那我需要将它转换成中文,这就需要我提前预知所有的.net类型转换异常才能去做转换。有没有接口可以统一处理。像IValidationMetadataProvider这种我就可以对自带的模型验证(例如Required)提示信息按中文输出。
在我这个请求中,本来我是想尝试通过ModelBindingMessageProvider.SetValueMustBeANumberAccessor来设置自定义的错误信息,但实际上执行过程中.net类型转换的异常并没有被ModelBindingMessageProvider捕获。可能我更需要的是做一个通用的自定义模型绑定,用来自定义类型转换的错误信息。