Asp.Net MVC2 Clientside Validation problem with controls with prefixes
Asked Answered
P

1

5

The problem is: when I put 2 controls of the same type on a page I need to specify different prefixes for binding. In this case the validation rules generated right after the form are incorrect. So how to get client validation work for the case?:

the page contains:

<%
    Html.RenderPartial(ViewLocations.Shared.PhoneEditPartial, new PhoneViewModel { Phone = person.PhonePhone, Prefix = "PhonePhone" });
    Html.RenderPartial(ViewLocations.Shared.PhoneEditPartial, new PhoneViewModel { Phone = person.FaxPhone, Prefix = "FaxPhone" });
%>

the control ViewUserControl<PhoneViewModel>:

<%= Html.TextBox(Model.GetPrefixed("CountryCode"), Model.Phone.CountryCode) %>
<%= Html.ValidationMessage("Phone.CountryCode", new { id = Model.GetPrefixed("CountryCode"), name = Model.GetPrefixed("CountryCode") })%>

where Model.GetPrefixed("CountryCode") just returns "FaxPhone.CountryCode" or "PhonePhone.CountryCode" depending on prefix


And here is the validation rules generated after the form. They are duplicated for the field name "Phone.CountryCode". While the desired result is 2 rules (required, number) for each of the FieldNames "FaxPhone.CountryCode", "PhonePhone.CountryCode" alt text http://www.freeimagehosting.net/uploads/37fbe720bf.png

The question is somewhat duplicate of Asp.Net MVC2 Clientside Validation and duplicate ID's problem but the advise to manually generate ids doesn't helps.

Predictor answered 3/5, 2010 at 15:31 Comment(0)
P
10

Correct way to set the same prefixes both for textbox and validation:

<% using (Html.BeginHtmlFieldPrefixScope(Model.Prefix)) { %>
   <%= Html.TextBoxFor(m => m.Address.PostCode) %>
   <%= Html.ValidationMessageFor(m => m.Address.PostCode) %>
<% } %>

where

public static class HtmlPrefixScopeExtensions
{
    public static IDisposable BeginHtmlFieldPrefixScope(this HtmlHelper html, string htmlFieldPrefix)
    {
        return new HtmlFieldPrefixScope(html.ViewData.TemplateInfo, htmlFieldPrefix);
    }

    private class HtmlFieldPrefixScope : IDisposable
    {
        private readonly TemplateInfo templateInfo;
        private readonly string previousHtmlFieldPrefix;

        public HtmlFieldPrefixScope(TemplateInfo templateInfo, string htmlFieldPrefix)
        {
            this.templateInfo = templateInfo;

            previousHtmlFieldPrefix = templateInfo.HtmlFieldPrefix;
            templateInfo.HtmlFieldPrefix = htmlFieldPrefix;
        }

        public void Dispose()
        {
            templateInfo.HtmlFieldPrefix = previousHtmlFieldPrefix;
        }
    }
}

(by chance found the solution in the code on Steve Sanderson's blog http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/)

Also looks like Html.EditorFor approach should work as well as suggested here: ASP.NET MVC 2 - ViewModel Prefix

Predictor answered 5/5, 2010 at 1:11 Comment(4)
Nice. This answer was very helpful. Wish I could upvote it a couple more times.Lycopodium
I know this is an old answer, but I was wondering if your method is preferable to putting this in your view: ViewData.TemplateInfo.HtmlFieldPrefix = "myViewModel.MyCustomObjdect";Uund
Yes, cause it does the same in DRY manner and more: it restores previous HtmlFieldPrefix in Dispose method.Predictor
I think this should be a part of MVC core functionalityProa

© 2022 - 2024 — McMap. All rights reserved.