5
votes

I'm new to web development in general, and so I'm suspecting that i have misunderstood the core premise of razor pages.

I am trying to add a loading indicator to my page while I'm pulling data. While this could be achieved with a js promise, i was under the assumption that i could do this entirely in c# with the cshtml files.

In my controller i have a Page model looking like so:

public Boolean IsLoading { get; set; } = true;

public async Task<IActionResult> OnGetAsync()
{
    await Task.Run(() =>
    {
        Thread.Sleep(1000 * 10);
        IsLoading = false;
    });
    return Page();
}

Just something to simulate an expensive database query, and a bool to indicate when loading is done.

In my pagefile i have something looking like this:

@if (@Model.IsLoading)
{
    <div>
        <img src="~/Images/loading.gif" />
    </div>
}
else
{
    <div>
        <<Some Code Showing My Data>>
    </div>
}

I have tried multiple ways to try and update the model or redraw the page when the data pull is finished, but i have been unable to find any ways that work.

The desired behavior is to have the page show the loading symbol up until the 'database query' finished and then display the data instead.

The current behavior that i am seeing is that the page will not percent until the 'database query' has finished. So I never see the loading gif.

2
You have to keep this in mind: Razor => server-side code. As soon as you see the page in your browser, Razor no longer exists, all your logic has already ran.Camilo Terevinto
To echo what Camilo said, all the C# code runs on the server and is used to build some static HTML, which is then sent to the browser. Browsers cannot run C#, and no C# code is ever sent to the browser. The browser will just wait for the HTML to be delivered. So a long-running DB query in this context will simply cause the page to take longer to load. For your idea to work, you'd load the skeleton of the page, then use JS to make an AJAX request to a separate URL which will run the long-running query and return a result. Use JS to show/hide the loading indicator as the request starts and endsADyson

2 Answers

2
votes

Normally if the IsLoading property is true you should see the loading image. The reason you don't see it, is because IsLoading is never true. This happens because you are using the await keyword. By using that, this part of the code: return Page(); is only reached after the task has been completed. So when the Page object is returned, the IsLoading property is false.

Also, to reiterate @LosManos answer, C# cannot be executed on the client. So even if the image is shown, you still need JavaScript to query the server to check if the job has been finished and hide the image.

0
votes

Unless you are using Blazor or similar cool tech, the rule in aspnet land is "Javascript runs on the client. Dotnet/C# runs on the server." Also see the comment from ADyson.