4

I have a view model containing a DateTime property, for which I want to provide a text box using using a custom format (only month and year, "MM.YYYY"):

public class MyModel {
  public DateTime? DateField {get; set;}
}

Formatting the value for the TextBox is easy (using the format string). I also have implemented a custom model binder to do the conversion and this works fine.

I still have a problem with client side validation: I can implement a custom validator deriving from ValidationAttribute which implements IClientValidatable and set up the corresponding jquery.validate adapters etc.

But MVC still adds the "default" validation attribute data-val-date (in addition to my custom validation attribute data-val-monthyeardate) to the input field, so the default check still applies and the input "MM.YYYY" is rejected.

Is there any way to suppress the default client side validation for a data type and replace it with a custom one (instead of "adding" the custom one)?

MartinStettner
  • 28,719
  • 15
  • 79
  • 106

3 Answers3

3

Since the framework doesn't let you override the real type with some custom attribute or even override the ModelMetadataProvider for specific types, you'll have to register your own global ModelMetadataProvider that fools the validator to think it's actually a string.

Something like:

public class MyModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {
        if (attributes.OfType<ExcludeCharAttribute>().Any())
            modelType = typeof (String);

        return base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName); ;
    }
}

Register it using:

ModelMetadataProviders.Current = new MyModelMetadataProvider();

Still, since the core problem is a client-side problem, I would deal with it purely with client-side code. In your monthyeardate adapter you can force removal of the date validation (I can provide an example if you'll share your monthyeardate code).

See MSDN

haim770
  • 48,394
  • 7
  • 105
  • 133
  • 1
    Thanks! In the meanwhile I came up with your second solution too: when adding the adapter (using `jQuery.validator.unobtrusive.adapters.add`), I put something like `options.rules['date'] = false;` in the registration code. This works perfectly. – MartinStettner Nov 05 '14 at 15:55
2

This is hacky but one simple thing you could do is add:

$(function () {
    $.validator.methods.date = function () { return true; }; 
});

So that the default data-val-date always returns true along with firing your custom date validation.

AlexC
  • 10,676
  • 4
  • 37
  • 55
0

I know that this is a little older, and just in case someone doesn't think about it (and since I cannot leave comments yet), to enhance @AlexC response, you can add validation to to that statement.

For instance, I use moment.js for date validation (moment.js), and this allows you to add your own validation rules.

if (moment(a, "M/YYYY").isValid() || moment(a).isValid())
{
    return true;
}

This will check to see if it is a regular date, and also in this case, if the date is in "M/YYYY" format. If one of these are true, it accepts the validation.

Godrules500
  • 467
  • 6
  • 25