почему UserManager.GetUserAsyn c не возвращается? - PullRequest
0 голосов
/ 18 апреля 2020

почему UserManager.GetUserAsyn c не возвращается?

Свойство IsAdmin будет доступно в Blazor UI, когда я нажму вручную на странице About. Я не понимаю, почему вызов GetUSerAsyn c не возвращается. Любые подсказки или ошибки? Для простоты я удалил код блокировки. (не работает без них)

About.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

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);
        }
    }
}

также (startup.cs):

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

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

services.AddScoped<UserSessionInfo>();

1 Ответ

0 голосов
/ 19 апреля 2020

Наконец я нашел решение. (и причина, по которой он не работает)

Проблема была в том, что я обращался к IsAdmin во время обратного вызова OnInitialized вместо OnInitializedAsyn c.

Помещение доступа к IsAdmin в OnInitializedAsyn c все работает!

...