InvalidOperationException in Blazor 8 state manager #3749
Replies: 10 comments
-
@mtavares628 I did the following:
I am not seeing any exceptions in the console or host window where the web server is running. How are you seeing these exceptions? |
Beta Was this translation helpful? Give feedback.
-
I'm seeing them in the Output Window when Debugging: |
Beta Was this translation helpful? Give feedback.
-
I wonder what is different in your app from my test. My config: builder.Services.AddCsla(o=>o
.AddAspNetCore()
.AddServerSideBlazor()); My pages: @inject Csla.Blazor.State.StateManager stateManager
...
protected override async Task OnInitializedAsync()
{
await stateManager.InitializeAsync();
} Because I (and you?) have no wasm pages, at no point should session be "checked out" and so at no point should the task completion source code even be invoked. Are you seeing the exceptions as a result of a data portal call, or something else? |
Beta Was this translation helpful? Give feedback.
-
It appears to be happening in LocalProxy.cs on line 40 of InitializeContext where it tries to get the ApplicationContext: private void InitializeContext(out IDataPortalServer _portal, out IServiceScope _logicalServerScope, out ApplicationContext _logicalServerApplicationContext)
{
IServiceProvider provider = CallerApplicationContext.CurrentServiceProvider;
if (Options.UseLocalScope && CallerApplicationContext.LogicalExecutionLocation == ApplicationContext.LogicalExecutionLocations.Client && CallerApplicationContext.IsAStatefulContextManager)
{
_logicalServerScope = CallerApplicationContext.CurrentServiceProvider.CreateScope();
provider = _logicalServerScope.ServiceProvider;
provider.GetRequiredService<IRuntimeInfo>().LocalProxyNewScopeExists = true;
}
else
{
_logicalServerScope = null;
}
_logicalServerApplicationContext = provider.GetRequiredService<ApplicationContext>();
_portal = provider.GetRequiredService<IDataPortalServer>();
} If you are around, I can show you, just let me know. |
Beta Was this translation helpful? Give feedback.
-
@mtavares628 I am available for about an hour - waiting for a flight to board. Meet me on Discord? |
Beta Was this translation helpful? Give feedback.
-
@rockfordlhotka So I've been troubleshooting further and it seems that it definitely has something to do with the scoped service provider in that InitializeContext method of LocalProxy. When I look at the state of _logicalServerApplicationContext in that method, the Identity of the ClaimsPrincipal is null. I'm not sure why. But if I use the existing CallerApplicationContext service provider to get the _logicalServerApplicationContext, then the Identity is there. In tracking why my application worked in a prior pre-release, it looks like the pull request which changed things appears to be #3632 in particular this commit from it: d3aa7cc This was where IntializeContext was changed. |
Beta Was this translation helpful? Give feedback.
-
If it has something todo with the |
Beta Was this translation helpful? Give feedback.
-
@StefanOssendorf - In performing more testing, I don't think the issue has anything to do with the StateManager code with TaskCompletionSource in it. @rockfordlhotka - I've dug a little deeper and the inner message of the InvalidOperationException is:
I've traced this to me using a custom AuthenticationStateProvider that inherits from ServerAuthenticationStateProvider. All I'm doing with it is adding in roles as claims: public class DadAuthenticationStateProvider : ServerAuthenticationStateProvider
{
private IUserRoleStore<DadUser> _roleStore;
public DadAuthenticationStateProvider(IUserRoleStore<DadUser> roleStore)
{
_roleStore = roleStore;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var authState = await base.GetAuthenticationStateAsync();
if (authState.User.Identity != null && authState.User.Identity.IsAuthenticated)
{
var identity = (ClaimsIdentity)authState.User.Identity;
int UserId;
if (int.TryParse(identity.FindFirst("sub")?.Value, out UserId))
{
var roleList = (List<string>)(await _roleStore.GetRolesAsync(new DadUser() { Id = UserId }, new CancellationToken(false)));
foreach (string item in roleList)
{
if (!identity.HasClaim("role", item))
{
identity.AddClaim(new Claim("role", item));
}
}
}
}
return authState;
}
} The exception is actually being thrown In the InitializeUser method of ApplicationContextManagerInMemory.cs: private void InitializeUser()
{
Task<AuthenticationState> task = default;
try
{
task = AuthenticationStateProvider.GetAuthenticationStateAsync();
}
catch (InvalidOperationException ex)
{
task = Task.FromResult(new AuthenticationState((ClaimsPrincipal)UnauthenticatedPrincipal));
string message = ex.Message;
if (message.Contains(nameof(AuthenticationStateProvider.GetAuthenticationStateAsync))
&& message.Contains(nameof(IHostEnvironmentAuthenticationStateProvider.SetAuthenticationState)))
{
SetHostPrincipal(task);
}
else
{
throw;
}
}
AuthenticationStateProvider_AuthenticationStateChanged(task);
} While it does have a try-catch for an InvalidOperationException to check for this specific error, the catch isn't being hit because it is being captured within the task object and not immediately thrown at that point. The solution to that would be to use async/await in the method, but unfortunately, this method is being called in the constructor, so running an async method isn't recommended. I also want to note that it does catch the exception if we are not adding a custom scoped AuthenticationStateProvider to the service model and stick with the default one. Essentially, I see 2 issues to solve here:
|
Beta Was this translation helpful? Give feedback.
-
I don't think this is a CSLA issue, so I'm moving this to a discussion instead of an issue. |
Beta Was this translation helpful? Give feedback.
-
Should be fixed in #3964 |
Beta Was this translation helpful? Give feedback.
-
@rockfordlhotka Upon further research, I think the errors are related to the new StateManager using TaskCompletionSource. A google search turned up this info:
I'm not sure how to troubleshoot this further, since I'm not that familiar with this new StateManager. Any guidance is appreciated.
Originally posted by @mtavares628 in #3647 (reply in thread)
Beta Was this translation helpful? Give feedback.
All reactions