mz1378
mz1378

Reputation: 2582

How to detect a full page Refresh/Reload in Blazor

I am trying to detect a page refresh in Blazor, So that before the refresh occures, I save some data to local storage, I tried Dispose, But the services that I get Data to save are not available at this stage. I also tried JavaScript's window.onbeforeunload and calling a C# method when this occures as follows:

public static class SessionSaver
{
    [JSInvokable]
    public static Task SaveServicesToSession()
    {
        ViewDataService viewData = (ViewDataService)GetMeSomeServiceLocator.Instance.GetService(typeof(ViewDataService));           
        ProtectedBrowserStorage protectedBrowserStorage = (ProtectedBrowserStorage)GetMeSomeServiceLocator.Instance.GetService(typeof(ProtectedSessionStorage));
        protectedBrowserStorage.SetAsync("ViewData", viewData);
        protectedBrowserStorage.SetAsync("AuthModel", viewData.AuthModel);            
        return Task.FromResult("Success.");
    }
}

Javascript:

 window.onbeforeunload  = () => {
        DotNet.invokeMethodAsync('BlazorStore9', 'SaveServicesToSession')
            .then(message => { console.log(message); });
        }

Startup.cs: a nested class:

 public static class GetMeSomeServiceLocator
    {
        public static IServiceProvider Instance { get; set; }
    }

and in the configure method:

GetMeSomeServiceLocator.Instance = app.ApplicationServices;

The JsInvokable is called when I reload the page but I get error:

System.InvalidOperationException: 'Cannot resolve scoped service 'BlazorStore9.Services.ViewDataService' from root provider.'

Is there anything can be done to solve this problem?

Upvotes: 2

Views: 10300

Answers (2)

Sharif Yazdian
Sharif Yazdian

Reputation: 4718

According to Microsoft Document you can recognize the first render using the OnAfterRender or OnAfterRenderAsync methods with firstRender parameter.

 protected override void OnAfterRender(bool firstRender)
{
  ...} 

Upvotes: 0

devbf
devbf

Reputation: 561

Based on the comments from @Mister Magoo and @mz1378 and this Microsoft documentation, I created a solution which worked for me. To call C# functions from a HTML attribute (like onBeforeUnload) you have to use JavaScript.

Let´s create a java script function named callDotNetFunctionFromJS like this (I created mine in a file named callDotNetFunctionFromJS.js which I saved in the wwwroot folder of the client project):

function callDotNetFunctionFromJS(functionName) {
    DotNet.invokeMethod('YourProjectName.Client', functionName);
}

Then create the function you want to call :

[JSInvokable]
public static void PageAboutToBeReloaded()
{
    Console.WriteLine("Page will be refreshed");
}

Important: Don´t forget to add [JSInvokable], else the C# function can´t be called from the java script function. Also the method has to be static. If your method is non-static, please see my edit below.

In your .razor-file let´s add something like this:

<body onbeforeunload="callDotNetFunctionFromJS('PageAboutToBeReloaded')"></body>

Last but not least you have to add a reference to your .js-file to the index.html:

<script src="callDotNetFunctionFromJS.js"></script>

Now if you refresh the page where you want to be notified, you should see the output "Page will be refreshed". Pro tip: Activate Preserve log in the settings of the browser console to prevent the console to clear after refresh.

EDIT: If you want to call a non-static method, here you go:

The PageAboutToBeReloaded method has to look like this:

[JSInvokable]
public static void PageAboutToBeReloaded()
{
   callNonStaticFunction.Invoke();
}

For this to work, you have to add an Action at the top:

private static Action callNonStaticFunction;

Your OnInitialized() should look like this:

protected override void OnInitialized()
{
    callNonStaticFunction = NonStaticFunction;
}

Now you can implement a non-static method to be called on page refresh:

void NonStaticFunction()
{
    Console.WriteLine("DEBUG: huhu");
}

Upvotes: 4

Related Questions