views:

1012

answers:

3

I want to use RenderPartial twice in my view with different models associated. The problem is that some properties are present in both models (nickname, password). They have no prefix, so even the id's or names are equal in the output. Now, if I have model errors for nickname or password, both fields get highlighted.

Main View:

<div>
    <% Html.RenderPartial("Register", Model.RegisterModel); %>
</div>
<div>
    <% Html.RenderPartial("Login", Model.LoginModel); %>
</div>

Login PartialView:

<% using (Html.BeginForm("Login", "Member")) { %>
<fieldset>
    <legend>Login</legend>
    <p>
        <%= Html.LabelFor(x => x.Nickname) %>
        <%= Html.TextBoxFor(x => x.Nickname) %>
    </p>
    <p>
        <%= Html.LabelFor(x => x.Password) %>
        <%= Html.PasswordFor(x => x.Password) %>
    </p>    
    <input type="submit" value="Login" />
</fieldset>
<% } %>

Register PartialView:

<% using (Html.BeginForm("Register", "Member")) { %>
<fieldset>
    <legend>Register</legend>
    <p>
        <%= Html.LabelFor(x => x.Nickname) %>
        <%= Html.TextBoxFor(x => x.Nickname) %>
    </p>
    <p>
        <%= Html.LabelFor(x => x.Email) %>
        <%= Html.TextBoxFor(x => x.Email) %>
    </p>
    <p>
        <%= Html.LabelFor(x => x.Password) %>
        <%= Html.PasswordFor(x => x.Password) %>
    </p>
    <p>
        <%= Html.LabelFor(x => x.PasswordRepeat) %>
        <%= Html.PasswordFor(x => x.PasswordRepeat) %>
    </p>
    <input type="submit" value="Register" />
</fieldset>
<% } %>

How can I change this?

A: 

Looks like there's an overload for TextBoxFor that allows you to specify extra HTML attributes. It isn't an ideal solution, but it should let you change the id (and possibly name?) of the rendered textboxes. Of course changing the name would probably screw things up when you try to post the form.

R0MANARMY
A: 

First of all, you could use Html.TextBox("input form name", ...) and set the name to whatever you wish. There's a bigger issue how would you provide a prefix on Html.RenderPartial() level? You are already providing a model instance. So without changing their view models, there's just one more possibility: to write your own overloads for RenderPartial() that would take the prefix and pass it on to others.

Check this one out. Someone's written a whole bunch of overloads that support setting prefixes. http://stackoverflow.com/questions/2051985/textboxfor-rendering-to-html-with-prefix-on-the-id-attribute

If any is missing you can see the pattern how to extend these with additional ones you may need.

Robert Koritnik
You don't need to write your own overload for RenderPartial, there's already an overload that let's you redefine what the ViewData collection is. You can just add your prefix in there and have your model look for it. See: http://msdn.microsoft.com/en-us/library/dd470827.aspx
R0MANARMY
+4  A: 

Instead of using Html.RenderPartial you could use editor templates which will handle prefixes.

So in your main view:

<div>
    <%-- See below what does the second argument mean --%>
    <%= Html.EditorFor(x => x.RegisterModel, "RegisterModel") %>
</div>
<div>
    <%= Html.EditorFor(x => x.LoginModel, "LoginModel") %>
</div>

And then create a folder Views/Shared/EditorTemplates/RegisterModel.ascx (The name of this file is used in the EditorFor helper method). Also notice that this partial should be strongly typed to the type of the RegisterModel property:

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

<% using (Html.BeginForm("Register", "Member")) { %>
<fieldset>
    <legend>Register</legend>
    <p>
        <%= Html.LabelFor(x => x.Nickname) %>
        <%= Html.TextBoxFor(x => x.Nickname) %>
    </p>
    <p>
        <%= Html.LabelFor(x => x.Email) %>
        <%= Html.TextBoxFor(x => x.Email) %>
    </p>
    <p>
        <%= Html.LabelFor(x => x.Password) %>
        <%= Html.PasswordFor(x => x.Password) %>
    </p>
    <p>
        <%= Html.LabelFor(x => x.PasswordRepeat) %>
        <%= Html.PasswordFor(x => x.PasswordRepeat) %>
    </p>
    <input type="submit" value="Register" />
</fieldset>
<% } %>

You could define a different partial for the login model in Views/Shared/EditorTemplates/LoginModel.ascx

Darin Dimitrov