By ricardo


2011-01-24 17:19:57 8 Comments

Following on from this post Perform client side validation for custom attribute

I am trying to get my head around how to do this, passing additional parameters to the client-side script

As I understand it so far to implement custom validation with MVC 3 the following is required

Create a custom validation attribute

Based on ValidationAttribute and implementing IClientValidatable. I have also see some examples deriving from ModelValidator, which seems to implement the functionality of both ValidationAttribute and IClientValidatable. So this is my first point of confusion as to what the diffirences are or whether ModelValidator was used in MVC 2 but is now deprecated or what ?

An instance of ModelClientValidationRule must be returned from GetClientValidationRules() to specify details such as the error message, ValidationType (which I understand to be the name of the Javascript function that will perform the client-side validation) and any additional custom parameters that the attribute may have, and that need to be passed to the Javascript validation.

I assume that the runtime (not sure which part of it) then use the ModelClientValidationRule to generate html attribute in the tag elements as follows:

data-val="true"  (to indicate that the element requires validation)
data-val-[ValidationType]=[ErrorMessage]
data-val-[ValidationType].[ValidationParameters(n).Key]=[ValidationParameters(n).Value]

Implement the client-side validation logic

A Javascript function must be created and added to jQuery.validators with jQuery.validators.addmethod() so that JQuery is aware of it when it need to be executed. Something like:

jQuery.validator.addMethod(
    'greaterThan', 
    function (value, element, params) {
        /.../
       return /* true or false   */ ; 
    },
    ''
); 

My question here is whether the signature 'function (value, element, params)' is standard for methods that will handle validation and I assume it will be called by some jQuery functionality at the appropriate time such as before a form is submitted or when an element looses fuces or on keyUp events. I just don't undertand how you can controll this i.e. choose which event is appropriete for yout custom validation.

Implement an unobtrusive adapter

This translates unobtrusive attributes to; something I am not very clear on, but assume it to be a jQuery Rule, but I am not clear on how those work. Something like

jQuery.validator.unobtrusive.adapters.add(
    'futuredate', 
    { },
    function (options) {
        options.rules['greaterThan'] = true;
        options.messages['greaterThan'] = options.message;
    }
); 

My question here is about 'function (options)'. Is this the function that will be called before 'function (value, element, params)' and is responsible for extracting the unobtrusive tags into a data structure that can be understood by jQuery.Validation. From the code example it seems to me that options is an object that contains both, the attribute values from the tag (such as options.message) and the jQuery relevant properties it must map to (such as options.messages['ClientSideValidationFunctionName']. If so how are custom parameters retrieved and mapped.

I hope I have not added any additional confusion.

1 comments

@Darin Dimitrov 2011-01-24 17:24:43

You could use the ValidationParameters property to add custom parameters to the rule:

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
    var rule = new ModelClientValidationRule
    {
        ErrorMessage = this.ErrorMessage,
        ValidationType = "futuredate",
    };
    rule.ValidationParameters.Add("param1", "value1");
    rule.ValidationParameters.Add("param2", "value2");
    yield return rule;
}

which could be used in the adapter:

jQuery.validator.unobtrusive.adapters.add(
    'futuredate', 
    [ 'param1', 'param2' ],
    function (options) {
        var param1 = options.params.param1; // shall equal 'value1'
        var param2 = options.params.param2; // shall equal 'value2'
        // TODO: use those custom parameters to define the client rules
    }
);

UPDATE:

As requested in the comments section here's how you could pass those parameters to the custom validator rule function:

jQuery.validator.unobtrusive.adapters.add(
    'futuredate', 
    [ 'param1', 'param2' ],
    function (options) {
        // simply pass the options.params here
        options.rules['greaterThan'] = options.params;
        options.messages['greaterThan'] = options.message;
    }
);

jQuery.validator.addMethod('greaterThan', function (value, element, params) {
    // params here will equal { param1: 'value1', param2: 'value2' }
    return ...
}, '');

@ricardo 2011-01-24 17:35:47

ok great. Could you also please show how I would reference those params in the script that would perform the validation. This is where I am now stuck. I understand the method signature for the validation is function (value, element, params), but am not sure how param1 and param2 are passed to it

@ricardo 2011-01-24 17:38:33

P.S. I have register the validationmethod with jQuery.validator.addMethod('validationtype', function (value, element, params) { /* ...*/ },'');

@Darin Dimitrov 2011-01-24 17:54:26

@ricardo, does this answer your question?

@ricardo 2011-01-24 17:59:18

Apologies for being a bit dence. Would you mind showing me some code accessing those like just an alert please.

@Darin Dimitrov 2011-01-24 18:01:10

@ricardo, you could alert(params.param1); or alert(params.param2);

@ricardo 2011-01-24 18:12:02

AaaaHH Yes finally. I was trying that but had not assigned options.rules['greaterThan'] = options.params. Thanks your are a star. It is really hard to find any complete exampels. I think the naming options.rules to assign the parameters is not very intuative . 'rules; was indicative to me of having to provide the name of the function that would enforce the rule, but I now understand that it server to provide the variables required. Thanks again

@ricardo 2011-01-24 19:22:32

Actually could you possibly also shed some light on some of these other related question in my post ...

@ricardo 2011-01-24 19:23:45

1. What is the diffirence between deriving from ValidationAttribute end implementing IClientValidatable or deriving from ModelValidator or DataAnnotatiopnModelValidator

@ricardo 2011-01-24 19:25:48

2. Is 'function (value, element, params)' the standard and jQuery validation function or doe sit belong to Microsoft's unobtrusive validation

@Darin Dimitrov 2011-01-24 19:33:17

@ricardo, concerning your first question, ModelValidator allows you to achieve the same thing as with IClientValidatable as it exposes the GetClientValidationRules method. As far as your second question is concerned, that's jquery validation.

@ricardo 2011-01-24 19:59:23

So there is no compelling reason to use DataAnnotationModelValidator one over ValidationAttribute with IClientValidatable. ?

@Darin Dimitrov 2011-01-24 20:03:21

@ricardo, ValidationAttribute acts on a single property of your model whereas a ModelValidator acts on the entire model.

@ricardo 2011-01-24 20:32:36

That was what I thought to, but having read this several posts I have noted that ValidateAttribute now also as an IsValid(object value, ValidationContext context) which as I understand it give access to the whole model. So I am wondering if there is any other reason to derive from ModelValidator

@Paul Hiles 2011-01-28 10:30:21

The ModelValidator approach is from MVC2 and in my opinion, should not be used going forward on an MVC3 project. The MVC3 ValidationAttribute/IClientValidatable approach is much cleaner and does not involve modifying the global.asax to register the adapter.

@kdawg 2011-01-28 23:31:31

holy crap, this line of comments is exactly what i needed. i've been working with an mvc 2 site that i updated to mvc 3. it has a custom "RequiredIf" ValidationAttribute that uses DataAnnotationsModelValidator and all that stuff described here: haacked.com/archive/2009/11/19/…. I was getting so confused by the old way and these new mvc3 ways of doing it. apparently they achieve the same thing. thanks for the documentation (and heads up) on this, microsoft! sigh Thanks Darin, ricardo, and The Flower Guy!

@kdawg 2011-01-28 23:45:56

Of course, I'm still not totally set on this stuff. If someone were to post a blog entry or something describing what's new in mvc 3 and what it replaces from mvc 2 regarding emitting client-side validation from custom DataAnnotations, that'd be the bees knees! =D

@Softlion 2011-04-28 14:04:41

In fact DataAnnotationsModelValidator in MVC3 is still useful if the attribute is not your attribute, or if it is in another assembly which does not reference the Mvc assembly.

@Enigma State 2013-07-30 15:57:21

@DarinDimitrov would you pls tell what is meant by this one ['greaterThan'] .. is this is the method name like this one ...'futuredate' or any other thing...

@Alexandr 2015-11-06 15:25:15

How can I test such Validator?

Related Questions

Sponsored Content

88 Answered Questions

[SOLVED] How to validate an email address in JavaScript

73 Answered Questions

20 Answered Questions

[SOLVED] Does Java support default parameter values?

8 Answered Questions

[SOLVED] How are parameters sent in an HTTP POST request?

25 Answered Questions

[SOLVED] Set a default parameter value for a JavaScript function

49 Answered Questions

[SOLVED] Validate decimal numbers in JavaScript - IsNumeric()

21 Answered Questions

[SOLVED] File Upload ASP.NET MVC 3.0

43 Answered Questions

2 Answered Questions

3 Answered Questions

[SOLVED] IValidatableObject in MVC3 - client side validation

Sponsored Content