可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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; }