Search code examples
c#blazortelerik-blazor

IEnumerable property issue using API call - Blazor Telerik


I have created a Blazor project using Telerik's built in extension.

Below is my code:

<div class="tableeee"
    <table cellpadding="0" cellspacing="0">
    <tr>
        <th>Forename</th>
        <th>Surname</th>
        <th>Username</th>
    </tr>
    @foreach (UvwUser uuser in Users)
    {
            <tr>
                <td>@uuser.Forename</td>
                <td>@uuser.Surname</td>
                <td>@uuser.Username</td>
            </tr>
    }
</table>
</div>

@code {

public string _URL = String.Empty;
//UvwUser Users { get; set; }

IEnumerable<UvwUser> Users { get; set; }



public UvwUser user = new UvwUser();

EditContext userEditContext { get; set; }

protected async override void OnInitialized()
{
    userEditContext = new EditContext(user);

    _URL = settingsAccessor.AllClientSettings().BaseServiceURI;

    Users = (await http.CreateClient("ClientSettings").GetFromJsonAsync<List<UvwUser>>($"{_URL}/api/lookup/User"))
        .OrderBy(t => t.Username)
        .ToList();

}

This is just a dummy app, Users in OnInitialized() is my call to the API. It returns 2x records which consist of columns PK, Forename, Surname & Username. I want to populate the table in the above code. My Users IEnumerable that I'm trying to get & set returns a value of null even though it sets to the values in my API call. Its as if outside of my OnInitialized() there's no communication. so I get the below error, as expected:

System.NullReferenceException: 'Object reference not set to an instance of an object.'

I use override on this method as it has its own build in method which I don't want to use

EDIT:

After further debugging I have found this is an OnInitialized issue. I'm still trying to figure out why but its as if the UI loads before the OnInitialized which is causing the issue


Solution

  • Since HttpClient.GetFromJsonAsync() is an async operation, it may be null when the razor component initializes. Try to wrap it with a conditional like so:

    @if(Users is not null)
    {
        foreach (UvwUser uuser in Users)
        {
            <tr>
                <td>@uuser.Forename</td>
                <td>@uuser.Surname</td>
                <td>@uuser.Username</td>
            </tr>
        }
    }
    

    Razor component, notice the method signature it returns a Task:

    protected override async Task OnInitializedAsync()
            {
                userEditContext = new EditContext(user);
    
                _URL = settingsAccessor.AllClientSettings().BaseServiceURI;
    
                 Users = (await http.CreateClient("ClientSettings").GetFromJsonAsync<List<UvwUser>>($"{_URL}/api/lookup/User"))
                         .OrderBy(t => t.Username)
                         .ToList();
            }