Client side validation of a timespan on asp.net mv

2020-03-05 09:56发布

问题:

I need to receive some time information in the format "hh:mm" (no seconds). The property is defined like this:

[DataType(DataType.Time), DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = @"{0:hh\:mm}")]
public TimeSpan SomeTimeProperty { get; set; }

The server side validation works as expected. However, I can't get the client side validation to work as no client-side validation rules are generated.

How can I make it work?

回答1:

I am afraid you will need to go the long route and create a Custom validator attribute for it.

public class TimeSpanValidationAttribute : ValidationAttribute, IClientValidatable
{
    public bool IsValid() {
        // Your IsValid() implementation here
    }

    // IClientValidatable implementation
    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new TimeSpanValidationRule("Please specify a valid timespan (hh:mm)", "hh:mm");
        yield return rule;
    }
}

Then you need to write the TimeSpanValidationRule class:

public class TimeSpanValidationRule : ModelClientValidationRule
{
    public TimeSpanValidationRule(string error, string format)
    {
        ErrorMessage = error;
        ValidationType = "timespan";
        ValidationParameters.Add("format", format);
    }
}

This is enough to get the Html Helper generate a data-val-timespan="Please specify a valid timespan (hh:mm)" and a data-val-timespan-format="hh:mm" for the html input box.

This two values can be "harvested" by adding an adapter to javascript unobtrusive validation for the "timespan" attribute. It will then be validated by its corresponding rule (which will mimic the server side rule):

$.validator.unobtrusive.adapters.add('timespan', ['format'], function (options) {
    options.rules['timespan'] = {
        format: options.params.format //options.params picked up the extra data-val- params you propagated form the ValidationRule. We are adding them to the rules array.
    };
    if (options.message) { // options.message picked up the message defined in the Rule above
        options.messages['timespan'] = options.message; // we add it to the global messages
    }
});

$.validator.addMethod("timespan", function (value, el, params) {
    // parse the value and return false if not valid and true if valid :)
    // params.format is the format parameter coming from the ValidationRule: "hh:mm" in our case
});