How to display a loading icon when logging into Blazor server application?

Viewed 300

I have a Blazor server application (great) with a Razor page login form (absolute pain in my backside).

Upon submitting the login form, in the PageModel class I have an OnPostAsync method which calls upon my API to sign in and obtain an auth token, but obviously there is an element of delay to this (quite bad in my case at the moment). As it is, my page shows almost no indication that it is doing anything at all after pressing login, whilst the API is being contacted the page sits there like the submit button hasn't even been pressed, which is obviously very bad for users because the first thing they will do is mash the submit button until they get a visual response (as I probably would to be fair).

How on earth do I do this in a Razor page? I've tried this and this, neither have worked. At the moment I don't particularly care what is shown or done, I just want it to do SOMETHING. The perfect solution for me is disabling the form and/or overlaying something to show that it's busy, but I'd take a basic "Loading..." message somewhere.

Is there any way of doing this?

1 Answers

It seems that it simply isn't possible to do with a Razor page in a Blazor server application, because there is nothing to update the UI, it's not like a Blazor component where there is a SignalR connection kept active between the server and the client. In the case of the login page, the page is served to the client and the connection is then severed, so the next action that occurs is the page submits the details it's holding to the server and expects the login result as a response.

Javascript should have worked and I don't know why it didn't, I added a script to change some of the UI elements upon submission of the form, but it seems the OnPostAsync method in the PageModel was being called first and whether the script was running or not it just wasn't updating the UI, I'm guessing because it's awaiting the response before doing anything. The alternative was to remove the login code from the PageModel and use an AJAX call instead, but I didn't really want to do this.

I've added an ILoginHandlerService, with a StoreLogin and RetrieveLogin. In the implementation it receives a login object containing the credentials, encrypts them and stores them in a private variable. This service is added as a singleton in the app startup class. The login page now calls the StoreLogin method with the submitted details, and redirects to a new "Logging in" page. This new page has a "form" with just a text element containing a please wait message, and a script which calls Post on the form upon loading.

The "Logging in" page's OnPostAsync is what actually performs the login. It calls upon an injected IAuthService to log in, without passing any details to it. The IAuthService implementation itself (added as a scoped service in app startup) gets injected with the ILoginHandlerService, then internally calls upon that service to supply the stored login object. The stored object is decrypted, nulled and returned to the IAuthService and is then submitted to my API, which then responds with the logged-in user token, that is returned to the "Logging in" page, which then calls upon HttpContext.SignInAsync, adding the received API token, and redirects the user to the home page, signed in.

This seems very convoluted to me and I'm not entirely sure it's correct. From what I understand of the above, once the credentials are submitted from the login form all future processing of the credentials should now be done server side and are never returned back to the client?

Related