Reputation: 2582
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
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
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