Tomer Something
Tomer Something

Reputation: 780

Null reference on foreach loop in Razor Page

EDIT: removing the @page annotation in the Index.cshtml fixed the problem.

When calling the page I am getting a error:

System.NullReferenceException: Object reference not set to an instance of an object. at AspNetCore.Views_Inspector_Inspect.get_Model()

Which is caused by this line: @foreach (var rule in Model.Items) Surely enough, when debugging, I see that Model is indeed null.

But I call this view using the desired object like so: return View(res);

Furthermore, getting model data using DisplayTextFor like so: <h2>@Html.DisplayTextFor(model => model.CardNumber)</h2> indeed works and displays the correct data.

What am I doing wrong here?

Full code below.

Controller:

public IActionResult Inspect() {
    var res = GetDataObject();
    return View(res);
}

Inspect.cshtml:

@page
@model mynamespace.DataObject

<style>
    table, th, td {
        border: 1px solid black;
        border-collapse: collapse;
    }
    th, td {
        padding: 5px;
        text-align: left;    
    }
</style>

<h2>@Html.DisplayTextFor(model => model.SomeItem)</h2> <!-- THIS WORKS -->


    <table class="table" style="width: 50%">
        <thead>
        <tr>
            <th>Header1</th>
            <th>Header2</th>
            <th>Header3</th>
            <th>Header4</th>
        </tr>
        </thead>
        <tbody>
            @foreach (var rule in Model.SomeCollection) <!-- Model is null -->
            {
                <tr>
                    <td>
                        @Html.DisplayTextFor(modelItem => rule.Name)
                    </td>
                </tr>
                <tr>
                    <td>
                        @Html.DisplayTextFor(modelItem => rule.Name)
                    </td>
                </tr>
                <tr>
                    <td>
                        @Html.DisplayTextFor(modelItem => rule.Name)
                    </td>
                </tr>
                <tr>
                    <td>
                        @Html.DisplayTextFor(modelItem => rule.Name)
                    </td>
                </tr>
                <tr>
                    <td>
                        @Html.DisplayTextFor(modelItem => rule.Name)
                    </td>
                </tr>
            }
        </tbody>
    </table>
</p>

Upvotes: 2

Views: 1809

Answers (2)

Aaron Bar
Aaron Bar

Reputation: 620

For those that are using Razor Pages, leave @page at the top and return IActionResult.

    public IActionResult OnGet(string id)
    {
        ID = id;
        return Page();
    }

Notice the return type is IActionResult, but the actual return is of type Page(). Behind the scenes, the page is returned with the model bound. It appears to be equivalent to:

return MyPage(this);

Upvotes: 0

Anton Toshik
Anton Toshik

Reputation: 2909

As per comment.

The solution to this problem is removing the @page keyword.

What @page does is specifies that it's a Razor Page.

Your confusion is that you think that Razor Page is the same as Razor Syntax.

The .cshtml file extensions specifies the the file can have Razor Syntax, it doesn't mean it's a Razor Page.

MVC and Razor Pages follow a different naming convention, are setup differently in the Startup.cs file and will use different folder structure.

For example a Index.cshtml razor page will get it's model from Index.cshtml.cs file method Get() which will return a Page(model).

The error occurs because the razor page doesn't expect anything from a controller, it's not meant to be served by one.

Upvotes: 2

Related Questions