4

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

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

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

4

1 回答 1

5

对于.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

IsValid.net 3.5 中方法的返回值ValidationAttribute不是ValidationResultbut bool。当我尝试设置时ErrorMessage,我得到了错误value can be set only once

于 2013-02-02T22:45:26.643 回答