为什么获取异常消息为空

Why getting exception message as null

我有基于 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 传递,它会 returns Data Annotations 中提到的正确错误消息,而如果我将 string 传递给 CountryId,进入else条件(*ModelState.IsValid = false*) 但是 ErrorMessage 是空的。

虽然如果我调试并将以下语句放在快速观察中。

 msg = ModelState.SelectMany(s => s.Value.Errors).FirstOrDefault().Exception.Message;

它returns - Could not convert string to integer: en. Path 'Country', line 6, position 14.

为什么在这种情况下,我没有收到 CountryId Invalid

的错误消息

我如何得到这个?

据我所知,这是一个常见问题:SO question 1, SO question 2

根据代码,任何验证属性都有 creating a wrapper, derived from RequestFieldValidatorBase。每个包装器调用 ValidationAttributeIsValid 方法。在 RequestFieldValidatorBase 的方法 Validate 中传递表单值进行验证。

因此,RequiredAttribute不会失败,因为表单值不为空且不是null,而RangeAttribute不会失败,因为它在将此值转换为int时遇到问题.

为了实现您想要的行为,建议创建您自己的验证属性或使用 RegularExpressionAttribute。你可以看看this answer.

我认为范围验证器不适合字符串输入,即它们仅在输入有效整数时触发。它不强制执行传入的类型。 尝试将注释更改为正则表达式。

[RegularExpression("([1-9][0-9]*)", ErrorMessage = "Country code invalid")]
public string Country { get; set; }

参照此linkInteger validation against non-required attributes in MVC

作为脏补丁,我将我的 属性 从 int 修改为 string 并用正则表达式对其进行了修饰。

使用 RegularExpressionAttribute does not prevent RangeAttribute 抛出 "Could not convert string to integer" 异常。所以只筛选正确的:

var msg = ModelState.SelectMany(s => s.Value.Errors)
                    .FirstOrDefault(_ => _.Exception == null)
                    .ErrorMessage;