6

Допустим, у меня есть StartDate и EndDate и я Wnt, чтобы проверить, если EndDate не более чем 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 ("StartDate", "EndDate", ErrorMessage = "Сделка может быть только 3 месяца долго!")]

Я знаю, что я получаю ошибка здесь ... но как я могу сделать такую ​​проверку бизнес-правил в asp.net mvc

+0

есть ли ответ на этот вопрос? oliver, что для вас работает? –

ответ

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

Вы создали этот класс? Или вы нашли его где-нибудь? Когда пароли не совпадают, это не отображает ошибку. Я должен что-то упустить. Uhh nevermind, он поставляется с MVC –

+0

Это часть базового приложения MVC. Он добавляет ошибку к _form, а не к определенному объекту. – scottrakes

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

2

Спасибо за информацию. Я остался царапать голову, когда хотел привязать сообщение проверки к свойству. При переключении линии

[AttributeUsage(AttributeTargets.Class)] 

к ...

[AttributeUsage(AttributeTargets.Property)] 

вы можете переместить сравнения выше определенного свойства. Спасибо за информацию! Большая помощь, так как мой клиент все еще работает на 3.5 sp1. грустное лицо

4
  1. Даты

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

Атрибут:

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.Пароль

Entity:

public string Password { get; set; } 

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

Я надеюсь, что это помогает

+0

Красивые и короткие примеры. Нет необходимости в $ .validator jQuery. – Misi

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 и изменения перечислителя для этого конкретного типа сравнительную

  2. Добавьте атрибуты в поле folows:
    [DateCompareValidation(DateCompareValidationAttribute.CompareType.GreatherThenOrEqualTo, "This Date must be on or after another date", compareWith: "AnotherDate")]

  3. Обратите внимание, что сгенерированный html изменен. Он должен включать ваше подтверждение, имя поля для даты сравнения и т. Д. Сгенерированные парты начинаются с «data-val-compare». Вы определили это «сравнение», когда вы установите ValidationType = «compare» в методе GetClientValidationRules.

  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. Кроме того, вы можете использовать Reflection для генерации сообщения об ошибке с использованием атрибутов отображения и т. Д. И сделать аргумент сообщения опционным.

Смежные вопросы