Hey I´m currently working on a blazor-server-app and encountered a problem.
I´m using the protected session storage to save my data. If the value of a key exceeds a certain amount of characters (34160) the circuit starts attempt to reconnect and recovers. However the application is in a frozen state.
I try to access the storage inside the OnInitializedAsync method.
protected override async Task OnInitializedAsync()
{
Warenkorb = await SessionStorageService.GetNotNull<Warenkorb>( SessionStorageKeys.WarenkorbKey );
}
Inside the SessionStorageService:
public async Task<T> GetNotNull<T>( string key )
{
ProtectedBrowserStorageResult<string> result = await protectedSessionStorage.GetAsync<string>( key );
}
Debugger stops at "GetAsync(key)"
Is there any explanation for this? Thanks
I could not find an explanation, but since I faced same problem I ended up with next workaround:
Create a Session class with a Guid Id and any other properties you might need as session state:
public class Session
{
public Guid Id { get; set; }
public int Counter { get; set; }
}
Create an application state class to maintain a collection of Sessions:
public class AppState
{
public List<Session> Sessions { get; set; } = new();
public Session AddSession() {
var retval = new Session();
Sessions.Add(retval);
return retval;
}
public Session? Session(Guid? sessionId) => Sessions.FirstOrDefault(x => x.Guid == sessionId);
}
Register it on Program.cs as a Singleton service:
var state = new TestState.Shared.AppState(http);
builder.Services.AddSingleton(sp => state);
Create a SessionProvider component which will create a new session n AppState if missing and persist it's Id on the Protected Session Storage:
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inject ProtectedSessionStorage ProtectedSessionStore
@inject AppState AppState
@if (isLoaded)
{
<CascadingValue Value="@this">
@ChildContent
</CascadingValue>
}
else
{
<p>Loading...</p>
}
@code {
[Parameter] public RenderFragment? ChildContent { get; set; }
public Session? Session { get; set; }
public bool isLoaded;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var result = await ProtectedSessionStore.GetAsync<Guid>("sessionId");
if (result.Success)
Session = AppState.Session(result.Value);
else
{
Session = AppState.AddSession();
await ProtectedSessionStore.SetAsync("sessionId", Session.Guid);
}
isLoaded = true;
StateHasChanged();
}
}
}
Wrap App.razor Router component with SessionProvider:
<SessionProvider>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</SessionProvider>
Access Session properties from any page:
@page "/counter"
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<div>session id: @sessionProvider?.Session?.Id.ToString()</div>
<p role="status">Current count: @sessionProvider?.Session?.Counter</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
[CascadingParameter] public SessionProvider? sessionProvider { get; set; }
private void IncrementCount()
{
if (sessionProvider?.Session != null)
sessionProvider.Session.Counter++;
}
}