I need an equivalent of Blazor-Server Server-Side session support, that behaves just like Cookie sessions in razor pages and works across multiple tabs.How I can achieve this? Is this so unique that I really have to roll my own?
This question comes up often, and the answers "don't" or "can't". I'm not really satisfied with that because it is possible (albeit not easily) and my customers want and expect it.
My Customer Need:I want a simple option, very similar to "theme Dark Mode" in the FluentBlazor demo.When changed on page, all open pages/tabs/windows from that client update immediately.The scope for sharing state + synchronization is exactly the scope offered by cookies.
What I have looked into:I understand the technical architecture of Blazor, the http pipelines, the SignalR circuits, the browser storage using sessionStorage etc. The Microsoft Learn pages cover a lot of details but none of them provide a usable solution. I also understand well the DI scopes in blazor and their limitations.
The sessionStorage is quite limited because it doesn't work until JSInterop is up. It is way more complicated than just sharing a cookie.
I understand the implications of scaling-out. But this is a real project and we need quick solutions now, with knowledge we can restructure the solution to use distributed cache and some message when (if) we grow.
My Planned Solution:This is what I am about to write, but it seems excessive and I'm surprised it is not already done:
Write some custom middleware, early in the pipeline, to find (or create) a
SessionID
cookie.Write a custom circuit handler to transfer that
SessionID
over to the SignalR circuit handler. I think I need to store it in thecurcuit.Items
dictionary.Create an interface to be injected into each page to access the options
IMySessionOptions { public bool IsDarkMode{get;set;} }
Create a class MySessionOptions. This will somehow obtain the session ID from either the httpContext or the SignalR circuit. I think one of those should always be available.
The MySessionOptions can then use some standard in-memory cache & event notification service to synchronize between scopes/circuits. It just needs the shared session key.