28
votes

I need to create a view that displays Order Header information and I need to add a patial view that displays a grid of Line Items. The partial view will be strongly typed from a viewmodel. I understand that I should use the html helper @Html.Partial("Path/view"). I have only used controllers up til now to open a view, populating the viewmodel before sending it to the view. Since the partial view is being called form the html helper, I would like to know is what would be the best way to populate the parital view with the model data.

2

2 Answers

52
votes

Option 1: Inherit from parent page

By default, any partial view rendered by calling @Html.Partial("PartialViewName") will get the view model passed to the parent view.

So if you have:

View Model

namespace MyNamesapce
{
    public OrderInfoViewModel
    {
        public string OrderTitle { get; set; }
        public IEnumerable<OrderItem> OrderItems { get; set; }
    }
}

OrderInfo.cshtml

@model MyNamespace.OrderInfoViewModel

<h1>@Model.OrderTitle</h1>

@Html.Partial("OrderLineItems")

The OrderLineItems page should get a MyNamespace.OrderViewModel passed to it... so your partial view should look like this:

OrderLineItems.cshtml

@model MyNamespace.OrderInfoViewModel

foreach (var orderItem in Model.OrderItems)
{
    //Do stuff
}

Option 2: Specify model

You can use the second parameter to specify the view model to be passed. I.e.

OrderInfo.cshtml

@model MyNamespace.OrderInfoViewModel

<h1>@Model.OrderTitle</h1>

@Html.Partial("OrderLineItems", Model.OrderItems)

OrderLineItems.cshtml

@model IEnumerable<OrderItem>

foreach (var orderItem in Model)
{
    //Do stuff
}

Option 3: Use partial actions

If you need to reuse a partial view over multiple pages, it could be a good idea to use a partial view to eliminate having to populate different view models with the same info just because the page is going to be using the same partial.

E.g.

View Model

namespace MyNamesapce
{
    public OrderInfoViewModel
    {
        public string OrderTitle { get; set; }
    }
}

Controller

public class OrderController : Controller
{
    public ActionResult OrderInfo(int orderId)
    {
        OrderInfoViewModel viewModel = GetViewModel(orderId);
        return View(viewModel);
    }

    public PartialViewResult OrderLineItems(int orderId)
    {
        IEnumerable<OrderItem> orderItems = GetOrderItems(orderId);
        return Partial(orderItems);
    }
}

OrderInfo.cshtml

@model MyNamespace.OrderInfoViewModel

<h1>@Model.OrderTitle</h1>

@Html.Action("OrderLineItems")

OrderLineItems.cshtml

@model IEnumerable<OrderItem>

foreach (var orderItem in Model.OrderItems)
{
    //Do stuff
}
6
votes

With a partial view, you are just sending in a Model just like you would with a normal View. For example, if your Model has a property of LineItem objects named 'LineItems' you simply would do this:

@Html.Partial("_PartialName", Model.LineItems)

Now if your Model does not have that property, you can either add it, or pass it another way, like ViewBag (I prefer a strongly typed method, but that is my opnion:

@Html.Partial("_PartialName", (List<LineItem>)ViewBag.LineItems)

These are not the only ways, but they are my preferred methods.