针对 MVC 中非必需属性的整数验证

ror*_*yok 4 c# validation data-annotations asp.net-mvc-3

我试图验证我拥有的模型上的属性。此属性不是必需的,因此如果其无效的 MVC 似乎会忽略它。我什至创建了一个自定义 ValidationAttribute,但没有任何作用。

public class NumberWang : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        if (value == null)
            return true;

        int g;
        if (int.TryParse(value.ToString(), out g))
        {
            if (g >= 0)
                return true;
        }
        return false;
    }
}

public class MyModel 
{
    [Range(0, 999999, ErrorMessage = "category_id must be a valid number")]
    [NumberWang(ErrorMessage = "That's NumberWang!")]
    public int? category_id { get; set; }

    /* there are other properties of course, but I've omitted them for simplicity */

    public void Validate()
    {
        Validator.TryValidateProperty(this.category_id,
        new ValidationContext(this, null, null) { MemberName = "category_id" },
        this.validation_results);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我将值“abc”作为category_id传递给该模型,它就可以很好地验证。我究竟做错了什么?

ror*_*yok 5

我找到了一个丑陋的解决方法。

似乎如果category_id 是可空的int?并且我的值不是有效数字,则会传递空值,并且模型不会看到无效的“abc”值。

[Range(0, 999999, ErrorMessage = "category_id must be a valid number")]
public int? category_id { get; set; }

// when we pass a good number
MyAction?category_id=123
validation: successful

// when we pass a bad number
// validation ignores it. not what we want. 
MyAction?category_id=abc
validation: successful
Run Code Online (Sandbox Code Playgroud)

如果我将category_id更改为不可空的int,即使没有传递任何值,它也会失败验证。

[Range(0, 999999, ErrorMessage = "category_id must be a valid number")]
public int? category_id { get; set; }

// when we pass a good number
MyAction?category_id=123
validation: successful

// when we pass an bad number
MyAction?category_id=abc
validation: "category_id must be a valid number"

// BUT, when we don't pass any number at all ... 
MyAction 
validation: "category_id must be a valid number"
Run Code Online (Sandbox Code Playgroud)

丑陋的解决方法

如果我将 Category_id 更改为 a string,然后仅int在需要时将其转换为 an ,我可以仅使用正确验证它[Range]

[Range(0, 999999, ErrorMessage = "category_id must be a valid number")]
public string category_id { get; set; }

// when we pass a good number
MyAction?category_id=123
validation: successful

// when we pass a bad number
MyAction?category_id=abc
validation: "category_id must be a valid number"

// no number, no validation. hooray!
MyAction 
validation: successful
Run Code Online (Sandbox Code Playgroud)

它很丑,但很有效。

(注意:不需要自定义属性,因此我将其删除并仅使用 [Range])