How to store session data in server-side blazor

Codo picture Codo · Dec 24, 2018 · Viewed 22.8k times · Source

In a server-side Blazor app I'd like to store some state that is retained between page navigation. How can I do it?

Regular ASP.NET Core session state does not seem to be available as most likely the following note in Session and app sate in ASP.NET Core applies:

Session isn't supported in SignalR apps because a SignalR Hub may execute independent of an HTTP context. For example, this can occur when a long polling request is held open by a hub beyond the lifetime of the request's HTTP context.

The GitHub issue Add support to SignalR for Session mentions that you can use Context.Items. But I have no idea how to use it, i.e. I don't know hot to access the HubConnectionContext instance.

What are my options for session state?

Answer

Codo picture Codo · Dec 26, 2018

Note: This answer is from December 2018 when an early version of Server-side Blazor was available. Most likely, it is no longer relevant.

The poor man's approach to state is a hinted by @JohnB: Use a scoped service. In server-side Blazor, scoped service as tied to the SignalR connection. This is the closest thing to a session you can get. It's certainly private to a single user. But it's also easily lost. Reloading the page or modifying the URL in the browser's address list loads start a new SignalR connection, creates a new service instance and thereby loses the state.

So first create the state service:

public class SessionState
{
    public string SomeProperty { get; set; }
    public int AnotherProperty { get; set; }
}

Then configure the service in the Startup class of the App project (not server project):

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<SessionState>();
    }

    public void Configure(IBlazorApplicationBuilder app)
    {
        app.AddComponent<Main>("app");
    }
}

Now you can inject the state into any Blazor page:

@inject SessionState state

 <p>@state.SomeProperty</p>
 <p>@state.AnotherProperty</p>

Better solutions are still super welcome.