Search code examples
asp.net-mvcasp.net-mvc-4razordisplay-templates

MVC Html.DisplayModelFor Expects IEnumerable, which I think I'm passing, but I get error


I am trying to use a display template (Pet.cshtml), which I have placed in ~/Views/Shared/DisplayTemplates, as per convention.

The Index action gets the IEnumerable and passes it to Index.cshtml, which passes it along to _PetTablePartial. So far, so good. However, when Html.DisplayForModel is called, I get this error:

The model item passed into the dictionary is of type 'Pet', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[Pet]'. 

But I (think) I can clearly see that the model item is in fact an IEnumerable. What am I doing wrong?

Controller: 

public ActionResult Index()
{
  return View(pet.GetPets()); // returns IEnumerable<Pet>
}

Index.cshtml:

@model IEnumerable<Pet>
{Html.RenderPartial("_PetTablePartial", Model);}
...

_PetTablePartial.cshtml:

@model IEnumerable<Pet>
@Html.DisplayForModel()

~/Shared/DisplayTemplates/Pet.cshtml:
@model IEnumerable<Pet>

<table>
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
...

Solution

  • Pet.cshtml should have a model type of Pet, because you are only dealing with a single pet here.

    DisplayTemplates automatically enumerate over a collection, and call your DisplayTemplate with a single item. That's one of their benefits. You don't need to do any enumeration.

    Just change Pet.cshtml's type to Pet

    I also suspect you don't want to have a separate table for each pet. So what you want is to create the table and header In your partial view, then only have a single data row in Pet.cshtml, because Pet.cshtml will be called multiple times, once for each row.

    PetTablePartial.cshtml:

    @model IEnumerable<Pet>
    
    <table>
        <tr>
            <th> Pet Name </th>
        </tr>
       @Html.DisplayForModel()
    </table>
    

    ~/Shared/DisplayTemplates/Pet.cshtml:

    @model Pet
    
    <tr>
        <td>@Html.DisplayFor(x => x.Name)</td>
    </tr>