John S
John S

Reputation: 8331

MVC Html.DisplayNameFor on a complex model

I have a model with a complex type i.e. User/Addresses/List of Addresses

public class User{
public List<Address> Addresses{get;set;}
}

On my View I am displaying this

<fieldset><legend>@Html.DisplayNameFor(model=>model.Addresses)</legend>
<table>       
<tr>
    <th>
        @Html.DisplayNameFor(m => Model.Addresses.Street)
    </th>
    <th>
        @Html.DisplayNameFor(model => model.Addresses.City)
    </th>
<th>
        @Html.DisplayNameFor(model => model.Addresses.State)
    </th>

    </tr>
@foreach (var item in Model.Addresses) {    
<tr>
    <td>
        @Html.DisplayFor(m => item.Street)
    </td>
    <td>
        @Html.DisplayFor(m => item.City)
    </td>
    <td>
        @Html.DisplayFor(m => item.State)
    </td>
</tr>
} 
    </table></fieldset>

The DisplayNameFor Street/City/State do not work.

What is the proper way to get the DisplayNameFor on a sub object?

TIA J

Upvotes: 9

Views: 10908

Answers (6)

Amal K
Amal K

Reputation: 4854

In ASP.NET Core, Html.DisplayNameForInnerType() can be used instead:

@Html.DisplayNameForInnerType((Address address) => address.Street)

This can be used both when your current model represents a collection as well as when you want the display name of the properties of an inner model.

However, it is required that you specify the lambda expression parameter's type explicitly (Address address).

Upvotes: 4

John S
John S

Reputation: 8331

I changed

@Html.DisplayNameFor(m => Model.Addresses.Street)

to

@Html.DisplayNameFor(m => Model.Addresses.FirstOrDefault().Street)

Do not use @Html.DisplayNameFor(m => Model.Addresses[0].Street) because if you need to edit the first row, you won't be able this way.

Everything works as expected now.

Upvotes: 12

Bellash
Bellash

Reputation: 8184

To display name for the adress property, you may define an empty Adress model

{
  var adress =new Models.Address();
}

and use it like this

 @Html.DisplayNameFor(m => adress.Street)

Upvotes: 0

antarias
antarias

Reputation: 19

This could be better:

@Html.DisplayNameFor(m => Model.Addresses.FirstOrDefault().Street)

will also work in case the list is empty

Upvotes: 1

0xC0DED00D
0xC0DED00D

Reputation: 20348

You can also use the Linq to avoid the indexing error. I used this is my code -

@Html.DisplayNameFor(m => Model.Addresses.first().Street)

And the following error went away.

Cannot apply indexing with [] to an expression of type 'System.Data.Objects.DataClasses.EntityCollection<Address>

However it's better to use the Name directly using the following statement

@Html.DisplayName("Street")

Upvotes: 1

VJAI
VJAI

Reputation: 32758

The way you are using DisplayNameFor is wrong. Addresses is a list and it doesn't have properties like Street, City, State. So how you expect the name to get displayed.

Isn't that simple directly using the names in the view instead of using helper in this case.

Upvotes: -1

Related Questions