Reputation: 199
I have three models: Animal, Dog and Cat.
Class Animal
public class Animal
{
}
Class Dog
public class Dog : Animal
{
}
And Class Cat
public class Dog : Animal
{
}
There alse two controllers (DogController and CatController),in each controller, there is an index action that return the view to show the list result.
Dog Controller
public class DogController : Controller
{
public DogController ()
{
}
public async Task<IActionResult> Index()
{
DogRepository IRepos = new DogRepository ();
// Get List of Dogs
IList<Animal> listDogs= await IRepos.GetListDogs();
return View(ilIst);
}
[Httpost]
public async Task<IActionResult> Add(Animal Dog)
{
....
// Add dog to Database
return RedirectToAction("Index");
}
}
Index view for Dogs
@model IEnumerable<Dog>
@{
ViewData["Title"] = "Index";
}
<div class="row">
<div class="table-responsive">
<table class="table">
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Dog_ID)
</td>
<td>
@Html.DisplayFor(modelItem => item.Dog_Name)
</td>
</tr>
}
</table>
</div>
</div>
In the index Action of the Dog Controller, the return type is IList<Animal>
and the model type in the index view is IEnumerable<Dog>
.
When the application is executed, an error is generated
An unhandled exception occurred while processing the request.
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List1[Animal]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable
1[Dog]'.
So, it is important to cast the list of Animals sent by the action in the controller to list of the Dogs type of the model in the view. How can we Cast the List of Animal to list of Dogs in the view, the @model IEnumerable as IEnumerable is not working.
The same thing in the post action, how can we cast the Dog model from the view to the Animal model in the action
Upvotes: 2
Views: 1702
Reputation: 8459
Polymorphism seems not work for page model. You can define partial views for Cat and Dog, and use child class for the partial view and use the base class as the model for the main view.
Main View (Index):
@model IEnumerable<Animal>
@{
ViewData["Title"] = "Index";
}
<div class="row">
<div class="table-responsive">
<table class="table">
<thead>
</thead>
<tbody>
@foreach (var item in Model)
{
@if (item is Dog)
{
<partial name="_DogPartial" model="item" />
}
}
</table>
</div>
</div>
Partial View (_DogPartial):
@model Dog
<tr>
<td>
@Html.DisplayFor(modelItem => Model.Dog_ID)
</td>
<td>
@Html.DisplayFor(modelItem => Model.Dog_Name)
</td>
</tr>
Upvotes: 1