【问题标题】:Enterprise Library Validation - Allow Nulls but verify other properties?企业库验证 - 允许空值但验证其他属性?
【发布时间】:2012-12-05 22:12:46
【问题描述】:

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

[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 电子邮件验证。

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

编辑

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

谢谢!

【问题讨论】:

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


    【解决方案1】:

    我自己从来不需要这样做,但我认为您可以创建自己的 DataAnnotations Validation 上下文。看这篇文章:

    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; }
    

    【讨论】:

    • 已编辑以包含有关如何在传统视图/控制器操作验证之外执行此操作的参考。
    【解决方案2】:

    看到有人通过属性进行验证只会伤害我的眼睛。再一次,我建议使用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();
        }
    }
    

    这是关于视图模型的。现在,满足您对这是 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
    

    【讨论】:

    • 这很讽刺,因为我认为为每个属性创建一个验证器是大量工作和维护的噩梦。但无论我转向哪种方式,看起来我都必须做这样的事情,因为我只是没有得到我想要的属性/配置设置的结果。
    【解决方案3】:

    我认为问题在于您不能嵌套多个 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");
    

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

    【讨论】:

    • +1 用于我正在使用的配置方法
    【解决方案4】:

    因此,感谢您提供的所有解决方案,但基于 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));
        }
    }
    

    作为类的方法。

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

    【讨论】:

      【解决方案5】:

      【讨论】:

      • Stack Overflow 不鼓励仅链接的答案。或许可以展示NullIgnoringValidatorWrapper 类如何用于解决 OP 的问题并提供链接以供参考。
      猜你喜欢
      • 1970-01-01
      • 2019-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多