企业库验证 - 允许空值但验证其他属性?

时间:2012-12-18 16:37:58

标签: c# asp.net-mvc enterprise-library

我在类的属性中设置了一个属性列表,如下所示:

[ValidatorComposition(CompositionType.Or, Ruleset = "BillingEmail", MessageTemplate = Constants.ERROR_INVALID_EMAILADDRESS)]
[NotNullValidator(Negated = true, Ruleset = "BillingEmail")]
[StringLengthValidator(0, RangeBoundaryType.Exclusive, 255, RangeBoundaryType.Inclusive, Ruleset = "BillingEmail")]
[RegexValidator(@"^[A-Z0-9._%-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$", RegexOptions.IgnoreCase, Ruleset = "BillingEmail")]
public string BillingEmailAddress { get; set; }

我遇到的问题是我输入:

someone@blah

,电子邮件地址仍然通过验证。

我想要的规则是如果BillingEmailAddress是NULL,那么它是VALID。但是,如果它不是NULL,那么EmailAddress需要验证字符串长度并通过Regex Email验证。

有人可以告诉我在此验证中缺少什么或我做错了吗?

修改

请注意,这不是MVC模型,而是类对象。此属性是DTO的一部分,而不是页面模型(此层不使用DataAnnotations类)。

谢谢!

5 个答案:

答案 0 :(得分:2)

所以,感谢您提供所有解决方案,但请基于Tuzo提供的链接。我必须实施:

[HasSelfValidation]
public class SomeDTO
{
    public string BillingEmailAddress { get; set; }
}

上课。然后,我必须实施:

[SelfValidation]
public void Validation(ValidationResults results)
{
    if (!Utility.IsValidEmailAddress(this.BillingEmailAddress))
    {
        results.AddResult(new ValidationResult(Constants.ERROR_INVALID_EMAILADDRESS, this, "", "", null));
    }
}

作为课堂的一种方法。

我希望这可以帮助有同样问题的人。

答案 1 :(得分:1)

看到有人通过属性进行验证只是伤害了我的眼睛。我再次建议使用FluentValidation。您的模型将更加清洁,您的验证现在将如下所示:

public class CustomerValidator: AbstractValidator<Customer>
{
    public CustomerValidator()
    {
        RuleFor(customer => customer.BillingEmailAddress)
            .NotEmpty()
            .WithMessage("You must specify Email Address.")
            .Length(1, 255)
            .WithMessage("Email address is too long.")
            .EmailAddress();
    }
}

这与View Model有关。现在,为了满足您对DTO这一事实的要求。您可以单独触发验证:

Customer customer = // get your customer from whatever source
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
if(results.Errors.Count() > 0)
    // do whatever in case your customer class does not validate

答案 2 :(得分:1)

我认为问题在于您无法嵌套多个ValidatorComposition属性。

您可以使用基于配置的方法完成您想要的任务:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="validation" type="Microsoft.Practices.EnterpriseLibrary.Validation.Configuration.ValidationSettings, Microsoft.Practices.EnterpriseLibrary.Validation, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
    </configSections>
    <validation>
        <type name="ConsoleApplication.Order" defaultRuleset="Validation Ruleset"
            assemblyName="ConsoleApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
            <ruleset name="Validation Ruleset">
                <properties>
                    <property name="BillingEmailAddress">
                        <validator type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.AndCompositeValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                            name="And Composite Validator">
                            <validator type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.OrCompositeValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                                name="Or Composite Validator">
                                <validator type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.NotNullValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                                    negated="true" name="Not Null Validator" />
                                <validator type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                                    upperBound="255" lowerBound="5" lowerBoundType="Exclusive"
                                    name="String Length Validator" />
                            </validator>
                            <validator type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.OrCompositeValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                                name="Or Composite Validator 2">
                                <validator type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.NotNullValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                                    negated="true" name="Not Null Validator" />
                                <validator type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.RegexValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                                    pattern="^[A-Z0-9._%-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$" options="IgnoreCase"
                                    name="Regular Expression Validator" />
                            </validator>
                        </validator>
                    </property>
                </properties>
            </ruleset>
        </type>
    </validation>
</configuration>

您还可以通过编程方式创建嵌套验证器。请参阅使用复合验证器验证@ http://msdn.microsoft.com/en-us/library/ff953182(v=pandp.50).aspx

另一种选择可能是使用多个规则集:

    [ValidatorComposition(CompositionType.Or, Ruleset = "BillingEmailStringLength", MessageTemplate = Constants.ERROR_INVALID_EMAILADDRESS)]
    [StringLengthValidator(5, RangeBoundaryType.Exclusive, 255, RangeBoundaryType.Inclusive, Ruleset = "BillingEmailStringLength")]
    [NotNullValidator(Negated = true, Ruleset = "BillingEmailStringLength")]
    [ValidatorComposition(CompositionType.Or, Ruleset = "BillingEmailStringFormat", MessageTemplate = Constants.ERROR_INVALID_EMAILADDRESS)]
    [RegexValidator(@"^[A-Z0-9._%-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$", RegexOptions.IgnoreCase, Ruleset = "BillingEmailStringFormat")]
    [NotNullValidator(Negated = true, Ruleset = "BillingEmailStringFormat")]
    public string BillingEmailAddress { get; set; }

然后,您可以指定多个规则集进行验证:

var vrs = Validation.Validate(objectToValidate, 
              "BillingEmailStringLength", "BillingEmailStringFormat");

另一种方法是创建自己的验证器来处理空值。

答案 3 :(得分:0)

我自己从未这样做,但我认为您可以创建自己的DataAnnotations验证上下文。看这篇文章:

Check if Model is valid outside of Controller

然后你只需要创建一个验证属性。我使用自定义验证器在我的应用程序中使用类似的电子邮件地址。这是我的代码,经过修改以更好地适合您的问题。

public class MyEmailValidationAttribute : RegularExpressionAttribute
{
    public MyEmailValidationAttribute ()
        : base(@"^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-zA-Z0-9]{1}[a-zA-Z0-9\-]{0,62}[a-zA-Z0-9]{1})|[a-zA-Z])\.)+[a-zA-Z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$")
    {
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        Regex RegexObj = new Regex(this.Pattern);

        if (value == null)
        {
            return ValidationResult.Success;
        }           

        Match match = RegexObj.Match((string)value);

        if (!match.Success)
        {
            return new ValidationResult("Email not in correct format.");
        }

        return ValidationResult.Success;     
    }
}

然后在你的模型中添加:

//You may be able to remove some of your other attributes 
//by going this route so I won't include them all.
[MyEmailValidationAttribute()]
public string BillingEmailAddress { get; set; }

答案 4 :(得分:-1)