自定义验证属性 - 有效整数

时间:2014-08-11 10:29:12

标签: asp.net-mvc asp.net-mvc-4

我有一点奇怪的要求。

我有一个有2个属性的类,如下所示:

public class MyViewModel
{
    [EnhancedServiceValidInteger("Name")]
    public int NumberOfItems { get; set; }

    public string Name { get; set; }
}

上面的类用作构建动态表单的动态字段。当NumberOfItems不正确(不是有效整数)时,应使用Name属性中的值作为DisplayName显示错误消息,并且是任何错误消息的输出。

我已经实现了触发的自定义验证属性,但如果用户输入了一封信,我希望该属性可以选择该属性。在这种情况下(IsValid(对象值,...)),IsValid方法的value属性始终为0,因此验证通过,并且MyCustomValidIntegerValidator中没有任何断点被命中。为什么价值不会被设置为' aaa'如果这是在UI中输入的内容?

有人可以帮忙吗?

我有以下自定义验证属性:

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false)]
public class MyCustomValidInteger : ValidationAttribute
{
    private readonly string _validationNameFromProperty;

    public EnhancedServiceValidInteger(string validationNameFromProperty) : base("{0} contains invalid character.")
    {
        _validationNameFromProperty = validationNameFromProperty;
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        // the the other property
        var property = validationContext.ObjectType.GetProperty(_validationNameFromProperty);

        // check it is not null
        if (property == null)
        {
            return new ValidationResult(String.Format("Unknown property: {0}.", _validationNameFromProperty));
        }

        // get the other value
        var nameToUse = property.GetValue(validationContext.ObjectInstance, null).ToString();

        if (value == null || value.ToString().Length == 0)
        {
            return ValidationResult.Success;
        }

        int i;

        var errorMessage = string.Format("The value '{0}' is not valid for {1}", value, nameToUse);

        ValidationResult validationResult = !int.TryParse(value.ToString(), out i) ? new ValidationResult(errorMessage) : ValidationResult.Success;

        return validationResult;
    }
}

以下是上述类的DataAnnotationsModelValidator实现:

public class MyCustomValidIntegerValidator : DataAnnotationsModelValidator<MyCustomValidInteger>
{
    public MyCustomValidIntegerValidator(ModelMetadata metadata, ControllerContext context, EnhancedServiceValidInteger attribute) 
        : base(metadata, context, attribute)
    {
        if (!attribute.IsValid(context.HttpContext.Request.Form[metadata.PropertyName]))
        {
            var propertyName = metadata.PropertyName;
            context.Controller.ViewData.ModelState[propertyName].Errors.Clear();
            context.Controller.ViewData.ModelState[propertyName].Errors.Add(attribute.ErrorMessage);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

至于为什么,当表单值发布回控制器时,DefaultModelBinder首先将值绑定到属性(使用SetValue() PropertyDescriptor方法)。由于属性为int且值为string,因此无法设置并分配默认值。直到此绑定完成,验证过程才开始。

不确定如何实现您想要的效果,但创建自定义ModelBinder可能是一个选项