为什么将异常消息视为null

时间:2017-03-10 08:50:12

标签: c# validation asp.net-web-api data-annotations modelstate

我有基于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

我如何得到这个?

3 个答案:

答案 0 :(得分:1)

据我所知,这是一个常见问题:SO question 1SO 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;