Server-side Blazor state management

%3CLINGO-SUB%20id%3D%22lingo-sub-2923610%22%20slang%3D%22en-US%22%3EServer-side%20Blazor%20state%20management%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2923610%22%20slang%3D%22en-US%22%3E%3CP%3EOne%20of%20the%20more%20interesting%20things%20about%20server-side%20Blazor%20is%20that%2C%20unlike%20all%20previous%20UI%20frameworks%2C%20it%20maintains%20all%20per-user%20state%20(including%20the%20user's%20identity)%20in%20a%20dependency%20injection%20scope.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EWindows%20Forms%2C%20WPF%2C%20and%20UWP%20use%20the%20current%20thread.%20ASP.NET%20normally%20uses%20HttpContext.%20Blazor%20WebAssembly%20is%20similar%20to%20WinForms%2FWPF%20-%20a%20single%20process%20space%20for%20the%20user%20and%20app.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EBut%20server-side%20Blazor%20is%20stateful%20on%20the%20server%2C%20so%20it%20can't%20rely%20on%20HttpContext%2C%20or%20any%20specific%20thread.%20So%20the%20way%20they%20implemented%20management%20of%20things%20like%20the%20current%20user's%20principal%2Fidentity%20is%20via%20DI%20scope.%20Each%20server-side%20Blazor%20app%20is%20hosted%20in%20its%20own%20DI%20scope%2C%20and%20so%20a%20service%20added%20as%20a%20scoped%20service%20is%20exactly%20what%20is%20necessary%20to%20maintain%20any%20per-user%20information.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20downside%20to%20this%2C%20is%20that%20if%20you%20(like%20me)%20have%20any%20static%20methods%20that%2C%20for%20example%2C%20check%20the%20user's%20permissions%20based%20on%20user%20identity%20-%20well%2C%20that's%20impossible.%20It%20is%20impossible%20because%20the%20user's%20identity%20isn't%20%22ambient%22%20like%20in%20all%20other%20UI%20frameworks.%20The%20user's%20identity%20is%20only%20available%20in%20an%20_instance_%20of%20a%20type%2C%20and%20only%20if%20a%20service%20that%20has%20the%20user%20identity%20was%20injected%20into%20your%20instance!%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EAs%20a%20result%2C%20I've%20spent%20many%2C%20many%20hours%20over%20the%20past%20couple%20weeks%20rewriting%20the%20%23cslanet%20framework%20so%20it%20gets%20the%20user%20identity%20via%20DI%2C%20and%20then%20passes%20the%20identity%20around%20to%20all%20objects%20that%20need%20it%20(which%20is%20a%20lot%20-%20CSLA%20is%20primarily%20a%20rules%20engine%2C%20so%20the%20user%20identity%20is%20necessary%20all%20over%20the%20place).%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIt%20turns%20out%20that%20DI%2C%20like%20async%2Fawait%2C%20is%20like%20a%20virus.%20Once%20you%20start%20using%20it%20a%20little%2C%20pretty%20soon%20you%20find%20that%20you've%20had%20to%20rewrite%20nearly%20all%20your%20code%20to%20rely%20on%20the%20concept.%26nbsp%3B%20%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-2923610%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3Eblazor%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E%3CLINGO-SUB%20id%3D%22lingo-sub-2923806%22%20slang%3D%22en-US%22%3ERe%3A%20Server-side%20Blazor%20state%20management%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2923806%22%20slang%3D%22en-US%22%3EThe%20good%20news%20is%20the%20the%20.razor%20page%20always%20*does*%20know%20who%20the%20current%20user%20is.%3CBR%20%2F%3EWhen%20calling%20.cs%20code%2C%20yes%2C%20I%20do%20need%20to%20pass%20the%20identity%20of%20the%20current%20user.%3C%2FLINGO-BODY%3E
MVP

One of the more interesting things about server-side Blazor is that, unlike all previous UI frameworks, it maintains all per-user state (including the user's identity) in a dependency injection scope.

 

Windows Forms, WPF, and UWP use the current thread. ASP.NET normally uses HttpContext. Blazor WebAssembly is similar to WinForms/WPF - a single process space for the user and app.

 

But server-side Blazor is stateful on the server, so it can't rely on HttpContext, or any specific thread. So the way they implemented management of things like the current user's principal/identity is via DI scope. Each server-side Blazor app is hosted in its own DI scope, and so a service added as a scoped service is exactly what is necessary to maintain any per-user information.

 

The downside to this, is that if you (like me) have any static methods that, for example, check the user's permissions based on user identity - well, that's impossible. It is impossible because the user's identity isn't "ambient" like in all other UI frameworks. The user's identity is only available in an _instance_ of a type, and only if a service that has the user identity was injected into your instance!

 

As a result, I've spent many, many hours over the past couple weeks rewriting the #cslanet framework so it gets the user identity via DI, and then passes the identity around to all objects that need it (which is a lot - CSLA is primarily a rules engine, so the user identity is necessary all over the place).

 

It turns out that DI, like async/await, is like a virus. Once you start using it a little, pretty soon you find that you've had to rewrite nearly all your code to rely on the concept.   

1 Reply
The good news is the the .razor page always *does* know who the current user is.
When calling .cs code, yes, I do need to pass the identity of the current user.