1

I'm not sure if I'm searching this incorrectly, but I can't seem to determine as to how to null check @Html.DisplayNameFor.

I have an IEnumerable<model> which has a model.Numbers model.Order and model.Time:

@Html.DisplayNameFor(Model => Model.Numbers)

etc.

I tried doing a this but VS throws an error on:

@Html.DisplayNameFor(Model => Model?.Numbers)

But I get this message when I hover over the red squiggly in VS:

An expression tree lambda may not contain a null propagating operator

I've also tried appending where() and @Html.DisplayNameFor(Model => Model.Numbers.Any()) but these do not work.

My code:

@model IEnumerable<BusinessLayer.NumbersModel>

...

<table class="table table-sm">

    <thead class="thead-dark">
        <tr>
            <th>@Html.DisplayNameFor(Model => Model.Numbers)</th>
            <th>@Html.DisplayNameFor(Model => Model.Order)</th>
            <th>@Html.DisplayNameFor(Model => Model.Time)</th>
        </tr>
    </thead>

    @foreach (var item in Model)
    {
        if (item.Numbers != null && item.Order != null && item.Time != null)
        {
            <tr>
                <td>@Html.DisplayFor(m => item.Numbers)</td>
                <td>@Html.DisplayFor(m => item.Order)</td>
                <td>@Html.DisplayFor(m => item.Time)</td>
                <td><i class="m-icon--edit"></i> @Html.ActionLink("Edit", "Edit", new { id = item.ID }, new { @class = "m-numbers__link" })</td>
                <td>
                    @using (Html.BeginForm("Delete", "Numbers", new { id = item.ID }))
                    {
                        <i class="m-icon--delete"></i> <input type="submit" value="Bin" onclick="return confirm('You are about to delete this record');" />
                    }
                </td>
            </tr>
        }
    }
</table>

Model:

public class NumbersModel
{
    public int ID { get; set; }
    public string Numbers { get; set; }
    public string Order { get; set; }
    public string Time { get; set; }
}
user1574598
  • 3,771
  • 7
  • 44
  • 67
  • What's the error you are getting? – Suresh Jun 02 '19 at 16:11
  • `An expression tree lambda may not contain a null propagating operator.` is what I get when I hover over the red squiggly line in VS with the `?` – user1574598 Jun 02 '19 at 16:12
  • You may want to read the accepted answer for this [question](https://stackoverflow.com/questions/44681362/an-expression-tree-lambda-may-not-contain-a-null-propagating-operator) – Suresh Jun 02 '19 at 16:15
  • If your `@model` is `IEnumerable`, then surely you can't call `.Numbers` etc on that. You probably have a loop on the page that enumerates the `Model`, and it's the loop variable that you pass to the lambda. – GSerg Jun 02 '19 at 16:17
  • I have a loop after I call `DisplayNameFor` three times that iterates through the models and renders the data via `DisplayFor` – user1574598 Jun 02 '19 at 16:19
  • That doesn't make sense. Can you show that part of the view, including the `@model` clause? – GSerg Jun 02 '19 at 16:21
  • Yes, I'll edit my question now. – user1574598 Jun 02 '19 at 16:22
  • I'm still not sure, but it would appear you want something like `DisplayNameFor(m => m.First().Numbers)`. – GSerg Jun 02 '19 at 16:25
  • what is the type of Model.Numbers? – Ahmed Yousif Jun 02 '19 at 16:29
  • 1) Please explain what is your expectation from this code: `DisplayNameFor(Model => Model.Numbers)` 2) Please show us the class for your Model. – CodingYoshi Jun 02 '19 at 16:29
  • I'll edit my question again - they are all strings. – user1574598 Jun 02 '19 at 16:31

1 Answers1

2

Your @model is an IEnumerable<T>. It does not have .Numbers or .Order, the objects it contains do.

DisplayNameFor() only needs to know the type of the expression to get the attribute DisplayAttribute from. The expression you pass to it does not have to calculate to a non-null instance of the object, it will not be executed for its result.

So

<thead class="thead-dark">
    <tr>
        <th>@Html.DisplayNameFor(m => m.First().Numbers)</th>
        <th>@Html.DisplayNameFor(m => m.First().Order)</th>
        <th>@Html.DisplayNameFor(m => m.First().Time)</th>
    </tr>
</thead>

This will work even if .Numbers is null, or .First() is null, or the entire Model is null.

You generally do not need to handle nulls when passing expression trees to the ASP.NET MVC helpers.

GSerg
  • 76,472
  • 17
  • 159
  • 346