views:

74

answers:

2

Hi,

I have created an Address user control which is as follow:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Address>" %>

   <div class="span-4" style="text-align: right" title="<%: GetLocalResourceObject("Type") %>">
        <%: GetLocalResourceObject("Type")%>
   </div>
   <div class="span-6 last">
       <%: Html.RadioButtonFor(model => model.AddressType, RealProperty.Core.Domain.AddressType.Postal, new { id = ViewData["AddressPrefix"] + "AddressType" })%>
    &nbsp;
       <%: GetLocalResourceObject("PostalType")%>
       <%: Html.RadioButtonFor(model => model.AddressType, RealProperty.Core.Domain.AddressType.Intersection, new { id = ViewData["AddressPrefix"] + "AddressType" })%>
    &nbsp;
       <%: GetLocalResourceObject("IntersectionType")%>
    </div>
    <div class="span-4" style="text-align: right" title="<%: GetLocalResourceObject("Country") %>">
      <%: GetLocalResourceObject("Country")%>
    </div>
    <div class="span-6 last">
    <%: Html.DropDownList(ViewData["AddressPrefix"] + "Country", new SelectList(RealProperty.Core.Service.CountryService.Countries, "Id", "Name"), "Please select Country", new { id = ViewData["AddressPrefix"] + "Country" })%>
        <%: Html.ValidationMessage(ViewData["AddressPrefix"] + "Country")%>
    </div>
    <div class="span-4" style="text-align: right" title="<%: GetLocalResourceObject("Address1") %>">
       <%: GetLocalResourceObject("Address1")%>
    </div>

 .
 .
 .
 .

I'll be using two instance of this user control on a page for "Main Address" and "Alternate Address":

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<PhysicalLocation>" %>

   <div class="span-12">
        <fieldset>
            <legend>Main Address</legend>
            <%
                Html.RenderPartial("~/Views/Address/New.ascx", Model.MainAddress);
            %>
        </fieldset>
    </div>
    <div class="span-12 last">
        <fieldset>
            <legend>Alternate Address</legend>
            <%
                Html.RenderPartial("~/Views/Address/New.ascx", Model.AlternateAddress);
            %>
        </fieldset>
    </div>

Address user control is bound to "Address" model.

 [PostalCode("PostalCode", "Country", ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "PostalCode_Is_Invalid"), DisplayName("Address") ]
    public class Address : ICanBeValidated
    {

        public virtual long Id { get; set; }

        [RegularExpression("^[^,'\"]*$", ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "InvalidCharacter"),
    Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Field_Required"), StringLength(255, ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Field_Max_Length_Allowed")]
        public virtual string Address1 { get; set; }

        [RegularExpression("^[^,'\"]*$", ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "InvalidCharacter"),
    StringLength(255, ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Field_Max_Length_Allowed")]
        public virtual string Address2 { get; set; }

        [RegularExpression("^([a-zA-Z\\.\\-\\s]*)$", ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "ValidCharacter_Allowed")]
        [Required(ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Field_Required"), StringLength(30, ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "Field_Max_Length_Allowed")]
        public virtual string City { get; set; }
    .
    .
    .
 }

I expect upon render, it creates two differnet sets of input controls for MainAddress and AlternateAddress (i.e. coming from Web Form experience).

I'm guessing that I'm missing a very basic point here, since when both user controls are rendered, on the page I have two "city","address1", "address2", etc.

And as the result Microsoft Validation only works for one of the user controls. The JSON array that is sent to client only contains the validation for one, base on the Model definition. For example for “City” property of the address we have only one entry in the mentioned array and as the result only the "span" element with id "City_ValidateMessage" associated to validation exists.

I appreciate any thoughts.

Thanks, Mohammad

A: 

If you're using 2 instances on the page, does your model have 2 sets of properties to store the address?

Your model should be:

Class DoubleAddressViewModel()
    <PropertiesForAddressMain>
    <PropertiesForAddressAlternate>
End Class

From your comments above, I'm guessing you've got a model which represents a single address

Basiclife
Thanks for the reply.I'm having an Address list; IList<Address> Addresses. Addresses[0] is Main, Addresses[1] is Alternative.I may go your path of having only two properties in the Model, however it should work with the list as well?
I haven't delved deeply enough into the property binder to answer that but it seems at a glance that .Net would have difficulty determining how many entries to expect when re-binding the post data to the model. That said, as I haven't tried it, I can't say one way or the other
Basiclife
I've updated the Model with provided solution, however I still don't get what I'm missing here.
Ok let's analyse what's going on with the POST data - If you use ie, get a copy of fiddler 2. <IOf you use firefox, install the firebug addon. For other browsers, you need something which will allow you to inspect traffic to the server. We want to identify exactly what form parameters are being posted back to the server. We then need to put a breakpoint on your action and see what fields have been populate in your model. Also, can you clarify if you've got a model which is 1-deep (Model.Address1Postcode, Model.Address2Postcode) or 2+deep (Model.Address1.Postcode, Model.Address2.Postcode)?
Basiclife
Well, all these happen in Client Side validation and I haven't post data back to server yet. I have a 2+deep model as you mentioned. As you can imagine window.mvcClientValidationMetadata variable only contains one entry for "Postcode" validation rules.
Sorry, you mentioned a JSON response sent to the client with validation data - which implies server-side validation? or do you mean the validation definition loaded when the form is displayed?For testing purposes, can you disable client-side validation and let me know what happens with the model on the HTTPPost'd action?
Basiclife
A: 

The solution that I found on Steve Sanderson's blog is a hack on HttpContext to generate unique ids when rendering the user control. It solves the problem with validation nicely.