Multi-lingual form validation using MVC DataAnnotation attributes and Sitecore – Part 2 (Client validation)

So you wanna extend your custom MVC data annotations for form validations for client-side validation?

internationalI suggest that you read Part 1 for context and to ensure that you have the prerequisites to fully understand the series.

In the first post of this series, we built custom attributes to allow the language translation of the error messaging. These custom attributes need to be extended to support client validation.

1) Below is the data model properties decorated with custom attributes that provide translated error messaging (via Sitecore.Globalization.Translate and the dictionary domain) for server validation:

public class RequiredTranslated : RequiredAttribute
    {
        public override string FormatErrorMessage(string name)
        {
            return Translate.Text(base.FormatErrorMessage(name));
        }
    }

public class MinLengthTranslated : MinLengthAttribute
    {
        public MinLengthTranslated(int length) : base(length) { }

        public override string FormatErrorMessage(string name)
        {
            return Translate.Text(base.FormatErrorMessage(name));
        }
    }

public class CompareTranslated : CompareAttribute
    {
        public CompareTranslated(string otherProperty) : base(otherProperty) { }

        public override string FormatErrorMessage(string name)
        {
            return Translate.Text(base.FormatErrorMessage(name));
        }
    }

These classes inherit from their ‘non-translated’ equivalents, “Required”, “MinLength”, and “Compare.”

To improve on this translated server validation, let’s add translated client validation.

Each custom attribute class will inherit from IClientValidatable. IClientValidatable requires implementation of a method called GetClientValidationRules() which ensures the propagation of the validation rule(s) within the validation markup and script.

RequiredAttribute -> RequiredTranslatedAttribute
Adding the method to RequiredTranslated is straightforward; implement the method for IClientValidatable and pass the translated text for the error messaging to the front-end.

MinLength -> MinLengthTranslated
For MinLengthTranslated, the front-end not only needs the error message but also the minimum length to properly validate with javascript (More on the javascript in the next section).

Compare -> CompareTranslated
CompareTranslated elevates the complexity of implementing IClientValidatable because we need to pass an existing property thru to the validator (in this case, the VerifyPassword property value needs to be evaluated against the Password property value). The script needs to know in what parameter the property will be passed  (below, that is the ‘other’ param). We also need to declare which validation rule (i.e. ValidationType) of jquery.validate that this property matches to.  In this case, it matches the jquery.validate rule of “equalto”.

2) Implement IClientValidatable for each custom attribute.

public class RequiredTranslated : RequiredAttribute, IClientValidatable
    {
        public override string FormatErrorMessage(string name)
        {
            return Translate.Text(base.FormatErrorMessage(name));
        }

        public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            return new[] { new ModelClientValidationRequiredRule(Translate.Text(ErrorMessage)) };
        }
    }

public class MinLengthTranslated : MinLengthAttribute, IClientValidatable
    {
        public MinLengthTranslated(int length) : base(length) { }

        public override string FormatErrorMessage(string name)
        {
            return Translate.Text(base.FormatErrorMessage(name));
        }

        public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            return new[] { new ModelClientValidationMinLengthRule(Translate.Text(ErrorMessage), Length) };
        }
    }

public class CompareTranslated : CompareAttribute, IClientValidatable
    {
        public CompareTranslated(string otherProperty) : base(otherProperty) { }

        public override string FormatErrorMessage(string name)
        {
            return Translate.Text(base.FormatErrorMessage(name));
        }

        public IEnumerable GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var clientValidationRule = new ModelClientValidationRule()
            {
                ErrorMessage = FormatErrorMessage(ErrorMessage),
                ValidationType = "equalto"
            };

            clientValidationRule.ValidationParameters.Add("other", OtherProperty));

            return new[] { clientValidationRule };
        }
    }

3) What happens when this new “GetClientValidationRules()” method is called when building the HTML for the page and what javascript is required?

In ASP.NET MVC 3 a new feature called “Unobtrustive Client Validation” was added which uses jQuery and jQuery.validate to perform validation based on the data annotations (and in our case, custom attributes). There are plenty of blogs that describe.

What do you need to use this?

First, turn on the functionality in the appSettings.config file:

configvalidatesettings

You will also need to include three javascript files (or their min equivalent) on your page:

1) jQuery
2) jQuery Validate
3) jQuery Validate Unobtrusive (plugin for ASP.NET MVC by Microsoft)

It all works as smooth as butter.  Love it.

What if you want to do some custom validation??  Glad you asked!  Check out Part 3 of this series, Custom Validation, Soup to Nuts.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s