I've read Phil Haack's post on custom client-side validation in ASP.NET MVC 2. I want to do the same thing but with the jQuery adapter and using ASP.NET MVC 2 RC (as opposed to MVC 2 Beta that the post uses). Has anyone been able to figure how to do this?
I specially want to implement the password matching validation (i.e. password & confirm password must match). The ASP.NET MVC 2 RC VS.NET project template does show how to implement that on the server-side (using the PropertiesMustMatchAttribute
) but not on the client-side.
I assume you already followed Phil Haack's instructions here http://haacked.com/archive/2009/11/19/aspnetmvc2-custom-validation.aspx) on how to get custom validation working with MS AJAX client validation. To get it to work with jQuery, you'll need to modify the MicrosoftMvcJQueryValidation.js file:
In the __MVC_CreateRulesForField(validationField) function, you'll need to add a case statement. Continuing Phil's example, you'll need to add:
case "price":
__MVC_ApplyValidator_Price(rulesObj, thisRule.ValidationParameters["min"]);
break;
You'll then need to create the __MVC_ApplyValidator_Price function:
function __MVC_ApplyValidator_Price(object, value) {
// min is what jQuery Validate uses to validate for minimum values
object["min"] = value;
}
That should be enough to get Phil's example working.
Now, regarding your PropertiesMustMatchAttribute validation, it doesn't look like MVC generates the client-side json validation definition for attributes that decorate classes. Since PropertiesMustMatchAttribute must be used on the model (and not the property), I can't figure out how to make it trigger client-side validation. Instead, I took a different approach. I created a dummy validation attribute who's IsValid() overload always returns true, and used this attribute on a property. This is just a dummy attribute that will delegate the validation logic to jQuery validator's equalTo function. Here's the dummy attribute:
public class PropertiesMustMatchClientTriggerAttribute : ValidationAttribute
{
public string MatchProperty { get; set; }
public PropertiesMustMatchClientTriggerAttribute(string matchProperty)
{
MatchProperty = matchProperty;
ErrorMessage = "{0} doesn't match {1}.";
}
public override bool IsValid(object value)
{
return true;
}
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, MatchProperty);
}
}
Here is the custom validator:
public class PropertiesMustMatchClientTriggerValidator : DataAnnotationsModelValidator<PropertiesMustMatchClientTriggerAttribute>
{
private string _message;
private string _matchProperty;
public PropertiesMustMatchClientTriggerValidator(ModelMetadata metaData, ControllerContext context, PropertiesMustMatchClientTriggerAttribute attribute)
: base(metaData, context, attribute)
{
_message = attribute.FormatErrorMessage(metaData.DisplayName);
_matchProperty = attribute.MatchProperty;
}
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
var rule = new ModelClientValidationRule
{
ErrorMessage = _message,
ValidationType = "equalTo"
};
rule.ValidationParameters.Add("matchField", _matchProperty);
return new[] { rule };
}
}
the above custom validator needs to be registered in Application_Start() per Phil's blog:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(PropertiesMustMatchClientTriggerAttribute), typeof(PropertiesMustMatchClientTriggerValidator));
Finally, you need to modify the MicrosoftMvcJQueryValidation.js file:
case "equalTo":
__MVC_ApplyValidator_EqualTo(rulesObj, thisRule.ValidationParameters["matchField"]);
break;
function __MVC_ApplyValidator_EqualTo(object, elemId) {
object["equalTo"] = document.getElementById(elemId);
}
Now you need to attach the dummy validation attribute to a property:
[PropertiesMustMatchClientTrigger("Password")]
public string ConfirmPassword { get; set; }
That should do it.
Creating this dummy attribute is a bit ugly, so I hope someone can come up with a more elegant solution.
Here's how to add a custom jQuery validation:
$.validator.addMethod("noSpaces", function(value, element) {
if ($(element).val().indexOf(" ") >= 0) {
return false;
} else {
return true;
}
}, "Value must not contain spaces");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With