我正在開發一個 ASP.NET Core 應用程式,并且正在使用自定義PageModelActivatorProvider來創建我的剃須刀頁面。這個應用程式有用戶并使用AddIdentityCore. 我還添加了一個SignInManager和身份驗證:
builder.Services.AddIdentityCore<ApplicationUser>(options =>
{
options.SignIn.RequireConfirmedEmail = true;
options.User.RequireUniqueEmail = true;
})
.AddSignInManager<CustomSignInManager>();
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
options.DefaultSignOutScheme = IdentityConstants.ApplicationScheme;
})
.AddCookie(IdentityConstants.ApplicationScheme, options =>
{
options.LoginPath = new PathString("/Account/Login");
options.Events = new CookieAuthenticationEvents
{
OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
};
});
我創建了一個自定義并將其添加為我的檔案UserStore中的范圍服務:Program.cs
string connectionString = builder.Configuration.GetConnectionString("connectionString");
builder.Services.AddSingleton<IPageModelActivatorProvider, WebUIPageModelActivatorProvider>();
builder.Services.AddScoped<IUserRepository>(_ => new UserRepository(connectionString));
builder.Services.AddScoped<IUserStore<ApplicationUser>, UserStore>();
和類分別作為范圍服務添加到和UserManager方法中。SignInManagerAddIdentityCoreAddSignInManager
我的PageModelActivatorProvider班級創建了一個LoginModel頁面模型,它采用 aUserManager和 a SignInManager。這兩個都是范圍服務,但是我PageModelActivatorProvider的注冊為單例服務,所以我不能通過建構式注入UserManager和注入。SignInManager當我嘗試使用IServiceProvidertoGetRequiredService時,出現以下例外:
'Cannot resolve scoped service 'Microsoft.AspNetCore.Identity.IUserStore`1[DataAccess.ApplicationUser]' from root provider.'
我得到了同樣的例外UserManager,SignInManager因為它們都注冊為范圍服務,我試圖在單例服務中訪問它們。
public sealed class WebUIPageModelActivatorProvider : IPageModelActivatorProvider, IDisposable
{
private readonly IServiceProvider _services;
public WebUIPageModelActivatorProvider(IServiceProvider services)
{
// Create Singleton components
_services = services;
}
public Func<PageContext, object> CreateActivator(CompiledPageActionDescriptor descriptor)
{
return (context) => _CreatePageModelType(context, descriptor.ModelTypeInfo!.AsType());
}
public Action<PageContext, object>? CreateReleaser(CompiledPageActionDescriptor descriptor)
{
return (context, pageModel) => (pageModel as IDisposable)?.Dispose();
}
private object _CreatePageModelType(PageContext context, Type pageModelType)
{
// Scoped components for Identity Core
IUserStore<ApplicationUser> userStore = _services.GetRequiredService<IUserStore<ApplicationUser>>();
UserManager<ApplicationUser> userManager = _services.GetRequiredService<UserManager<ApplicationUser>>()!;
SignInManager<ApplicationUser> signInManager = _services.GetRequiredService<SignInManager<ApplicationUser>>()!;
// Create Transient components
switch (pageModelType.Name)
{
case nameof(IndexModel):
return new IndexModel();
case nameof(LoginModel):
return new LoginModel(userManager, signInManager, Logger<LoginModel>());
default: throw new NotImplementedException(pageModelType.FullName);
}
}
public void Dispose()
{
// Release singleton components here, if needed
}
private ILogger<T> Logger<T>() => this._loggerFactory.CreateLogger<T>();
接下來我嘗試創建一個IServiceScope來解決我的范圍服務:
...
private object _CreatePageModelType(PageContext context, Type pageModelType)
{
using (var scope = _services.CreateScope())
{
// Scoped components for Identity Core
IUserStore<ApplicationUser> userStore = scope.ServiceProvider.GetRequiredService<IUserStore<ApplicationUser>>();
UserManager<ApplicationUser> userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>()!;
SignInManager<ApplicationUser> signInManager = scope.ServiceProvider.GetRequiredService<SignInManager<ApplicationUser>>()!;
// Create Transient components
switch (pageModelType.Name)
{
case nameof(IndexModel):
return new IndexModel();
case nameof(LoginModel):
return new LoginModel(userManager, signInManager, Logger<LoginModel>());
default: throw new NotImplementedException(pageModelType.FullName);
}
}
}
...
這個方法成功地創建了作用域服務并將它們注入到 myLoginModel中,但是,在它們被注入之后,它們被處理掉了,我收到了以下例外:
ObjectDisposedException: Cannot access a disposed object. Object name: 'UserManager`1'.
有沒有辦法將范圍服務注入自定義PageModelActivatorProvider?
uj5u.com熱心網友回復:
正如評論中所討論的,將 注入IHttpContextAccessor單例服務,并用于httpContextAccessor.HttpContext.RequestServices獲取IServiceProvider當前請求的 ,您可以使用它來決議您的范圍服務。
public sealed class WebUIPageModelActivatorProvider : IPageModelActivatorProvider, IDisposable
{
private readonly IHttpContextAccessor _httpContextAccessor;
public WebUIPageModelActivatorProvider(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
}
private object _CreatePageModelType(PageContext context, Type pageModelType)
{
IServiceProvider services = _httpContextAccessor.HttpContext.RequestServices;
// Scoped components for Identity Core
IUserStore<ApplicationUser> userStore = services.GetRequiredService<IUserStore<ApplicationUser>>();
UserManager<ApplicationUser> userManager = services.GetRequiredService<UserManager<ApplicationUser>>()!;
SignInManager<ApplicationUser> signInManager = services.GetRequiredService<SignInManager<ApplicationUser>>()!;
...
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/456528.html
標籤:C# asp.net-mvc asp.net 核心 依赖注入 剃刀页面
上一篇:身份-如何重定向已登錄的用戶
