在MVC.Net中,如何最好地验证模型,其中我想接受最小/最大值。
不是针对字段的个别min/max值。而是针对用户指定最小/最大值的单独字段。
public class FinanceModel{
public int MinimumCost {get;set;}
public int MaximumCost {get;set;}
}
所以我需要确保MinimumCost始终小于Maximum cost。
在MVC.Net中,如何最好地验证模型,其中我想接受最小/最大值。
不是针对字段的个别min/max值。而是针对用户指定最小/最大值的单独字段。
public class FinanceModel{
public int MinimumCost {get;set;}
public int MaximumCost {get;set;}
}
所以我需要确保MinimumCost始终小于Maximum cost。
有一个名为 Foolproof 的 NuGet 包,可以为您提供这些注释。话虽如此 - 编写自定义属性既简单又是一种很好的实践。
使用 Foolproof 如下:
public class FinanceModel{
public int MinimumCost {get;set;}
[GreaterThan("MinimumCost")]
public int MaximumCost {get;set;}
}
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;
}
jQuery.validator.addMethod('isdateafter', function (value, element, params) {
if (!/Invalid|NaN/.test(new Date(value))) {
return new Date(value) > new Date();
}
return isNaN(value) && isNaN($(params).val()) || (parseFloat(value) > parseFloat($(params).val()));
}, '');
jQuery.validator.unobtrusive.adapters.add('isdateafter', {}, function (options) {
options.rules['isdateafter'] = true;
options.messages['isdateafter'] = options.message;
});
- LoBoif (this.allowEqualDates && value == propertyTestedValue)
这一行存在错误。这个可以正常工作:if (this.allowEqualDates && value.Equals(propertyTestedValue))
,或者甚至是这个:if (this.allowEqualDates && (DateTime)value == (DateTime)propertyTestedValue)
。 - publicgk对于客户端验证,使用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;
});
}
模型
<UtilController.IsIntegerGreatherOrEqualThan("PropertyNameNumberBegins", "PeriodErrorMessage")>
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
为什么你没有使用范围验证器。 语法:
[Range(typeof(int), "0", "100", ErrorMessage = "{0} can only be between {1} and {2}")]
public int Percentage { get; set; }