Home > OS >  Foreach Loop in Razor Component causes await to fail
Foreach Loop in Razor Component causes await to fail

Time:08-04

I'm new to Blazor and .NET 6, but I am working on a small app. I have LiteDB storing data on the backend, and my Razor component is fetching it. The problem is that, while 80% of the time it works as expected, the other 20% of the time the data gets populated as null in the Razor component before the database call has even processed. When debugging this, I see the code get to the database call in the backend, then it jumps back to the frontend Razor component which now has a null object, and then it jumps back to the backend where the database call has now been completed. The page populates from the null object though, so the data is not there. I get an error in the console, but it's just stating that the object was not set to an instance of an object at a foreach loop in my code. Here's my code:

@page "/origin"
@page "/origin/{id:int}"
@inject HttpClient http

@if (id == null)
{
    <PageTitle>Origin Not Found</PageTitle>
    <h3>Origin Not Found</h3>
}
else
{
    <PageTitle>Origin: @origin.Name</PageTitle>
    <h3>Origin: @origin.Name</h3>

    <table >
        <tbody>
            <tr>
                <td>Description: </td>
                <td>@origin.Description</td>
            </tr>
            <tr>
                <td>Starting Health: </td>
                <td>@origin.StartingHealth</td>
            </tr>
            <tr>
                <td>Ground Movement Speed: </td>
                <td>@origin.GroundMovementSpeed</td>
            </tr>
            @foreach(var stat in @essences)
            {
                <tr>
                    <td>Essence Increase Option: </td>
                    <td>@stat</td>
                </tr>
            }
            <tr>
                <td>Origin Benefit: </td>
                <td>@origin.OriginBenefit</td>
            </tr>
        </tbody>
    </table>
}


@code {
    [Parameter]
    public int id { get; set; }
    private Origin origin = new();
    private List<Essence> essences = new();
    protected async override Task OnInitializedAsync()
    {
        var result = await http.GetFromJsonAsync<Origin>($"/api/origin/{id}");
        if(result != null)
        {
            origin = result;
            essences = result.EssenceIncreaseOptions;
        }
    }
}

Now if I remove the foreach loop (and the essence information I want there), then the code works 100% of the time. So there's something about that foreach loop that's causing it to fail 20% of the time, but I'm just not sure what. Any help would be appreciated. Thanks in advance.

CodePudding user response:

In the posted code, the only point in the foreach(var stat ...) that could yield an NRE is <td>@stat</td>

So your Essence class probably has an override ToString() that causes the null de-reference.

CodePudding user response:

What you can do is put a conditional check before the @foreach loop and when essences is null show some message saying loading etc, also, put StateHasChanged() after completion of fetching of data.

     @if(essences.Count>0)
     {
           @foreach(var stat in @essences)
            {
                <tr>
                    <td>Essence Increase Option: </td>
                    <td>@stat</td>
                </tr>
            }
     }
    else {loading data}
    

and

protected async override Task OnInitializedAsync()
    {
        var result = await http.GetFromJsonAsync<Origin>($"/api/origin/{id}");
        if(result != null)
        {
            origin = result;
            essences = result.EssenceIncreaseOptions;
            StateHasChanged();
        }
    }
  • Related