2012-12-18 139 views
3

我有属性设置列表中的一个类上,看起来属性,如:企业库验证 - 允许空值但验证其他属性?

[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._%-][email protected](?:[A-Z0-9-]+\.)+[A-Z]{2,4}$", RegexOptions.IgnoreCase, Ruleset = "BillingEmail")] 
public string BillingEmailAddress { get; set; } 

我遇到的问题是,我进入:

[email protected] 

和电子邮件地址,还通过了验证。

我想要的规则是如果BillingEmailAddress是NULL,那么它是有效的。但是,如果它不是NULL,那么EmailAddress需要验证字符串长度并通过Regex电子邮件验证。

有人能告诉我什么是缺失或我在这个验证中做错了吗?

编辑

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

谢谢!

回答

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

作为类的一种方法。

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

0

我从来没有这样做过,但我认为你可以创建自己的DataAnnotations验证上下文。看到这个帖子:

Check if Model is valid outside of Controller

然后你只需要进行验证属性。我在我的应用程序中使用自定义验证器做了类似于电子邮件地址的操作。这里是我的代码,修改为更适合您的问题。

public class MyEmailValidationAttribute : RegularExpressionAttribute 
{ 
    public MyEmailValidationAttribute() 
     : base(@"^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~][email protected]((((([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; } 
+0

被编辑为包含对传统视图/控制器操作验证之外的方法的引用。 –

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

这是关于查看模型。现在,为了涵盖你对这个DTO的要求。您可以separatelly触发验证这样的:

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 
+0

这很具有讽刺意味,因为我认为为每个物业创建一个验证程序是一大堆工作和维护的噩梦。但是无论我把它转换成哪种方式,它看起来像我必须这样做,因为我只是没有得到我想要的属性/配置设置的结果。 – Sean

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._%-][email protected](?:[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._%-][email protected](?:[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"); 

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

+0

对于正在使用的配置方法+1 +1 – Kamal

-1
+0

在堆栈溢出时,仅阻止链接回答。也许可以展示如何使用'NullIgnoringValidatorWrapper'类来解决OP的问题并提供参考链接。 – drs