比较日期DataAnnotations验证asp.net mvc的

问题描述:

可以说我有一个起始日期和结束日期的我和Wnt信号,以检查是否结束日期是不是更多的则相隔3个月从开始日期比较日期DataAnnotations验证asp.net mvc的

public class DateCompare : ValidationAttribute 
{ 
    public String StartDate { get; set; } 
    public String EndDate { get; set; } 

    //Constructor to take in the property names that are supposed to be checked 
    public DateCompare(String startDate, String endDate) 
    { 
     StartDate = startDate; 
     EndDate = endDate; 
    } 

    public override bool IsValid(object value) 
    { 
     var str = value.ToString(); 
     if (string.IsNullOrEmpty(str)) 
      return true; 

     DateTime theEndDate = DateTime.ParseExact(EndDate, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); 
     DateTime theStartDate = DateTime.ParseExact(StartDate, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture).AddMonths(3); 
     return (DateTime.Compare(theStartDate, theEndDate) > 0); 
    } 
} 

,我想落实到我的验证

这个[DateCompare( “起始日期”, “结束日期” 的ErrorMessage = “该协议只能在3个月之久!”)

我知道我得到一个错误在这里...但我怎么能做这种业务规则验证在asp.net mvc

+0

有没有答案呢?奥利弗,什么适合你? – 2012-02-28 14:43:53

我只想出如何做到这一点在类级别,但不是在属性级别。如果您创建了MVC应用程序,则帐户模型将显示下面所示的方法。

类别:

[PropertiesMustMatch("Password", 
      "ConfirmPassword", ErrorMessage = 
      "Password and confirmation password 
      do not match.")] 
       public class RegisterModel 
       { 

        [Required(ErrorMessage = "Required")] 
        [DataType(DataType.EmailAddress)] 
        [DisplayName("Your Email")] 
        public string Email { get; set; }    

        [Required(ErrorMessage = "Required")] 
        [ValidatePasswordLength] 
        [DataType(DataType.Password)] 
        [DisplayName("Password")] 
        public string Password { get; set; } 

        [Required(ErrorMessage = "Required")] 
        [DataType(DataType.Password)] 
        [DisplayName("Re-enter password")] 
        public string ConfirmPassword { get; set; }     
       } 

验证方法:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)] 
    public sealed class PropertiesMustMatchAttribute : ValidationAttribute 
    { 
     private const string _defaultErrorMessage = "'{0}' and '{1}' do not match."; 

     private readonly object _typeId = new object(); 

     public PropertiesMustMatchAttribute(string originalProperty, string confirmProperty) 
      : base(_defaultErrorMessage) 
     { 
      OriginalProperty = originalProperty; 
      ConfirmProperty = confirmProperty; 
     } 

     public string ConfirmProperty 
     { 
      get; 
      private set; 
     } 

     public string OriginalProperty 
     { 
      get; 
      private set; 
     } 

     public override object TypeId 
     { 
      get 
      { 
       return _typeId; 
      } 
     } 

     public override string FormatErrorMessage(string name) 
     { 
      return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString, 
       OriginalProperty, ConfirmProperty); 
     } 

     public override bool IsValid(object value) 
     { 
      PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value); 
      object originalValue = properties.Find(OriginalProperty, true /* ignoreCase */).GetValue(value); 
      object confirmValue = properties.Find(ConfirmProperty, true /* ignoreCase */).GetValue(value); 
      return Object.Equals(originalValue, confirmValue); 
     } 
} 
+0

您是否创建了该课程?或者你觉得它在某个地方?密码不匹配时不显示错误。我肯定错过了什么。 呃没关系,它带有MVC – 2010-06-05 04:46:13

+0

它是基础MVC应用程序的一部分。它将错误添加到_form,而不是添加到特定的实体。 – scottrakes 2010-06-07 20:21:25

属性

public class CompareValidatorAttribute : ValidationAttribute, IInstanceValidationAttribute 
{ 
    public CompareValidatorAttribute(string prefix, string propertyName) { 
     Check.CheckNullArgument("propertyName", propertyName); 

     this.propertyName = propertyName; 
     this.prefix = prefix; 
    } 

    string propertyName, prefix; 

    public string PropertyName 
    { 
     get { return propertyName; } 
    } 

    public string Prefix 
    { 
     get { return prefix; } 
    } 

    #region IInstanceValidationAttribute Members 

    public bool IsValid(object instance, object value) 
    { 
     var property = instance.GetType().GetProperty(propertyName); 

     var targetValue = property.GetValue(instance, null); 
     if ((targetValue == null && value == null) || (targetValue != null && targetValue.Equals(value))) 
      return true; 

     return false; 
    } 

    #endregion 

    public override bool IsValid(object value) 
    { 
     throw new NotImplementedException(); 
    } 
} 

接口

public interface IInstanceValidationAttribute 
{ 
    bool IsValid(object instance, object value); 
} 

的验证

public class CompareValidator : DataAnnotationsModelValidator<CompareValidatorAttribute> 
{ 
    public CompareValidator(ModelMetadata metadata, ControllerContext context, CompareValidatorAttribute attribute) 
     : base(metadata, context, attribute) 
    { 
    } 

    public override IEnumerable<ModelValidationResult> Validate(object container) 
    { 
     if (!(Attribute as IInstanceValidationAttribute).IsValid(container, Metadata.Model)) 
      yield return (new ModelValidationResult 
      { 
       MemberName = Metadata.PropertyName, 
       Message = Attribute.ErrorMessage 
      }); 
    } 

    public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() 
    { 
     var rule = new ModelClientValidationRule() { ErrorMessage = Attribute.ErrorMessage, ValidationType = "equalTo" }; 
     rule.ValidationParameters.Add("equalTo", "#" + (!string.IsNullOrEmpty(Attribute.Prefix) ? Attribute.Prefix + "_" : string.Empty)+ Attribute.PropertyName); 

     return new[] { rule }; 
    } 
} 

注册吧:

DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(CompareValidatorAttribute), typeof(CompareValidator)); 
+0

+1这非常有用! – Robert 2011-01-11 20:27:28

感谢您的信息。当我想要将验证消息绑定到一个属性时,我被留下了头。如果切换线路

[AttributeUsage(AttributeTargets.Class)] 

到...

[AttributeUsage(AttributeTargets.Property)] 

您可以将上述特定属性的比较。谢谢(你的)信息!由于我的客户端仍在3.5 sp1上运行,所以提供了很多帮助。 悲伤的脸

  1. 日期

实体:

[MetadataType(typeof(MyEntity_Validation))] 
public partial class MyEntity 
{ 
} 
public class MyEntity_Validation 
{ 
    [Required(ErrorMessage="'Date from' is required")] 
    public DateTime DateFrom { get; set; } 

    [CompareDatesValidatorAttribute("DateFrom")] 
    public DateTime DateTo { get; set; } 
} 

属性:

public sealed class CompareDatesValidatorAttribute : ValidationAttribute 
{ 
    private string _dateToCompare; 
    private const string _errorMessage = "'{0}' must be greater or equal'{1}'"; 

    public CompareDatesValidatorAttribute(string dateToCompare) 
     : base(_errorMessage) 
    { 
     _dateToCompare = dateToCompare; 
    } 

    public override string FormatErrorMessage(string name) 
    { 
     return string.Format(_errorMessage, name, _dateToCompare); 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var dateToCompare = validationContext.ObjectType.GetProperty(_dateToCompare); 
     var dateToCompareValue = dateToCompare.GetValue(validationContext.ObjectInstance, null); 
     if (dateToCompareValue != null && value != null && (DateTime)value < (DateTime)dateToCompareValue) 
     { 
      return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); 
     } 
     return null; 
    } 
} 

2。密码

实体:

public string Password { get; set; } 

    [Compare("Password", ErrorMessage = "ConfirmPassword must match Password")] 
    public string ConfirmPassword { get; set; } 

我希望它能帮助

+0

不错和简短的例子。不需要jQuery的$ .validator。 – Misi 2014-11-05 13:03:57

这是一个迟到的回答,但我想分享给别人outhere。以下是我已经做到了让一切都用不显眼的客户端验证验证:

  1. 创建一个属性类:

    public class DateCompareValidationAttribute : ValidationAttribute, IClientValidatable 
    { 
    
        public enum CompareType 
        { 
         GreatherThen, 
         GreatherThenOrEqualTo, 
         EqualTo, 
         LessThenOrEqualTo, 
         LessThen 
        } 
    
    
    
    
        private CompareType _compareType; 
        private DateTime _fromDate; 
        private DateTime _toDate; 
    
        private string _propertyNameToCompare; 
    
        public DateCompareValidationAttribute(CompareType compareType, string message, string compareWith = "") 
    { 
        _compareType = compareType; 
        _propertyNameToCompare = compareWith; 
        ErrorMessage = message; 
    } 
    
    
    #region IClientValidatable Members 
    /// <summary> 
    /// Generates client validation rules 
    /// </summary> 
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
        ValidateAndGetCompareToProperty(metadata.ContainerType); 
        var rule = new ModelClientValidationRule(); 
    
        rule.ErrorMessage = ErrorMessage; 
        rule.ValidationParameters.Add("comparetodate", _propertyNameToCompare); 
        rule.ValidationParameters.Add("comparetype", _compareType); 
        rule.ValidationType = "compare"; 
    
        yield return rule; 
    } 
    
    #endregion 
    
    
    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
        // Have to override IsValid method. If you have any logic for server site validation, put it here. 
        return ValidationResult.Success; 
    
    } 
    
    /// <summary> 
    /// verifies that the compare-to property exists and of the right types and returnes this property 
    /// </summary> 
    /// <param name="containerType">Type of the container object</param> 
    /// <returns></returns> 
    private PropertyInfo ValidateAndGetCompareToProperty(Type containerType) 
    { 
        var compareToProperty = containerType.GetProperty(_propertyNameToCompare); 
        if (compareToProperty == null) 
        { 
         string msg = string.Format("Invalid design time usage of {0}. Property {1} is not found in the {2}", this.GetType().FullName, _propertyNameToCompare, containerType.FullName); 
         throw new ArgumentException(msg); 
        } 
        if (compareToProperty.PropertyType != typeof(DateTime) && compareToProperty.PropertyType != typeof(DateTime?)) 
        { 
         string msg = string.Format("Invalid design time usage of {0}. The type of property {1} of the {2} is not DateType", this.GetType().FullName, _propertyNameToCompare, containerType.FullName); 
         throw new ArgumentException(msg); 
        } 
    
        return compareToProperty; 
    } 
    } 
    

    注意:如果你想验证的时间长度,再添参数到constractor和改变枚举为这种特定类型的comparsion

  2. 的添加的属性的字段作为folows:
    [DateCompareValidation(DateCompareValidationAttribute.CompareType.GreatherThenOrEqualTo, "This Date must be on or after another date", compareWith: "AnotherDate")]

  3. 请记下您生成的html如何更改。它应该包含验证消息,比较日期的字段名称等。生成的参数将以“data-val-compare”开头。当您在GetClientValidationRules方法中设置ValidationType =“compare”时,您定义了此“比较”。

  4. 现在你需要匹配的javascript代码:添加一个验证适配器和验证方法。我在这里使用了一致的方法,但你不必这样做。我建议将这些代码放在一个单独的JavaScript文件中,以便将此文件与您的属性类一起变为控件并可以在任何地方使用。

$ .validator.unobtrusive.adapters.add( '比较', [ 'comparetodate', 'comparetype'], 功能(选项){ options.rules [ '比较' ] = options.params; options.messages ['compare'] = options.message; } );

$.validator.addMethod("compare", function (value, element, parameters) { 
    // value is the actuall value entered 
    // element is the field itself, that contain the the value (in case the value is not enough) 

    var errMsg = ""; 
    // validate parameters to make sure everyting the usage is right 
    if (parameters.comparetodate == undefined) { 
     errMsg = "Compare validation cannot be executed: comparetodate parameter not found"; 
     alert(errMsg); 
     return false; 
    } 
    if (parameters.comparetype == undefined) { 
     errMsg = "Compare validation cannot be executed: comparetype parameter not found"; 
     alert(errMsg); 
     return false; 
    } 


    var compareToDateElement = $('#' + parameters.comparetodate).get(); 
    if (compareToDateElement.length == 0) { 
     errMsg = "Compare validation cannot be executed: Element to compare " + parameters.comparetodate + " not found"; 
     alert(errMsg); 
     return false; 
    } 
    if (compareToDateElement.length > 1) { 
     errMsg = "Compare validation cannot be executed: more then one Element to compare with id " + parameters.comparetodate + " found"; 
     alert(errMsg); 
     return false; 
    } 
    //debugger; 

    if (value && !isNaN(Date.parse(value))) { 
     //validate only the value contains a valid date. For invalid dates and blanks non-custom validation should be used  
     //get date to compare 
     var compareToDateValue = $('#' + parameters.comparetodate).val(); 
     if (compareToDateValue && !isNaN(Date.parse(compareToDateValue))) { 
      //if date to compare is not a valid date, don't validate this 
      switch (parameters.comparetype) { 
       case 'GreatherThen': 
        return new Date(value) > new Date(compareToDateValue); 
       case 'GreatherThenOrEqualTo': 
        return new Date(value) >= new Date(compareToDateValue); 
       case 'EqualTo': 
        return new Date(value) == new Date(compareToDateValue); 
       case 'LessThenOrEqualTo': 
        return new Date(value) <= new Date(compareToDateValue); 
       case 'LessThen': 
        return new Date(value) < new Date(compareToDateValue); 
       default: 
        { 
         errMsg = "Compare validation cannot be executed: '" + parameters.comparetype + "' is invalid for comparetype parameter"; 
         alert(errMsg); 
         return false; 
        } 
      } 
      return true; 
     } 
     else 
      return true; 

    } 
    else 
     return true; 
}); 

这需要只有客户端不显眼的验证服务。如果您需要服务器端,您必须在重写isValid方法时拥有一些逻辑。此外,您可以使用反射来使用显示属性等生成错误消息,并使消息参数为可选。