6

Können sagen, ich habe ein Startdatum und ein Enddatum und ich wnt zu überprüfen, ob die EndDate nicht mehr als 3 Monate außer dem Datum StartDaten vergleichen DataAnnotations Validierung 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); 
    } 
} 

ist, und ich möchte dies in meine Validierung

[DateCompare ("Startdatum", "EndDate" Errormessage = "Der Deal nur 3 Monate lang sein kann!")] zu implementieren

ich weiß, dass ich eine bekommen Fehler hier ... aber wie kann ich diese Art von Geschäftsregel Validierung in asp.net mvc

+0

Gibt es dafür eine Antwort? oliver, was funktioniert für dich? –

Antwort

4

Ich habe nur herausgefunden, wie dies auf der Klassenebene, aber nicht auf der Eigenschaftsebene zu tun. Wenn Sie eine MVC-Anwendung erstellen, zeigt das Account-Modell den unten dargestellten Ansatz.

Klasse:

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

Validierung Methode:

[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

Haben Sie diese Klasse erstellt? Oder hast du es irgendwo gefunden? Wenn die Passwörter nicht übereinstimmen, wird der Fehler nicht angezeigt. Ich muss etwas verpassen. Uhh vergiss es kommt mit MVC –

+0

Es ist Teil der Basis MVC-Anwendung. Es fügt den Fehler zu _form, nicht zu einer bestimmten Entität hinzu. – scottrakes

2

Das Attribut

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

Die Schnittstelle

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

Der Validator

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

Registrieren Sie:

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

+1 Sehr nützlich, um dies zu haben! – Robert

2

Danke für die Info. Ich musste mir den Kopf kratzen, als ich die Validierungsnachricht an eine Eigenschaft binden wollte. Wenn Sie die Zeile

[AttributeUsage(AttributeTargets.Class)] 

zu wechseln ...

[AttributeUsage(AttributeTargets.Property)] 

können Sie die oberhalb einer bestimmten Eigenschaft vergleichen bewegen. Danke für die Information! Viel Hilfe, da mein Client immer noch auf 3.5 SP1 läuft. sad face

4
  1. Daten

Entity:

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

Attribut:

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.Kennwort

Entity:

public string Password { get; set; } 

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

Ich hoffe, es hilft

+0

Schöne und kurze Beispiele. Keine Notwendigkeit für $ $ Validator jQuery. – Misi

8

Es ist eine späte Antwort, aber ich wollte es teilen für andere Outhere. Hier ist, wie ich habe es getan, so dass alles validiert mit unaufdringlich-Client-Validierung:

  1. Eine Attributklasse:

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

    Hinweis: Wenn Sie längere Zeit überprüfen möchten, fügen Sie ein anderes Parameter an die constractor und Änderung Enumerator für diese spezielle Art von comparsion

  2. die Attribute auf das Feld als folows hinzufügen:
    [DateCompareValidation(DateCompareValidationAttribute.CompareType.GreatherThenOrEqualTo, "This Date must be on or after another date", compareWith: "AnotherDate")]

  3. Notieren Sie sich, wie Ihr generierter HTML-Code geändert wird. Es sollte Ihre Validierungsnachricht, den Feldnamen für das Vergleichsdatum usw. enthalten. Die generierten Parameter würden mit "Daten-Val-Compare" beginnen. Sie haben dieses "vergleichen" definiert, wenn Sie in der GetClientValidationRules-Methode ValidationType = "compare" festlegen.

  4. Jetzt benötigen Sie passender Javascript-Code: um einen Validierungsadapter und eine Validierungsmethode hinzuzufügen. Ich habe hier eine anonyme Methode benutzt, aber das musst du nicht. Ich empfehle, diesen Code in eine separate Javascript-Datei zu platzieren, damit diese Datei zusammen mit Ihrer Attributklasse wie ein Steuerelement wird und überall verwendet werden kann.

.validator.unobtrusive.adapters.add $ ( 'vergleichen', [ 'comparetodate', 'comparetype'], Funktion (Optionen) { options.rules [ 'vergleichen' ] = 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; 
}); 

Diese kümmert sich nur von clientseitigen unaufdringlich Validierung. Wenn Sie Server-Seite benötigen, müssten Sie eine Logik in der Überschreibung der isValid-Methode haben. Außerdem können Sie Reflection verwenden, um mithilfe von Anzeigeattributen usw. eine Fehlermeldung zu generieren und das Nachrichtenargument optional zu machen.