VictorySaber
VictorySaber

Reputation: 3164

Passing different models to RenderPartial()

I am chaining some partial views together, and I require a way to use different models in my call to RenderPartial(). Most answers on SO state to cast to the model type, but this will not be known at compile-time.

The website has different categories such as Cars, Planes, Helicopters and Boats. When the user clicks on say the Cars link, the Car controller's Index page displays all cars in a pretty table. Same for Planes etc. All the tables are identical, so I want to use a partial view to reuse the code.

@model IEnumerable<MyNamespace.Entities.Car>
@{Html.RenderPartial("Partials/_TableList", Model);}

Inside _TableList.cshtml is my pretty table. So I now want to call another partial view, which takes a list of models of type Car, and output the table head and body. Likewise if the user had clicked Planes, this would load a partial that takes a list of Plane models.

<table class="table prettyTable">
@{Html.RenderPartial((string)ViewBag.PartialToLoad, Model);}
</table>

And in _CarList.cshtml

@model IEnumerable<MyNamespace.Entities.Car>
<thead>...</thead>
<tbody>
@foreach (var item in Model)
{ ... }
</tbody>

Can this be done? Or must I put the model in the ViewBag and pass that around?

EDIT: Thanks to @Adas, I was able to solve this by adding

@model IEnumerable<dynamic>

to the top of _TableList.cshtml. Now, when I call RenderPartial() it does not complain that "Extension methods cannot be dynamically dispatched". This now works perfectly:

<table class="table prettyTable">
@{Html.RenderPartial((string)ViewBag.PartialToLoad, Model);}
</table>

FURTHER EDIT: I found that although the above worked with IEnumerable it did not with @model dynamic. I discovered that one can call RenderPartial this way, which works in this instance.

@{RenderPartialExtensions.RenderPartial(Html, (string)ViewBag.PartialToLoad, Model);}

where PartialToLoad in the ViewBag is set in the controller.

Upvotes: 3

Views: 5050

Answers (1)

Adas Petrovas
Adas Petrovas

Reputation: 575

You have 3 options here:

  1. use dynamic model, i.e. @model IEnumerable<dynamic>
  2. Implement some common interface on your models and use it @model IEnumerable<IYourCommonInterface>
  3. Inherit all your models from some common class, like emre nevayeshirazi commented, @model IEnumerable<YourBaseClass>.

It does not matter will you pass your model like Model, or you put it in the ViewBag, you will need one of the above methods to access common methods.

Upvotes: 2

Related Questions