【问题标题】:Custom validation attribute calling another validation attribute自定义验证属性调用另一个验证属性
【发布时间】:2013-01-17 22:21:49
【问题描述】:

我想创建一个调用其他验证属性的自定义验证属性。

例如,我想创建一个名为PasswordValidationAttribute 的属性。我希望它用RequiredAttributeRegularExpressionAttributeStringLengthAttribute 来装饰它定义的属性,并定义了各种参数(例如密码的正则表达式以及最大和最小字符串长度)。

我正在努力从哪里开始,确定涉及多少工作,并确定是否有可能。一旦将此属性应用于属性,我希望它能够正确处理 ValidationMessageFor HtmlHelper 并进行服务器端调用。我希望我不需要重新定义它们(否则工作量会很大)。

【问题讨论】:

    标签: c# asp.net-mvc validation custom-attributes


    【解决方案1】:

    对于 .net 4,它可能看起来像:

    [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
    public class MyValidationAttribute : ValidationAttribute
    {
        private readonly bool isRequired;
    
        public string Regex { get; set; }
    
        public int StringLength { get; set; }
    
        public MyValidationAttribute(bool isRequired)
        {
            this.isRequired = isRequired;
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var composedAttributes = ConstructAttributes().ToArray();
            if (composedAttributes.Length == 0) return ValidationResult.Success;
    
            var errorMsgBuilder = new StringBuilder();
            foreach (var attribute in composedAttributes)
            {
                var valRes = attribute.GetValidationResult(value, validationContext);
                if (valRes != null && !string.IsNullOrWhiteSpace(valRes.ErrorMessage))
                    errorMsgBuilder.AppendLine(valRes.ErrorMessage);
            }
            var msg = errorMsgBuilder.ToString();
            if (string.IsNullOrWhiteSpace(msg))
                return ValidationResult.Success;
            return new ValidationResult(msg);
        }
    
        private IEnumerable<ValidationAttribute> ConstructAttributes()
        {
            if (isRequired)
                yield return new RequiredAttribute();
            if (Regex != null)
                yield return new RegularExpressionAttribute(Regex);
            if (StringLength > 0)
                yield return new StringLengthAttribute(StringLength);
        }
    }
    

    用法:

    [MyValidationAttribute(true, Regex = "[a-z]*", StringLength = 3)]
    public string Name { get; set; }
    

    .net 3.5 中存在一个限制,您不能从底层属性动态构造消息值(至少我无法通过它)。您只能为每个属性设置一条消息。

    所有改变都在方法IsValid内。

    public override bool IsValid(object value)
    {
        var composedAttributes = ConstructAttributes().ToArray();
        if (composedAttributes.Length == 0) return true;
        return composedAttributes.All(a => a.IsValid(value));
    }
    

    注意ErrorMessage

    .net 3.5 中ValidationAttributeIsValid 方法的返回值不是ValidationResult,而是bool。当我尝试设置ErrorMessage 时,出现value can be set only once 的错误。

    【讨论】:

    • 这看起来不错,我明天早上去考试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多