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

本文关键字:属性 整数 验证 MVC | 更新日期: 2023-09-27 18:28:16

我试图验证我拥有的模型上的属性。这个属性不是必需的,所以如果它的无效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);
    }
}

如果我将值"abc"作为category_id传递给这个模型,它就会很好地验证。我做错了什么?

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

我发现了一个丑陋的解决方法。

似乎,如果category_id是一个可为null的int?,而我的值不是一个有效的数字,则会传递一个null值,并且模型不会看到无效的"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

如果我将category_id更改为不可为null的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"

丑陋的变通办法

如果我将category_id更改为string,然后仅在需要时将其转换为int,则我可以仅使用[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

它很难看,但它有效。

(注意:不需要自定义属性,所以我删除了它,只使用[Range])

型号:

// "('s*[0-9]{0,6})" for 999999 max
// "('s*[0-9]*)" for "infinite"
[RegularExpression(@"('s*[0-9]{0,6})", ErrorMessage = "Field must be a natural number (max 999999)")]
public int? Quantity { get; set; }

视图:

@Html.TextBoxFor(m => m.Quantity)
@Html.ValidationMessageFor(m => m.Quantity)

首先,您的模型应该实现IValidatableObject,但只有在ModelState有效的情况下才会调用Validate方法。此链接会有所帮助。您是否将您的模型作为动作中的参数接收?您是否要求ModelState.IsValid?这应该可以与默认模型绑定器配合使用。

我找到了一个我喜欢的变通方法。我遇到的问题也是类似的问题,值必须大于0和一个数字,所以当我尝试将9999999999(无效)字符串转换为数字时,它引发了一个异常,并且没有在帖子中显示模型状态有错误消息。我希望这是一个主题,因为它听起来像"当我输入一个无效的数字时,规则似乎不适用"

由于我的数字必须是正数,我将该值截获到一个匿名类型对象(动态)中,并将其用作模型的用户和私有int属性之间的截获体。当我这样做的时候,数据注释正如预期的那样工作。

    public dynamic MyProperty
    {
        get { return _myProperty; }
        set
        {
            try
            {

/我必须将该值转换为String,因为它以String[]的形式出现,如果有多个值,那么它应该有问题,所以你用一个无效字符将其连接在一起并抛出错误,或者你取第一个值/_myProperty==Convert.ToInt32(String.Join("a",value));}catch(异常e){_myProperty=-1;}}}

    private int _myProperty;