【发布时间】:2020-04-18 11:04:03
【问题描述】:
为什么 UserManager.GetUserAsync 不返回?
当我在“关于”页面上手动单击时,将在 Blazor UI 中访问属性 IsAdmin。我不明白为什么对 GetUSerAsync 的调用没有返回。有什么线索或错误吗?为简单起见,我删除了锁定代码。 (没有也不起作用)
关于.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>();
【问题讨论】:
-
services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<ApplicationDbContext>();你可以先查一下。 -
我正在使用。没有复制它。添加用户和登录工作正常。只是上面的代码没有。我用缺少的启动代码更新了我的问题代码。
-
@Henk Holtermann。这是正确的,但我总是使用一个 IServiceProvider ctor 参数来保持它的清洁。这减少了从基类继承时的样板签名代码。它还使测试类更容易一些,因为您只需为 IserviceProvider 传递一个模拟实例,而不是多个参数。无论如何,这并不能解决所描述的问题。
标签: c# asp.net-core entity-framework-core blazor-server-side