Why does ASP.Net MVC Range Attribute use a type?

I'm just wondering why the range check attribute can take a type and two strings as parameters? Is this for checking strings against Enum or something similar?

Also I am trying to find an easy way to check the 3-character string that should be present in the enumeration, any sugestions?

Thanks, Alex.

+6
c # asp.net-mvc asp.net-mvc-3 data-annotations
source share
6 answers

I found a Range ctor that you called fish. I could not help but investigate. (So ​​I wrote this answer, like a journal, researching.)

From MSDN

public RangeAttribute( Type type, string minimum, string maximum ) 

Note. MSDN says Type must be IComparable . And, their approximate description speaks of his comparison of the date when he is not!

So, since I got my asp.net mvc3 application, I tried this with a date date like this:

 [Range(typeof(DateTime),"1-Jan-1910","1-Jan-2060")] 

When I run this, this happens:

enter image description here

Please note that although I set the minimum and maximum values ​​with a dotted line and not the time, it gives a different format, so its probably TryParsing string correctly? But I'm sure it cannot be ICompare two on the client side !? Now no matter what date I enter, it still shows an error. (The date is entered as March 11, 20 (20, as in 2020).)

I tried char (below) since it is also IComparable . Same. In fact, it is not possible to perform range comparison on the client side .

 [Range(typeof(char), "a", "g")] 

But wait ...

Just remove the customer check! I removed links to jQuery validation and unobtrusive validation and viola! It works great. These are messages , then correctly show errors when the values ​​(Both char and Date) are NOT in the specified range.

Note. Perhaps someone can expand this solution by disabling ONLY certain fields to validate the client.

Hope this was helpful.

+15
source share

I also noticed that jQuery Validation does not work very well with ASP MVC Range-validator (it seems that the jQuery Validation plugin requires the range values ​​to be numbers).

A simple solution is to disable validation for specific fields. Server side validator will work anyway.

The following example will remove the "range" rule from all input fields with the "date" class:

 $('input.date').each(function() { $(this).rules('remove', 'range'); }); 
+4
source share

I ended up creating a custom DateRangeAttribute attribute, as described here . You do not get client-side validation, but you can customize it according to your needs and not enter javascript. Here is the code and how to use it:

 public class Person { [Required] public string FirstName { get; set; } [DataType(DataType.Date)] [DateRange("2010/12/01", "2010/12/16")] public DateTime DateOfBirth { get; set; } } 

DateRange is simple:

 public class DateRangeAttribute : ValidationAttribute { private const string DateFormat = "yyyy/MM/dd"; private const string DefaultErrorMessage = "'{0}' must be a date between {1:d} and {2:d}."; public DateTime MinDate { get; set; } public DateTime MaxDate { get; set; } public DateRangeAttribute(string minDate, string maxDate) : base(DefaultErrorMessage) { MinDate = ParseDate(minDate); MaxDate = ParseDate(maxDate); } public override bool IsValid(object value) { if (value == null || !(value is DateTime)) { return true; } DateTime dateValue = (DateTime)value; return MinDate <= dateValue && dateValue <= MaxDate; } public override string FormatErrorMessage(string name) { return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, MinDate, MaxDate); } private static DateTime ParseDate(string dateValue) { return DateTime.ParseExact(dateValue, DateFormat, CultureInfo.InvariantCulture); } } 
+3
source share

I picked it up quite late too :)

Of course, the CustomValidation attribute was created for these circumstances?

Thus, we do not need to change client-side validation. Plus, it’s beneficial in that it allows us to apply a custom range.

For instance:

 public class Person { [CustomValidation(typeof(Person), "validateDOB")] public DateTime DateOfBirth { get; set; } //field (or property) limits that we could look-up private static DateTime _MinDate = new DateTime(1, 1, 1900); private static DateTime _MaxDate = new DateTime(31, 12, 2999); //this method must be public and static and take a single //parameter: the field to validate public static ValidationResult validateDOB(DateTime dateOfBirth) { string errorMsg = ""; if (dateOfBirth < _MinDate) { errorMsg = "Date too early"; } else if (dateOfBirth > _MaxDate) { errorMsg = "Date too late"; } return errorMsg == "" ? null : new ValidationResult(errorMsg); } } 
+3
source share

You can use the following custom date range setting, which compares the date value with the provided minimum date or the specified dependent properties. It also demonstrates support and integration of client-side validation.

CustomDateRange

 public enum CustomDateRangeType { /// <summary> /// The direct value of property. /// </summary> Value, /// <summary> /// The dependent property. /// </summary> DependentProperty } /// <summary> /// The CustomDateComparAttribute Validator /// </summary> [AttributeUsage(AttributeTargets.All | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] public sealed class CustomDateRangeAttribute : ValidationAttribute, IClientValidatable { private const string UniversalDatePattern = "yyyy-Md"; /// <summary> /// The min date. /// </summary> private string minDate; /// <summary> /// The max date. /// </summary> private string maxDate; /// <summary> /// The date range type /// </summary> private CustomDateRangeType dateRangeType; /// <summary> /// Initializes a new instance of the <see cref="CustomDateRangeAttribute"/> class. /// </summary> /// <param name="minDate"> /// The min date in <example>yyyy-Md</example> format. Throws FormatException exception if not provided in specified format. /// </param> /// <param name="maxDate"> /// max date in <example>yyyy-Md</example> format. Throws FormatException exception if not provided in specified format. /// </param> public CustomDateRangeAttribute(string minDate, string maxDate) : this(CustomDateRangeType.Value, minDate, maxDate) { } /// <summary> /// Initializes a new instance of the <see cref="CustomDateRangeAttribute" /> class. /// </summary> /// <param name="dateRangeType">Type of the date range.</param> /// <param name="minDate">The minimum date dependent property or value. If value then it should be <example>yyyy-Md</example> format.</param> /// <param name="maxDate">The maximum date property or value. If value then it should be <example>yyyy-Md</example> format.</param> public CustomDateRangeAttribute(CustomDateRangeType dateRangeType, string minDate, string maxDate) { if (dateRangeType == CustomDateRangeType.Value) { if (!IsValidDate(minDate)) { throw new FormatException(string.Format(CultureInfo.InvariantCulture, "Max date should be in {0} format.", UniversalDatePattern)); } if (!IsValidDate(maxDate)) { throw new FormatException(string.Format(CultureInfo.InvariantCulture, "Min date should be in {0} format.", UniversalDatePattern)); } } this.dateRangeType = dateRangeType; this.minDate = minDate; this.maxDate = maxDate; } /// <summary> /// Gets the min date. /// </summary> public string MinDate { get { return this.minDate; } } /// <summary> /// Gets the max date. /// </summary> public string MaxDate { get { return this.maxDate; } } /// <summary> /// Gets the type of the date range. /// </summary> /// <value> /// The type of the date range. /// </value> public CustomDateRangeType DateRangeType { get { return this.dateRangeType; } } /// <summary> /// gets client validation rules /// </summary> /// <param name="metadata"> /// meta data parameter /// </param> /// <param name="context"> /// controller context /// </param> /// <returns> /// client validation rule /// </returns> public IEnumerable<ModelClientValidationRule> GetClientValidationRules( ModelMetadata metadata, ControllerContext context) { if (metadata != null) { return new[] { new ModelClientValidationCustomDateRangeRule( this.ErrorMessageString, this.DateRangeType, this.MinDate, metadata.PropertyName, this.MaxDate) }; } return null; } /// <summary> /// overridden method /// </summary> /// <param name="value"> /// value to be compared /// </param> /// <param name="validationContext"> /// validation context /// </param> /// <returns> /// validation result /// </returns> protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var result = ValidationResult.Success; var errorResult = new ValidationResult(this.ErrorMessageString); if (value == null) { return result; } DateTime dateValue = (DateTime)value; if (this.DateRangeType == CustomDateRangeType.Value) { if (ParseDate(this.MinDate) <= dateValue && dateValue <= ParseDate(this.MaxDate)) { return result; } } else { if (validationContext == null || string.IsNullOrEmpty(this.MinDate) || string.IsNullOrEmpty(this.MaxDate)) { return errorResult; } var minDatePropertyInfo = validationContext.ObjectType.GetProperty(this.MinDate); var maxDatePropertyInfo = validationContext.ObjectType.GetProperty(this.MaxDate); if (minDatePropertyInfo == null || maxDatePropertyInfo == null) { return errorResult; } var minDateValue = Convert.ToDateTime( minDatePropertyInfo.GetValue(validationContext.ObjectInstance, null), CultureInfo.CurrentCulture); var maxDateValue = Convert.ToDateTime(maxDatePropertyInfo.GetValue(validationContext.ObjectInstance, null), CultureInfo.CurrentCulture); if (minDateValue <= dateValue && dateValue <= maxDateValue) { return result; } } return errorResult; } /// <summary> /// The parse date. /// </summary> /// <param name="dateValue"> /// The date value. /// </param> /// <returns> /// The <see cref="DateTime"/>. /// </returns> private static DateTime ParseDate(string dateValue) { return DateTime.ParseExact( dateValue, UniversalDatePattern, CultureInfo.InvariantCulture); } /// <summary> /// The is valid date. /// </summary> /// <param name="dateValue"> /// The date value. /// </param> /// <returns> /// A value indicating whether the provided dateValue is a valid date. /// </returns> private static bool IsValidDate(string dateValue) { DateTime? date = null; var regex = new Regex(@"\d{4}-\d{1,2}-\d{1,2}"); if (regex.IsMatch(dateValue)) { var dateParts = dateValue.Split('-'); if (dateParts.Length == 3) { date = new DateTime( Convert.ToInt32(dateParts[0], CultureInfo.InvariantCulture), Convert.ToInt32(dateParts[1], CultureInfo.InvariantCulture), Convert.ToInt32(dateParts[2], CultureInfo.InvariantCulture)); } } return date != null; } /// <summary> /// ModelClientValidationCustomCompareRule class /// </summary> private class ModelClientValidationCustomDateRangeRule : ModelClientValidationRule { /// <summary> /// Initializes a new instance of the <see cref="ModelClientValidationCustomDateRangeRule"/> class. /// </summary> /// <param name="errorMessage">error message</param> /// <param name="dateRangeType">Type of the date range.</param> /// <param name="minDateProperty">The minimum date property.</param> /// <param name="currentProperty">The current property.</param> /// <param name="maxDateProperty">The maximum date property.</param> public ModelClientValidationCustomDateRangeRule( string errorMessage, CustomDateRangeType dateRangeType, string minDateProperty, string currentProperty, string maxDateProperty) { this.ErrorMessage = errorMessage; this.ValidationType = "customdaterange"; this.ValidationParameters.Add("daterangetypeproperty", dateRangeType.ToString()); this.ValidationParameters.Add("mindateproperty", minDateProperty); this.ValidationParameters.Add("currentproperty", currentProperty); this.ValidationParameters.Add("maxdateproperty", maxDateProperty); } } } 

ClientSide Integration

 (function ($) { jQuery.validator.addMethod('customdaterange', function (value, element, param) { if (value == '' || value == undefined) { return true; } var minValue; var maxValue; if (param.daterangetypeproperty == "DependentProperty") { var minDateValue = $('#' + param.mindateproperty).val(); var maxDateValue = $('#' + param.maxdateproperty).val(); minValue = new Date(minDateValue); maxValue = new Date(maxDateValue); } else { minValue = new Date(param.mindateproperty); maxValue = new Date(param.maxdateproperty); } var currentValue = new Date(value); if (minValue <= currentValue && currentValue <= maxValue) { return true; } return false; }); jQuery.validator.unobtrusive.adapters.add('customdaterange', ['daterangetypeproperty', 'mindateproperty', 'currentproperty', 'maxdateproperty'], function (options) { var params = { daterangetypeproperty: options.params.daterangetypeproperty, mindateproperty: options.params.mindateproperty, currentproperty: options.params.currentproperty, maxdateproperty: options.params.maxdateproperty }; options.rules['customdaterange'] = params; if (options.message) { options.messages['customdaterange'] = options.message; } }); }(jQuery)); 

Demo

Model

 public class DateRangeModel { public DateRangeModel() { this.MinDateDependentProperty = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1); this.MaxDateDependentProperty = DateTime.Today.AddDays(1 - DateTime.Today.Day).AddMonths(1); } [Required] [CustomDateRange("2015-10-01", "2015-10-15", ErrorMessage = "Date value is not in range.")] [DataType(DataType.Date)] public DateTime DateCompareWithMinMaxValue { get; set; } [Required] [CustomDateRange(CustomDateRangeType.DependentProperty, "MinDateDependentProperty", "MaxDateDependentProperty", ErrorMessage = "Date to select value is not in range.")] [DataType(DataType.Date)] public DateTime DateCompareWithMinMaxDependentProperty { get; set; } [Required] [DataType(DataType.Date)] public DateTime MinDateDependentProperty { get; set; } [Required] [DataType(DataType.Date)] public DateTime MaxDateDependentProperty { get; set; } } 

Checked Date Controls

Download the full implementation from here .

+1
source share

Guys! Here is another statement. I found it here: MVC check lower / higher than another value

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

http://foolproof.codeplex.com/

-3
source share

All Articles