2013-09-02 4 views
23

Как наилучшим образом проверить модель в MVC.Net, где я хочу принять минимум/максимум.MVC Проверка ниже/выше, чем другое значение

Отдельные минимальные/максимальные значения для поля. Но отдельные поля для пользователя указывают минимальный/максимальный.

public class FinanceModel{ 
    public int MinimumCost {get;set;} 
    public int MaximumCost {get;set;} 
} 

Поэтому мне нужно обеспечить, чтобы MinimumCost всегда был меньше максимальной.

ответ

21

Вы можете использовать специальный атрибут проверки, вот мой пример с датами. Но вы можете использовать его и с ints.

Во-первых, здесь модель:

public DateTime Beggining { get; set; } 

    [IsDateAfterAttribute("Beggining", true, ErrorMessageResourceType = typeof(LocalizationHelper), ErrorMessageResourceName = "PeriodErrorMessage")] 
    public DateTime End { get; set; } 

А вот сам атрибут:

public sealed class IsDateAfterAttribute : ValidationAttribute, IClientValidatable 
{ 
    private readonly string testedPropertyName; 
    private readonly bool allowEqualDates; 

    public IsDateAfterAttribute(string testedPropertyName, bool allowEqualDates = false) 
    { 
     this.testedPropertyName = testedPropertyName; 
     this.allowEqualDates = allowEqualDates; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     var propertyTestedInfo = validationContext.ObjectType.GetProperty(this.testedPropertyName); 
     if (propertyTestedInfo == null) 
     { 
      return new ValidationResult(string.Format("unknown property {0}", this.testedPropertyName)); 
     } 

     var propertyTestedValue = propertyTestedInfo.GetValue(validationContext.ObjectInstance, null); 

     if (value == null || !(value is DateTime)) 
     { 
      return ValidationResult.Success; 
     } 

     if (propertyTestedValue == null || !(propertyTestedValue is DateTime)) 
     { 
      return ValidationResult.Success; 
     } 

     // Compare values 
     if ((DateTime)value >= (DateTime)propertyTestedValue) 
     { 
      if (this.allowEqualDates && value == propertyTestedValue) 
      { 
       return ValidationResult.Success; 
      } 
      else if ((DateTime)value > (DateTime)propertyTestedValue) 
      { 
       return ValidationResult.Success; 
      } 
     } 

     return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     var rule = new ModelClientValidationRule 
     { 
      ErrorMessage = this.ErrorMessageString, 
      ValidationType = "isdateafter" 
     }; 
     rule.ValidationParameters["propertytested"] = this.testedPropertyName; 
     rule.ValidationParameters["allowequaldates"] = this.allowEqualDates; 
     yield return rule; 
    } 
+7

Вам нужно выполнить этот пример с клиентской стороны проверки: 'jQuery.validator.addMethod ('isdateafter', функция (значение, элемент, PARAMS) { if (!/Invalid | NaN/.test (новая дата (значение))) { return new Date (value)> new Date(); } return isNaN (значение) && isNaN ($ (params) .val()) || (parseFloat (значение)> parseFloat ($ (params) .val())); }, ''); jQuery.validator.unobtrusive.adapters.add ('isdateafter', {}, function (options) { options.rules ['isdateafter'] = true; options.messages ['isdateafter'] = options.message; }); ' – LoBo

+0

Кажется, что ошибка связана с линией' if (this.allowEqualDates && value == propertyTestedValue) '. Это работает: 'if (this.allowEqualDates && value.Equals (propertyTestedValue))' или даже это 'if (this.allowEqualDates && (DateTime) значение == (DateTime) propertyTestedValue)'. – publicgk

26

Существует пакет NuGet называется Foolproof, который предоставляет эти аннотации для вас. Тем не менее - писать пользовательский атрибут - довольно простая и хорошая практика.

Использование Защищенное будет выглядеть так:

public class FinanceModel{ 
    public int MinimumCost {get;set;} 

