0

I have a partial view, in my ASP.NET MVC4 web app. It's just a partial view designed to display a table, given a collection of entities. It looks like this:

@model ICollection<Portal.Models.Matter>

<table class="table table-striped table-bordered table-hover">
    <thead>
        <tr>
            <th>Name</th>
            <th>Last Accessed</th>
            <th>Client</th>
        </tr>
    </thead>
    <tbody>

        @if (Model.Count > 0)
        {
            @Html.DisplayForModel()
        }
        else
        {
            <tr>
                <td colspan="3" class="text-muted text-centered">There are no Matters to display.</td>
            </tr>
        }

    </tbody>
</table>

I have a DisplayTemplate for Matter that is statically typed to the single Matter entity, and it handles rendering of each table row.

For some reason, when this partial is rendered, instead of using the Matter DisplayTemplate it just shows the following:

System.Collections.Generic.List`1[Portal.Models.Account]System.Collections.Generic.List`1[Portal.Models.Account]

Now, this partial is not even bound to a collection of Account entities. It's bound to a collection of Matter entities. So, why is @Html.DisplayForModel() trying to display for a collection of Accounts? At run time, using a debugger, I can see the Model is in fact a collection of Matter entities, not Account.

I render this partial using the following code:

@Html.Partial("~/Views/Matter/_Table.cshtml", Model.Client.Matters, new ViewDataDictionary())
Ryan
  • 867
  • 9
  • 23
  • Why do you pass the Partial an empty `ViewDataDictionary`? – keeehlan Oct 30 '13 at 18:23
  • I was just testing it. With or without that, the same thing occurs. – Ryan Oct 30 '13 at 18:26
  • Is it possible for you to post a screenshot of all the files you have in your `~/Views/Shared/DisplayTemplates` folder? – keeehlan Oct 30 '13 at 18:27
  • Sure, [screen shot is here](http://i.imgur.com/PLFvlGS.png). – Ryan Oct 30 '13 at 18:32
  • For partials to be used by other views, outside of the controller's named folder, do they have to be in the Shared folder? – Ryan Oct 30 '13 at 19:11
  • Let me try to explain this as best I can. Say I have a View Model, `MyViewModel`. If I wanted to use `@Html.DisplayForModel()`, I would need to have a Partial View in my `~/Views/Shared/DisplayTemplates/` folder with the filename `MyViewModel.cshtml`. MVC is built to be able to automatically match up the type of your View Model with its corresponding Display Template, as long as the View Model's type name has the same name as the file in your `/DisplayTemplates` folder. The same concept applies to the `/EditorTemplates` folder, which is just as useful. – keeehlan Oct 30 '13 at 20:14
  • If you were to use `@Html.DisplayForModel()` on a View Model that does *not* have a template ready for use, MVC would automatically generate one based on every last property that the View Model has available, and it's usually laid out in a format that's less than preferable. – keeehlan Oct 30 '13 at 20:15
  • Also, now that I realize it, your Display Templates must *always* be in `~/Views/Shared/DisplayTemplates/`. Same for Editor Templates. – keeehlan Oct 30 '13 at 20:17
  • See http://stackoverflow.com/questions/8002059/asp-net-mvc-display-template-for-a-collection – haim770 Oct 30 '13 at 20:21

1 Answers1

0

I found a work around, or maybe a solution, not sure. Anyway, instead of using DisplayForModel on an ICollection, I iterate over the collection and use DisplayFor on each element.

For example ...

@model ICollection<Foo>

for (var item in Model)
{
    @Html.DisplayFor(m => item)
}

I guess nothing is forcing you to use a property off of m in DisplayFor.

Ryan
  • 867
  • 9
  • 23