Client-side validation for wrapped/multi model views

195 Views Asked by At

I have these 2 model classes wrapped in one model. The strongly typed view and server side validation works well enough but I can't get the client-side validation working for this wrapped model class.

Here's my client-side code:

Sys.Mvc.ValidatorRegistry.validators.usernameEmail = function (rule) {

    var emailProperty = rule.ValidationParameters.emailProperty;
    var message = rule.ErrorMessage;

    return function (value, context) {
        if (!value || !value.length) {
            return true;
        }

        var usernameField = context.fieldContext.elements[0];
        var emailFieldId = $('input[name = "' + emailProperty + '"]').attr('id');
        var emailField = $get(emailFieldId, usernameField.form);

        //...validation stuff...

    };
};

The problem is that emailProperty returns only the property name stated in its model ie. "EmailAddress" but the strongly typed view assigns the name as "Model1Name.EmailAddress" since it is called like:

<%: Html.TextBoxFor(m => m.Model1Name.EmailAddress)%>

Thus it returns null when looking for the property and I get an error. So I guess my questions here would be:

  1. Is there a way to get the assigned model name ("Model1Name") so I could append it with the property name?
  2. Could I pass the assigned model name from the DataAnnotations/ModelValidationRule classes? If so, how?

Here are my model classes:

public class Model1
{
    public string EmailAddress{ get; set; }
    ...
}

public class Model2
{
    [UsernameEmail]
    public string Username{ get; set; }
    ...
}

public class WrappedModel
{
    public Model1 Model1Name{ get; set; }
    public Model2 Model2Name { get; set; }
}

Side-note: The client side validation works well for single model views.

Edit After much debugging, I found out that

viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId("EmailAddress");

in my DataAnnotationsModelValidator is returning only the parameter name "EmailAddress" and is leaving out its prefix "Model1Name" thus returning the wrong Id.

Any help would be appreciated. Thanks.

1

There are 1 best solutions below

5
On

Your custom [UsenameEmail] attribute is a piece which is responsible for emitting correct client-side validation metadata. To be more precise, there should be validator adapter registered for that. You need to make sure adapter generates full property name, i.e. "Model1Name.EmailAddress", then "usernameEmail" client-side function will receive correct field name and will operate as expected.

See "DataAnnotationsModelValidatorProvider.RegisterAdapter(...)" for more details. Here is implementation sample - http://weblogs.asp.net/jacqueseloff/archive/2009/12/17/asp-net-mvc-2-rc-validating-credit-card-numbers.aspx