MarimerLLC / csla

A home for your business logic in any .NET application.
https://cslanet.com
MIT License
1.23k stars 394 forks source link

Can I get SIR only behavior added back to ApplicationContextManagerInMemory #3990

Closed swegele closed 1 month ago

swegele commented 1 month ago

See this comment: https://github.com/MarimerLLC/csla/issues/3990#issuecomment-2137969242


@rockylhotka - this is regarding the SetUser issue we discussed yesterday on discord. I cannot use a .cshtml file as suggested. After sleeping on it, I realized this is related to the cookies shared across browser tabs issue. I should not have that forced upon my app by requiring HttpContext. Let me try to explain as briefly as possible:

Our large Blazor app created in .net 6 and recently upgraded to .net 8 is 100% SIR only (required as will be seen). We have no context switching beyond the requisite one at startup when a circuit starts in app.razor.

A static UserCircuitTracker service keeps track of all circuits, their associated user, and whether a circuit is a root or child. A root login or circuit is a tab/circuit where a user performs a unique login. Whereas, a child tab/circuit is one that is opened from a root (think of it like your original tab opens a popup or popout tab). No cookies are involved. Nothing is shared across browser tabs.

Because of this, our app can offer some very powerful features:

This is a very powerful feature but it requires SIR only. It breaks if I were to start using cookies or SSR or WASM (which I obviously will not do)

With that as the back-drop, I come to the point how <= 8.1.0 AppContextManager allowed me to SetUser. IMHO this is a completely valid scenario. It rightly only sets the ClaimsPrincipal in memory and not in HTTPContext. In my circuits, per all the MS docs, I don't use HTTPContext beyond a read-only list of values (e.g. header values) like for knowing the user's preferred culture code. I grab those values at circuit startup time.

So now in .NET 8 here comes Microsoft saying you shouldn't set User outside of a component. Why? To accommodate our cool new feature we added (forced upon you) called context switching between WASM / SIR / SSR etc. Well what if I don't want that? Too bad. It's the new norm. The new "best practice" causes me to lose a core and cool feature.

So long story long. I need the ability restored to SetUser in memory to accommodate this SIR in-memory only app scenario. I argue this is not bad behavior. given this context. Yes I can presumably copy the old ApplicationContextManagerInMemory and get the old behavior back, but now I face the risk of getting out of sync with CSLA upgrades in future.

My ask is - can I have this added back into the context manager perhaps gated behind a configuration option for SIR only scenarios or something like that?

swegele commented 1 month ago

Perhaps an option here (or something similar):

public class BlazorServerConfigurationOptions
{
  /// <summary>
  /// Gets or sets a value indicating whether the app 
  /// context manager (in memory version) should allow 
  /// the SetUser to be called without throwing exception.
  /// Only used in Blazor Server Interactive with in memory
  ///  app context manager.
  /// </summary>
  public bool AllowSetUserInMemory { get; set; } = true;

and a subsequent change in the ApplicationContextManagerInMemory class in the method SetUser(IPrincipal principal)

rockfordlhotka commented 1 month ago

I think it is reasonable for the in-memory context manager to just revert to the 8.2.0 behavior.

That context manager doesn't support the new Blazor 8 rendering capabilities in any case and so I don't see how it is a bad thing for it to continue to support a pure server-interactive environment - that's the only environment in which it is valid anyway.