6

可以說我有一個起始日期和結束日期的我和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

回答

4

我只想出如何做到這一點在類級別,但不是在屬性級別。如果您創建了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

2

屬性

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

2

感謝您的信息。當我想要將驗證消息綁定到一個屬性時,我被留下了頭。如果切換線路

[AttributeUsage(AttributeTargets.Class)] 

到...

[AttributeUsage(AttributeTargets.Property)] 

您可以將上述特定屬性的比較。謝謝(你的)信息!由於我的客戶端仍在3.5 sp1上運行,所以提供了很多幫助。 悲傷的臉

4
  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

8

這是一個遲到的回答,但我想分享給別人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方法時擁有一些邏輯。此外,您可以使用反射來使用顯示屬性等生成錯誤消息,並使消息參數爲可選。