MVC Validation Lower/Higher than other value

匿名 (未验证) 提交于 2019-12-03 02:38:01

问题:

How is the best way to validate a model in MVC.Net where I want to accept a minimum/maximum.

Not individual min/max values for a field. But separate fields for a user to specify a minimum/maximum.

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

So I need to ensure that MinimumCost is always less than Maximum cost.

回答1:

You can use a custom validation attribute here is my example with dates. But you can use it with ints too.

First, here is the model :

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

And here is the attribute itself :

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


回答2:

There is a NuGet package called Foolproof which provides these annotations for you. That said - writing a custom attribute is both pretty easy and good practice.

Using Foolproof would look like:

public class FinanceModel{    public int MinimumCost {get;set;}     [GreaterThan("MinimumCost")]    public int MaximumCost {get;set;} } 


回答3:

For client side validation using the allowEqualDates and propertyTested parameters (complement to Boranas answer above but too long for comment):

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

More information: unobtrusive validation, jquery validation



回答4:

In VB for integers:

MODEL

         Public Property PropertyNameNumberEnds As Nullable(Of Integer) 

VALIDATION

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 


回答5:

Why you are not used Range Validator. Syntax:

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!