    [GreaterThan("MinimumCost")] 
    public int MaximumCost {get;set;} 
} 
+1

Принимает пользовательский валидатор как инструмент обучения. Спасибо за ссылку на Foolproof. В любом случае сохранит его под рукой. –

+0

Foolproof, похоже, не принимает пользовательские сообщения об ошибках. –

+2

Пользовательские сообщения об ошибках указываются как таковые [GreaterThan («MinimumCost»), ErrorMessage = «Должна быть больше минимальной стоимости»] –

-7

Почему вы не использовали Range Validator. Синтаксис:

[Range(typeof(int), "0", "100", ErrorMessage = "{0} can only be between {1} and {2}")] 
    public int Percentage { get; set; } 
+2

Если вы посмотрите на мой оригинальный вопрос или существующие ответы, вы увидите, что я пытаюсь проверить, где пользователь может выбрать верхнюю/нижнюю границу. Не тогда, когда они должны ввести значение между существующими высокими/низкими значениями. –

6

Для проверки на стороне клиента, используя allowEqualDates и параметры propertyTested (дополнение к Boranas ответ выше, но слишком долго для комментариев):

// definition for the isdateafter validation rule 
if ($.validator && $.validator.unobtrusive) { 
    $.validator.addMethod('isdateafter', function (value, element, params) { 
     value = Date.parse(value); 
     var otherDate = Date.parse($(params.compareTo).val()); 
     if (isNaN(value) || isNaN(otherDate)) 
      return true; 
     return value > otherDate || (value == otherDate && params.allowEqualDates); 
    }); 
    $.validator.unobtrusive.adapters.add('isdateafter', ['propertytested', 'allowequaldates'], function (options) { 
     options.rules['isdateafter'] = { 
      'allowEqualDates': options.params['allowequaldates'], 
      'compareTo': '#' + options.params['propertytested'] 
     }; 
     options.messages['isdateafter'] = options.message; 
    }); 
} 

Дополнительная информация: unobtrusive validation, jquery validation

1

В VB для целых чисел:

МОДЕЛЬ

<UtilController.IsIntegerGreatherOrEqualThan("PropertyNameNumberBegins", "PeriodErrorMessage")> 
     Public Property PropertyNameNumberEnds As Nullable(Of Integer) 

ВАЛИДАЦИЯ

Public Class IsIntegerGreatherOrEqualThan 
     Inherits ValidationAttribute 

     Private otherPropertyName As String 
     Private errorMessage As String 

     Public Sub New(ByVal otherPropertyName As String, ByVal errorMessage As String) 
      Me.otherPropertyName = otherPropertyName 
      Me.errorMessage = errorMessage 
     End Sub 

     Protected Overrides Function IsValid(thisPropertyValue As Object, validationContext As ValidationContext) As ValidationResult 

      Dim otherPropertyTestedInfo = validationContext.ObjectType.GetProperty(Me.otherPropertyName) 

      If (otherPropertyTestedInfo Is Nothing) Then 
       Return New ValidationResult(String.Format("unknown property {0}", Me.otherPropertyName)) 
      End If 

      Dim otherPropertyTestedValue = otherPropertyTestedInfo.GetValue(validationContext.ObjectInstance, Nothing) 

      If (thisPropertyValue Is Nothing) Then 
       Return ValidationResult.Success 
      End If 

      '' Compare values 
      If (CType(thisPropertyValue, Integer) >= CType(otherPropertyTestedValue, Integer)) Then 
       Return ValidationResult.Success 
      End If 

      '' Wrong 
      Return New ValidationResult(errorMessage) 
     End Function 
    End Class 
+0

Я удалил «FormatErrorMessage» из кода, поскольку он добавлял «« Поле »+ {errorMessage} + 'недействительно». Я делал проверку даты, поэтому я заменил Integer на Date. Отлично работал и спасал мне время. Спасибо. – PHBeagle

+0

Так errorMessage отображал неправильное сообщение ?, когда я его использовал, я не обращал на это внимания. – Dani

+0

Не совсем неправильно, просто дополнительная формулировка. Используя «Return new ValidationResult (errorMessage)», это было хорошо. – PHBeagle

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