Проверка MVC ниже/выше, чем другое значение
Как лучше всего проверить модель в MVC.Net, где я хочу принять минимум/максимум.
Не отдельные значения min/max для поля. Но отдельные поля для пользователя указывают минимальный/максимальный.
public class FinanceModel{
public int MinimumCost {get;set;}
public int MaximumCost {get;set;}
}
Поэтому мне нужно убедиться, что MinimumCost всегда меньше максимальной.
Ответы
Ответ 1
Вы можете использовать специальный атрибут проверки, вот мой пример с датами.
Но вы можете использовать его и с 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;
}
Ответ 2
Существует пакет NuGet под названием Foolproof, который предоставляет эти аннотации для вас. Тем не менее, создание пользовательского атрибута - довольно простая и хорошая практика.
Использование Foolproof будет выглядеть так:
public class FinanceModel{
public int MinimumCost {get;set;}
[GreaterThan("MinimumCost")]
public int MaximumCost {get;set;}
}
Ответ 3
Для проверки на стороне клиента с использованием параметров 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;
});
}
Дополнительная информация: ненавязчивая проверка, проверка jquery
Ответ 4
В VB для целых чисел:
MODEL
<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
Ответ 5
Почему вы не используете Range Validator.
Синтаксис:
[Range(typeof(int), "0", "100", ErrorMessage = "{0} can only be between {1} and {2}")]
public int Percentage { get; set; }