Question

I am trying to validate two dates on my form, the dates are populated via datetime picker. I wrote custom validator to validate these fields. but the client side validation is not working as expected.

I noticed parseFloat($(params).val()) in client side script is returning null.

Can some one please help?

Custom Attribute: ValidateToDateAttribute

public class ValidateToDateAttribute : ValidationAttribute, IClientValidatable
{
    /// <summary>
    /// Initializes a new instance of the <see cref="ValidateToDateAttribute"/> class.
    /// </summary>
    /// <param name="errorMessageKey">The error message key.</param>
    public ValidateToDateAttribute(string errorMessageKey)
    {
        this.ErrorMessageKey = errorMessageKey;
    }

    /// <summary>
    /// Gets the error message key.
    /// </summary>
    /// <value>
    /// The error message key.
    /// </value>
    public string ErrorMessageKey { get; private set; }

    /// <summary>
    /// When implemented in a class, returns client validation rules for that class.
    /// </summary>
    /// <param name="metadata">The model metadata.</param>
    /// <param name="context">The controller context.</param>
    /// <returns>
    /// The client validation rules for this validator.
    /// </returns>
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var modelClientValidationRule = new ModelClientValidationRule
        {
            ValidationType = "validatetodate",
            ErrorMessage = new ResourceManager(typeof(ValidationErrorMessages)).GetString(this.ErrorMessageKey)
        };

        yield return modelClientValidationRule;
    }

    /// <summary>
    /// Validates the specified value with respect to the current validation attribute.
    /// </summary>
    /// <param name="value">The value to validate.</param>
    /// <param name="validationContext">The context information about the validation operation.</param>
    /// <returns>
    /// An instance of the <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult" /> class.
    /// </returns>
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {
            var viewModel = (TransactionViewModel)validationContext.ObjectInstance;
            if (viewModel.ToDate.CompareTo(viewModel.FromDate) < 0)
            {
                return new ValidationResult(new ResourceManager(typeof(ValidationErrorMessages)).GetString(this.ErrorMessageKey));
            }
        }

        return ValidationResult.Success;
    }
}

ClientSide

enter code<script type="text/javascript">
jQuery.validator.addMethod('greaterThan', 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()));
}, '');

// and an unobtrusive adapter
jQuery.validator.unobtrusive.adapters.add('validatetodate', {}, function (options) {
    options.rules['greaterThan'] = options.params;
    options.messages['greaterThan'] = options.message;
});

Html

<div class="col-sm-7 margin-top-10">
                <div class="col-sm-12">
                    @Html.LabelFor(m => m.FromDate, new { @class = "col-sm-3 form-group control-label" })
                    <div class="col-sm-8">
                        @Html.TextBoxFor(m => m.FromDate, "{0:MMM dd yyyy}", new { @class = "datepicker", disabled = "disabled" })
                    </div>
                </div>
                <div class="col-sm-12">
                    @Html.LabelFor(m => m.ToDate, new { @class = "col-sm-3 form-group control-label" })
                    <div class="col-sm-8">
                        @Html.TextBoxFor(m => m.ToDate, "{0:MMM dd yyyy}", new { @class = "datepicker", disabled = "disabled" })                                                       
                    </div>                           
                </div>
                    @Html.ValidationMessageFor(m => m.ToDate)
                <button type="submit" class="apply-filter-button">Apply Filter</button>
            </div>

View Model

/// <summary>
    /// Gets or sets from date.
    /// </summary>
    /// <value>
    /// From date.
    /// </value>
    [Display(ResourceType = typeof(DisplayLabelText), Name = "FromDate")]       
    public DateTime FromDate { get; set; }

    /// <summary>
    /// Gets or sets to date.
    /// </summary>
    /// <value>
    /// To date.
    /// </value>
    [Display(ResourceType = typeof(DisplayLabelText), Name = "ToDate")]
    [ValidateToDate("ToDateMustBeGreater")]
    public DateTime ToDate { get; set; }
Was it helpful?

Solution

Finally, i got this working by modified the client side script.

<script type="text/javascript">
jQuery.validator.addMethod('greaterThan', function (value, element, params) {        
    if (!/Invalid|NaN/.test(new Date(value))) {                    
        return Date.parse(value) > Date.parse($(params).val());
    }       
    return isNaN(value) && isNaN($(fromDate)) || (parseFloat(value) > parseFloat($("input[name='FromDate']").val()));
}, '');

// and an unobtrusive adapter
jQuery.validator.unobtrusive.adapters.add('validatetodate', ["other"], function (options) {       
    options.rules['greaterThan'] = "#" + options.params.other;
    options.messages['greaterThan'] = options.message;
});

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top