我有基于ASP.Net WebAPI
的应用程序。以下是我的DTO。
public class CustomerTO
{
[Required(ErrorMessage="Name required")]
[StringLength(50, MinimumLength = 3, ErrorMessage = "Name invalid")]
public string Name { get; set; }
[Required(ErrorMessage="CountryId required")]
[Range(1,250,ErrorMessage="CountryId invalid")]
public int Country { get; set; }
}
我的API控制器。
[HttpPost]
[AllowAnonymous]
public HttpResponseMessage Post([FromBody]CustomerTO model)
{
if (ModelState.IsValid)
{
//my stuff
}
else
{
var msg = ModelState.SelectMany(s => s.Value.Errors).FirstOrDefault().ErrorMessage;
}
}
如果用户将任意必填字段作为Null
传递,则会返回Data Annotations
中提到的正确错误消息,而如果我string
传递CountryId
,则会进入进入else
条件(*ModelState.IsValid = false*
)
但是ErrorMessage是空的。
如果我调试&快速观察下面的陈述。
msg = ModelState.SelectMany(s => s.Value.Errors).FirstOrDefault().Exception.Message;
返回 - Could not convert string to integer: en. Path 'Country', line 6, position 14.
为什么在这种情况下,我没有收到错误消息CountryId Invalid
我如何得到这个?
答案 0 :(得分:1)
据我所知,这是一个常见问题:SO question 1,SO question 2。
根据代码,来自任何验证属性的creating a wrapper都来自RequestFieldValidatorBase
。每个包装器调用IsValid
的{{1}}方法。在ValidationAttribute
的方法Validate
中传递表单值以进行验证。
因此,RequestFieldValidatorBase
不会失败,因为表单值不为空且不是RequiredAttribute
,并且null
不会失败,因为它将此值转换为int时出现问题。 / p>
要实现所需的行为,建议您创建自己的验证属性或使用RangeAttribute
。您可以查看this answer。
答案 1 :(得分:1)
我认为范围验证器不能满足字符串输入的要求,即它们只有在它是有效整数时才会触发。它没有强制执行传入的类型。 尝试将注释更改为正则表达式。
[RegularExpression("([1-9][0-9]*)", ErrorMessage = "Country code invalid")]
public string Country { get; set; }
参考此链接Integer validation against non-required attributes in MVC
作为脏补丁,我将我的属性从int
修改为string
&用正则表达式装饰它。
答案 2 :(得分:0)
使用RegularExpressionAttribute不会阻止RangeAttribute抛出“无法将字符串转换为整数”异常。所以只过滤正确的一个:
var msg = ModelState.SelectMany(s => s.Value.Errors)
.FirstOrDefault(_ => _.Exception == null)
.ErrorMessage;