2

I'm surprised why the following table finds the names correctly.

@model IEnumerable<Member>
<table class="table">
  <thead>
    <tr>
      <th>
        @Html.DisplayNameFor(model => model.LastName)
      </th>
    <tr>
    ...

The model I've set is an array of type Member so the model has no property LastName. An element in the list does! Shouldn't it be

<th>
  @Html.DisplayNameFor(model => model.First().LastName)
</th>

I never noticed that until I changed my viewmodel to

public class IndexVm
{
  public IEnumerable<Member> Members { get; set; }
}

and tried to

<th>
  @Html.DisplayNameFor(model => model.Members.LastName)
</th>

This stopped working and when I investigated, I realized that I can see why. I can't understand how it could work previously, though...

  1. Can someone explain what's up with that?
  2. Is the below the only option given my new viewmodel?
  3. How is the computer supposed to know what to display if the list is empty?

    @Html.DisplayNameFor(model => model.Members.FirstOrDefault()?.LastName)

So confused...

DonkeyBanana
  • 3,266
  • 4
  • 26
  • 65
  • 1. I guess the `model` parameter is of type `Member`. `model` is just a name and may not be of the same type as your `@model` declaration at the beginning of your view. This can be easily checked by hovering over `model` and look what the tooltip says. 2. Again, check what the type of the `model` argument is. Intellisense will show you your options. 3. It’s a [lambda expression](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions) which is parsed but not executed. As such it doesn’t matter if parts of it would return null or not. – ckuri Feb 12 '19 at 22:39
  • @ckuri Regarding (1). The model served from the controller was of the same type as the *@model*, i.e. *IEnumerable*. It's used for iterating through it producing a table. You can verify it by producing the default template from VS. – DonkeyBanana Feb 13 '19 at 21:22

1 Answers1

4

The DisplayNameFor shows the name of the property or the string defined in the display attribute for the property.For

@Html.DisplayNameFor(model => model.LastName)

, it works since model has a type of Member not IEnumerable<Member> in the lambda expression.

You could use

@Html.DisplayNameFor(model => model.Members.FirstOrDefault().LastName)

This still works even if FirstOrDefault() would return null since it uses metadata from lambda expressions internally, the LastName property itself is not accessed.

If Members is list IList<Member>, you could also use Members[0]

@Html.DisplayNameFor(model => model.Members[0].LastName)

Refer to here and here.

Ryan
  • 19,118
  • 10
  • 37
  • 53
  • Sorry for the delay. Life happened. As for your answer - thanks. I get it. I must have been temporarily retarded, I guess. Green check and +1. – DonkeyBanana Feb 20 '19 at 18:24