Blazor调用NotifyAuthenticationStateChanged后抛出异常问题排查
问题描述
使用.NET 8与Chrome浏览器,运行应用后首次调用自定义AuthenticationStateProvider的AuthenticateUser方法,调用NotifyAuthenticationStateChanged后,浏览器日志出现如下异常:
blazor.web.js:1 [2023-12-07T18:37:52.343Z] Error: System.InvalidOperationException: Collection was modified; enumeration operation may not execute. at System.Collections.Generic.List`1.Enumerator.MoveNext() at Microsoft.AspNetCore.Components.CascadingValueSource`1.<>c__DisplayClass10_0.<NotifyChangedAsync>b__0() at Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContextDispatcher.InvokeAsync(Action workItem) at Microsoft.AspNetCore.Components.CascadingValueSource`1.NotifyChangedAsync() at Microsoft.Extensions.DependencyInjection.CascadingAuthenticationStateServiceCollectionExtensions.AuthenticationStateCascadingValueSource.HandleAuthenticationStateChanged(Task`1 newAuthStateTask) at PortableMemory.UI.Services.Authentication.Implementations.AppAuthenticationStateProvider.AuthenticateUser(AuthenticationModel authModel) in D:\d\PortableMemory\PortableMemory.UI\PortableMemory.UI\Services\Authentication\Implementations\AppAuthenticationStateProvider.cs:line 38 at PortableMemory.UI.Components.Login.LoginComponent.OnSubmit() in D:\d\PortableMemory\PortableMemory.UI\PortableMemory.UI\Components\Login\LoginComponent.razor.cs:line 34 at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task) at Microsoft.AspNetCore.Components.Forms.EditForm.HandleSubmitAsync() at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task) at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
自定义AuthenticationStateProvider实现代码:
public class AppAuthenticationStateProvider : AuthenticationStateProvider { public override Task<AuthenticationState> GetAuthenticationStateAsync() { var identity = new ClaimsIdentity(); var user = new ClaimsPrincipal(identity); return Task.FromResult(new AuthenticationState(user)); } public void AuthenticateUser(AuthenticationModel authModel) { var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, "bob"), }, "Custom Authentication"); var user = new ClaimsPrincipal(identity); NotifyAuthenticationStateChanged( Task.FromResult(new AuthenticationState(user))); } }
异常原因
这个异常的核心原因是:你在组件的同步提交流程(EditForm的OnSubmit方法)中,同步调用了NotifyAuthenticationStateChanged,触发了级联AuthenticationState的更新。此时Blazor内部正在枚举依赖该级联值的组件订阅列表,而更新过程中这个列表因为组件的重新渲染、订阅状态变更被修改,导致枚举操作与集合修改操作冲突,从而抛出"集合被修改;枚举操作可能无法执行"的异常。
简单来说,就是状态变更的时机和Blazor内部的组件枚举流程重叠,引发了集合操作的冲突。
内容的提问来源于stack exchange,提问作者Masteroxify
相关产品推荐
相关产品推荐

