This is a followup question for this one: How does DataAnnotations really work in MVC?
There is an example custom validation, and a "Self Validate Model" was mentioned. It is quite interesting, but I don't understand how to write a client side validation for it.
Can my model object implement the IClientValidateble interface (or it is for the dataannotation attributes only?), I would like to see an example on how to do it.
Edit: To my understanding, the "Self Validate Model" works without using DataAnnotations, and declares the validation logic inside the class which properties I'm validating, and it's not (necessarily) using attributes to validate something.
All of the examples I have seen on custom client side validation is about the dataannotation attribute implementing IClientValidatable.
When I'm declaring my validation logic in my class, I don't use attributes to validate the models state.
How to write clientside validation when I'm declaring my validation logic in the Validate method of the model class implementing the IValidatebleObject interface?
Can the class I'm actually passing to the view implement the IClientValidatable interface or something similar?
Taking the same answer:
After you implement the Self Validate Model, witch is a Server Side Validation, you need to create the Client Side Validation part, for that, just create this 3 steps:
- Implement
- Implement a jQuery validation method
- Implement an unobtrusive adapter
append to your IClientValidateble
class
public IEnumerable<ModelClientValidation> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelCLientValidationRule();
rule.ErrorMessage = FormatErrorMessage(metadata.GetDisplayName());
rule.ValidationType = "greater"; // This is what the jQuery.Validation expects
rule.ValidationParameters.Add("other", OtherPropertyName); // This is the 2nd parameter
yield return rule;
}
Then you need to write the new jQuery Validator and the metadata adapter that will link the jQuery.Validation with your code providing the correct data-
attributes for that field (if of course, UnobtrusiveJavaScriptEnabled
is true)
create a new js
file and attach to your <head>
for example as
<script src="@Url.Content("~/Scripts/customValidation.js")" type="text/javascript"></script>
and append the new validation
jQuery.validator.addMethod("greater", function(value, element, param) {
// we need to take value and compare with the value in 2nd parameter that is hold in param
return Date.parse(value) > Date.parse($(param).val());
});
and then we write the adapter
jQuery.validator.unobtrusive.adapters.add("greater", ["other"], function(options) {
// pass the 'other' property value to the jQuery Validator
options.rules["greater"] = "#" + options.param.other;
// when this rule fails, show message that comes from ErrorMessage
options.messages["greater"] = options.message;
});
You can view this in the AccountModel.cs
when you create a new MVC3 Web Applicatoin, it shows this method that implements the IClientValidatable
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class ValidatePasswordLengthAttribute : ValidationAttribute, IClientValidatable
{
private const string _defaultErrorMessage = "'{0}' must be at least {1} characters long.";
private readonly int _minCharacters = Membership.Provider.MinRequiredPasswordLength;
public ValidatePasswordLengthAttribute()
: base(_defaultErrorMessage)
{
}
public override string FormatErrorMessage(string name)
{
return String.Format(CultureInfo.CurrentCulture, ErrorMessageString,
name, _minCharacters);
}
public override bool IsValid(object value)
{
string valueAsString = value as string;
return (valueAsString != null && valueAsString.Length >= _minCharacters);
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
return new[]{
new ModelClientValidationStringLengthRule(FormatErrorMessage(metadata.GetDisplayName()), _minCharacters, int.MaxValue)
};
}
}
#endregion