MVC Validación inferior / superior a otro valor

¿Cómo es la mejor manera de validar un modelo en MVC.Net donde quiero aceptar un mínimo / máximo?

No valores min / max individuales para un campo. Pero campos separados para que un usuario especifique un mínimo / máximo.

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

Por lo tanto, debo asegurarme de que MinimumCost sea siempre menor que el Costo máximo.

Puede usar un atributo de validación personalizado aquí es mi ejemplo con fechas. Pero puedes usarlo también con Ints.

Primero, aquí está el modelo:

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

Y aquí está el atributo en sí:

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

Hay un paquete NuGet llamado Foolproof que proporciona estas anotaciones por usted. Dicho eso, escribir un atributo personalizado es una práctica bastante fácil y buena.

Usar Foolproof se vería así:

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

Para la validación del lado del cliente utilizando los parámetros allowEqualDates y propertyTested (complemento de la respuesta de Boranas, pero demasiado largo para comentar):

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

Más información: validación discreta , validación jquery

En VB para enteros:

MODELO

  Public Property PropertyNameNumberEnds As Nullable(Of Integer) 

VALIDACIÓN

 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 

Por qué no se usa Range Validator. Sintaxis:

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