简体   繁体   中英

How to handle PartialView with different model than parent View

I'm using VS2012 RC with MVC4, bot for all intents and purposes let's pretend it's MVC3. I would like to know what the standard best practice(s) is on how to handle PartialViews with a form that uses a different model than the parent View.

For example, here is a view that displays a table of all the available Roles and also has a form that allows the user to add more roles.

Main View - Roles.cshtml:

@model IEnumerable<RobotDog.Models.RoleModel>

<table>
    @foreach(var role in Model) {
        <tr>
            <td class="roleRow">@role.Role</td>
        </tr>
    }
</table>
<div class="modal hide">
    @Html.Partial("_AddRolePartial")
</div>

_AddRolePartial.cshtml

@model RobotDog.Models.RoleModel

@using(Html.BeginForm("AddRole","Admin", FormMethod.Post)) {
    @Html.TextBoxFor(x => x.Role, new { @class = "input-xlarge", @placeholder = "Role"})
    <input type="submit" value="Submit" class="btn btn-primary btn-large"/>
}

Model:

public class RoleModel {
    [Required]
    [DataType(DataType.Text)]
    [Display(Name = "Role")]
    public string Role { get; set; }
}

Controller for View:

public ActionResult Roles() {
    var model = from r in System.Web.Security.Roles.GetAllRoles()
                select new RoleModel {Role = r};
    return View(model);
}

Controller for PartialView:

[HttpPost]
public ActionResult AddRole(RoleModel model) {
    try {
        System.Web.Security.Roles.CreateRole(model.Role);
        RedirectToAction("Roles");
    } catch(Exception) {
        ModelState.AddModelError("", "Role creation unsuccessful.");
    }

    return ????; // not sure how to pass ModelState back to partialView
}

I thought about creating a ViewModel that held RoleModel and IEnumerable<RoleModel> but it seems like there would be a more stream lined way to accomplish what I wanted without having to create a ViewModel everytime I wanted to use this PartialView.

I think you are asking how to pass a RoleModel to the add RoleModel modal popup. Since you are creating a new Role, I am assuming you are needing an empty model. You can either pass it in like below:

<div class="modal hide">
    @Html.Partial("_AddRolePartial", new RoleModel())
</div>

Or just do a @Html.RenderAction("AddRole") with the supporing GET method of the controller to support populating the item.

public ActionResult AddRole() {
    var model = new RoleModel();
    //populate with any items needed for the Add Role Model View
    return View(model);
}

How about the form post is changed to an ajax form post with a target update partial id being the div which you will add to the parent view (effectively surrounding Roles.cshtml).

Add a new action public ActionResult _Roles() which will return PartialView("Roles", model)

Next, in the Post Action, Return RedirectToAction(...Roles Partial Action ...) at the end and remove RedirectToAction("Roles") in the try .

I personally don't like using Partial views with forms, because Partial Views do not render submodels correctly (ie, they don't take into account the hierarchy of the model).

This is why Display and EditorTemplates exist. They work well for rendering specific data types.

However, in your case, since your view doesn't have any forms of its own, and the end result is just a single item of the collection of your parent model, then a Partial View is actually a better approach simply because you CAN pass a different model to it than the views uses.

As others have pointed out, you can easily pass an empty model to the partial as the second parameter. I don't like newing up new objects in the view, but it doesn't look like there's a lot of choice there, as the alternatives would be pretty messy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM