'How to load razor page before it's done rendering?

I have a table of records in Index.cshtml, once a user clicks on a record to view the details it will take them to Details.cshtml.

The issue is, there is a lot of data being pulled and the page has a slow response time. I would like to add a loading spinner but the page doesn't switch, it just stays on Index.cshtml until all the data is loaded from the OnGet in Details.cshtml then it switches the page fully loaded/rendered.

How do I get my application to jump to Details.cshtml once a user clicks a record, have my loading spinner display, and then finish loading page. I don't want the user to be sitting waiting at the Index page.

Index.cshtml

<a asp-page="/Details" asp-route-id="@Person.id">Select</a>

Details.cshtml.cs,

//simplified  

public async Task<IActionResult> OnGetAsync(int? id)
{
 var data = await _dataService.GetData(id); 
 return Page(); 
}


Solution 1:[1]

I would proceed in the following manner.

Step 1: are you sure that your data access code is optimized ?

What can you do here:

  • check the query you are actually doing. Are you using an index ? If not, try to add an index and check if it helps in reducing the execution time. You can use the database tooling to check the actual query execution plan (I don't know what kind of database you are using, but any commonly used professional database offer some sort of tooling to check a query execution plan).
  • are you loading the minimum amount of fields that you need ? Sometimes people tend to write something like SELECT * FROM MyTable and end up loading all the 35 fields they have defined in MyTable when they actually need 2 or 3 of them.
  • have you considered caching the query result ? I would do this only after trying to optimize the query, in the way explained above. Sometimes data can be cached because they don't become stale, or it is acceptable to have stale data. This depends on your use case of course. Some other times it is possible to cache data and invalidate the cache when data changes and become stale.

Step 2: do you really need to show all the entire result set to the user ?

Sometimes we create web pages where we show 1000 record of data to the user. Most of the times this is useless: how many times you navigated to the second page of results of a Google search ? I mean that you can consider to show your users only the first 10 items and offer them a load more button, or a pagination system or a way to filter their search in order to reduce the result set.

Step 3: are you doing a lot of joins to load your data ?

Maybe you need to prepare a read model which is exactly 1:1 with the data that you need to show in your view, so that you can run a plain and simple query on it (no joins at all) and you are able to fetch the data in a quick and simple way. Consider exploring the CQRS architectural pattern.

Step 4: you can evaluate to load the data client side, in order to quickly show something to the user and let the actual data to load lazily, in the user browser.

To do this, you need to move a great amount of your page rending to the client, by using an AJAX request and some Javascript.

If all of your application is rendered server side and you are working from a Razor Page or an MVC project, I would avoid to do this. It's a complete different paradigm and, in any case, you need to optimize your data access code and review the amount of data that you want to load for the user.

In my opinion Step 1 and Step 2 are enough in the majority of cases.

Solution 2:[2]

You can try to use a partial page and js,use js to call the partial page,and pass the id to it,then use await _dataService.GetData(id);:

Details.cshtml:

<div id="content"></div>
@section Scripts{ 

    <script>
        $(function () {
            $.ajax({
                type: "GET",
                url: '[email protected]',
            }).done(function (result) {
                document.getElementById("content").innerHTML = result;
            })
        })
    </script>
}

Details.cshtml.cs:

[BindProperty]
public int ID { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
 ID = id;
 return Page(); 
}

Index2.cshtml.cs:

public IActionResult OnGet(int? id)
        {
            var data = await _dataService.GetData(id); 
            return Page();
        }

Update: If you don't want to return the layout elements,try to add the following code to Index2.cshtml:

@{
    Layout=null; 
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2