简体   繁体   English

为什么 UserManager.GetUserAsync 不返回?

[英]why does UserManager.GetUserAsync not return?

why does UserManager.GetUserAsync not return?为什么 UserManager.GetUserAsync 不返回?

Property IsAdmin will be accessed in blazor UI when i click manually on About page.当我在关于页面上手动单击时,将在 blazor UI 中访问属性 IsAdmin。 I don't get why the call to GetUSerAsync does not return.我不明白为什么对 GetUSerAsync 的调用没有返回。 Any clues or mistakes?有什么线索或错误吗? For simplicity I removed locking code.为简单起见,我删除了锁定代码。 (doesn't work either without) (没有也不起作用)

About.razor.cs关于.razor.cs

using System.Collections.Generic;
using System.Linq;
using Common.Server.Logic.Services;
using Common.Shared.Extensions;
using Microsoft.AspNetCore.Components;

namespace Common.Server.UI.Pages
{
    public partial class About : ComponentBase
    {
#nullable disable
        [Inject]
        private UserSessionInfo UserSession { get; set;  }

        private string IsAdminText { get; set; }
        private IEnumerable<string> UserRoleNames { get; set; } = Enumerable.Empty<string>();

#nullable restore

        protected override void OnInitialized()
        {
            IsAdminText = UserSession.IsAdmin.Format();
            UserRoleNames = UserSession.UserRoles;
        }
    }
}

UserSessionInfo.cs用户会话信息.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AspNetCore.ServiceRegistration.Dynamic.Interfaces;
using Common.Server.Logic.Bases;
using Common.Shared;
using Common.Shared.Extensions;
using Common.Shared.Models.Logging.Bases;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;

namespace Common.Server.Logic.Services
{
    public class UserSessionInfo : LockingBase, IHasUsername, IScopedService
    {
        public DateTime LoginAt { get; set; }

        private UserManager<IdentityUser> UserManager { get; }
        private AuthenticationStateProvider AuthenticationStateProvider { get; }

        public IEnumerable<string> UserRoles { get; private set; } = Enumerable.Empty<string>();

        private string? _username;
        public string? Username
        {
            get
            {
                CheckInitialized();

                return _username;
            }
        }

        private bool _isAdmin;
        public bool IsAdmin
        {
            get
            {
                CheckInitialized();

                return _isAdmin;
            }
        }

        public UserSessionInfo(IServiceProvider serviceProvider)
        {
            UserManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>();
            AuthenticationStateProvider = serviceProvider.GetRequiredService<AuthenticationStateProvider>();
        }

        private void CheckInitialized()
        {
            if (_username is null)
                // double lock
                SyncLock.Lock(async () => await InitializeAsync()).GetAwaiter().GetResult();
        }

        private async Task InitializeAsync()
        {
            var claimsPrincipal = (await AuthenticationStateProvider.GetAuthenticationStateAsync()).User;

            var user = await UserManager.GetUserAsync(claimsPrincipal); // Does not return
            _isAdmin = await UserManager.IsInRoleAsync(user, Const.Authorization.Roles.AdminRoleName);

            UserRoles = await UserManager.GetRolesAsync(user);

            var username = await UserManager.GetUserNameAsync(user);
            Interlocked.Exchange(ref _username, username);
        }
    }
}

also (startup.cs):也(startup.cs):

services.AddDefaultIdentity<IdentityUser>()
                .AddRoles<IdentityRole>()
                .AddClaimsPrincipalFactory<UserClaimsPrincipalFactory<IdentityUser, IdentityRole>>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders()
                .AddDefaultUI();

services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();

services.AddScoped<UserSessionInfo>();

When an async method doesn't return then .GetAwaiter().GetResult() is the first suspect.当异步方法没有返回时, .GetAwaiter().GetResult()是第一个嫌疑人。

Most likely your calling code (the renderer?) is getting your Username and IsAdmin properties overlapped, and then you have a deadlock.很可能您的调用代码(渲染器?)正在让您的 Username 和 IsAdmin 属性重叠,然后您就会出现死锁。 But we can't be sure without seeing the whole call chain.但是如果没有看到整个调用链,我们就无法确定。

As a rule of thumb, you shouldn't need locking or GetResult (or.Wait(), .Result).根据经验,您不需要锁定或 GetResult(或 .Wait()、.Result)。 When you think you do it may be time to back up.当你认为你这样做时,可能是时候备份了。

Finally I found the solution.最后我找到了解决方案。 (and the reason why it din't work) (以及它不起作用的原因)

The problem was that I accessed IsAdmin during OnInitialized callback instead of OnInitializedAsync.问题是我在 OnInitialized 回调期间访问了 IsAdmin 而不是 OnInitializedAsync。

Putting access to IsAdmin into OnInitializedAsync everything works!将 IsAdmin 的访问权限放入 OnInitializedAsync 一切正常!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么UserManager.GetUserAsync在使用JWT时返回null? - Why does UserManager.GetUserAsync return null when using JWT? UserManager.GetUserAsync(User)是否可以在具有Authorize属性的类中返回null? - Can UserManager.GetUserAsync(User) return null in a class with Authorize attribute? _userManager.GetUserAsync(User) 返回 null - _userManager.GetUserAsync(User) returns null JWT 身份验证 - UserManager.GetUserAsync 返回 null - JWT Authentication - UserManager.GetUserAsync returns null 当照片不存在时,UserManager.GetUserAsync(User).Result.ProfilePicture 失败 - UserManager.GetUserAsync(User).Result.ProfilePicture Failing when Photo does not exists 为什么我们每个动作方法都必须调用await _userManager.GetUserAsync(User)? - Why do we have to invoke await _userManager.GetUserAsync(User) per action method? Angular 客户端,WebAPI 服务器 - userManager.GetUserAsync() 方法时的 cookie 问题 - Angular client, WebAPI server - cookie issue when userManager.GetUserAsync() method 自定义UserManager始终返回null - Custom UserManager always return null UserManager是否 <IdentityUser> 有缓存吗? - Does UserManager<IdentityUser> have cache? GetUserAsync 在 Razor EF ASP.NET 核心返回 null 时已经登录? - GetUserAsync in Razor EF ASP.NET Core return null when already sign in?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM