ASP .NET MVC 3 Data Annotations GreaterThan LowerThan for DateTime and int

后端 未结 5 2122
执念已碎
执念已碎 2021-02-13 10:19

I would like to know what is the easiest way to have a \"Greater Than\" & \"Lower Than\" validation on a ASP.NET MVC 3 form?

I use unobtrusive JavaScript for client

相关标签:
5条回答
  • 2021-02-13 10:29

    You can use the DateGreaterThanEqual attribute in your model. Here is a snippet of code that I used to validate two fields in my form.

    [DataType(DataType.Date)]
    [DisplayName("From Date")]
    public DateTime? StartDate { get; set; }
    
    [DataType(DataType.Date)]
    [DisplayName("To Date")]
    [DateGreaterThanEqual("StartDate")]
    public DateTime? EndDate { get; set; }
    
    0 讨论(0)
  • 2021-02-13 10:31

    Take a look at the answer of this thread,

    There is a lib called MVC.ValidationToolkit. Though I'm not sure whether it works in case of DateTime fields.

    0 讨论(0)
  • 2021-02-13 10:32

    You can simply do this with custom validation.

    [AttributeUsage(AttributeTargets.Property, AllowMultiple=true)]
        public class DateGreaterThanAttribute : ValidationAttribute
        {
            string otherPropertyName;
    
            public DateGreaterThanAttribute(string otherPropertyName, string errorMessage)
                : base(errorMessage)
            {
                this.otherPropertyName = otherPropertyName;
            }
    
            protected override ValidationResult IsValid(object value, ValidationContext validationContext)
            {
                ValidationResult validationResult = ValidationResult.Success;
                try
                {
                    // Using reflection we can get a reference to the other date property, in this example the project start date
                    var otherPropertyInfo = validationContext.ObjectType.GetProperty(this.otherPropertyName);
                    // Let's check that otherProperty is of type DateTime as we expect it to be
                    if (otherPropertyInfo.PropertyType.Equals(new DateTime().GetType()))
                    {
                        DateTime toValidate = (DateTime)value;
                        DateTime referenceProperty = (DateTime)otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
                        // if the end date is lower than the start date, than the validationResult will be set to false and return
                        // a properly formatted error message
                        if (toValidate.CompareTo(referenceProperty) < 1)
                        {
                            validationResult = new ValidationResult(ErrorMessageString);
                        }
                    }
                    else
                    {
                        validationResult = new ValidationResult("An error occurred while validating the property. OtherProperty is not of type DateTime");
                    }
                }
                catch (Exception ex)
                {
                    // Do stuff, i.e. log the exception
                    // Let it go through the upper levels, something bad happened
                    throw ex;
                }
    
                return validationResult;
            }
    }
    

    and use it in model like

     [DisplayName("Start date")]
        [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]        
        public DateTime StartDate { get; set; }
    
        [DisplayName("Estimated end date")]
        [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
        [DateGreaterThan("StartDate", "End Date end date must not exceed start date")]
        public DateTime EndDate { get; set; }
    

    This works well with server side validation.For client side validaion you can write the method like GetClientValidationRules like

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
            {
                //string errorMessage = this.FormatErrorMessage(metadata.DisplayName);
                string errorMessage = ErrorMessageString;
    
                // The value we set here are needed by the jQuery adapter
                ModelClientValidationRule dateGreaterThanRule = new ModelClientValidationRule();
                dateGreaterThanRule.ErrorMessage = errorMessage;
                dateGreaterThanRule.ValidationType = "dategreaterthan"; // This is the name the jQuery adapter will use
                //"otherpropertyname" is the name of the jQuery parameter for the adapter, must be LOWERCASE!
                dateGreaterThanRule.ValidationParameters.Add("otherpropertyname", otherPropertyName);
    
                yield return dateGreaterThanRule;
            }
    

    Now simply in view

    $.validator.addMethod("dategreaterthan", function (value, element, params) {
    
        return Date.parse(value) > Date.parse($(params).val());
    });
    $.validator.unobtrusive.adapters.add("dategreaterthan", ["otherpropertyname"], function (options) {
        options.rules["dategreaterthan"] = "#" + options.params.otherpropertyname;
        options.messages["dategreaterthan"] = options.message;
    });
    

    You can find more details in this link

    0 讨论(0)
  • 2021-02-13 10:44

    Could look at the dataannotationsextensions it does Min/Max for int

    Also have a look at a foolproof validation it inlcudes GreaterThan comparison for numeric/datetime etc

    0 讨论(0)
  • 2021-02-13 10:48

    I don't know if writing your own validator class is the "easiest" way, but that's what I did.

    Usage:

    <DataType(DataType.Date)>
    Public Property StartDate() As DateTime
    
    
    <DataType(DataType.Date)>
    <DateGreaterThanEqual("StartDate", "end date must be after start date")>
    Public Property EndDate() As DateTime
    

    Class:

    <AttributeUsage(AttributeTargets.Field Or AttributeTargets.Property, AllowMultiple:=False, Inherited:=False)>
    Public Class DateGreaterThanEqualAttribute
        Inherits ValidationAttribute
    
        Public Sub New(ByVal compareDate As String, ByVal errorMessage As String)
            MyBase.New(errorMessage)
            _compareDate = compareDate
        End Sub
        Public ReadOnly Property CompareDate() As String
            Get
                Return _compareDate
            End Get
        End Property
        Private ReadOnly _compareDate As String
    
        Protected Overrides Function IsValid(ByVal value As Object, ByVal context As ValidationContext) As ValidationResult
            If value Is Nothing Then
                ' no need to do or check anything
                Return Nothing
            End If
            ' find the other property we need to compare with using reflection
            Dim compareToValue = Nothing
            Dim propAsDate As Date
            Try
                compareToValue = context.ObjectType.GetProperty(CompareDate).GetValue(context.ObjectInstance, Nothing).ToString
                propAsDate = CDate(compareToValue)
            Catch
                Try
                    Dim dp As String = CompareDate.Substring(CompareDate.LastIndexOf(".") + 1)
                    compareToValue = context.ObjectType.GetProperty(dp).GetValue(context.ObjectInstance, Nothing).ToString
                    propAsDate = CDate(compareToValue)
                Catch
                    compareToValue = Nothing
                End Try
            End Try
    
            If compareToValue Is Nothing Then
                'date is not supplied or not valid
                Return Nothing
            End If
    
            If value < compareToValue Then
                Return New ValidationResult(FormatErrorMessage(context.DisplayName))
            End If
    
            Return Nothing
        End Function
    
    End Class
    
    0 讨论(0)
提交回复
热议问题