我有一个多层应用程序,是我开始在 ASP.NET Core 1.1 中编写的,我仍在不断学习。我像以前在 Web API 中所做的应用程序一样组织它,我有主机服务(网络核心应用程序)、业务层和数据库之上的数据层。业务层和数据层是 net core 标准库,但是当我想添加实体框架时,我必须修改数据层以使其看起来像 net core 应用程序,所以现在我有 Startup.cs 并在那里进行配置。这使我能够配置实体框架服务并在数据层中创建迁移。但现在我有一个问题,因为我想添加 asp.net 身份。网上的每一篇教程都是关于 SPA,在一个项目中包含所有内容。
我已将身份添加到 Startup.cs 并且数据库生成良好
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration.GetConnectionString("DefaultConnection");
services.AddEntityFramework(connectionString);
services.AddMyIdentity();
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = false;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
// User settings
options.User.RequireUniqueEmail = true;
});
}
public void Configure(IApplicationBuilder app)
{
app.UseIdentity();
}
但现在我需要从一个不是控制器的类中使用 UserManager,并且我不知道如何处理依赖项注入。
为了更好地解释,我的主机服务中有一个帐户控制器
[HttpPost]
[Route("Register")]
public async Task<IActionResult> Register([FromBody]RegisterUserDto dto)
{
var result = await Business.Commands.Accounts.Register(dto);
return Ok(result);
}
业务层只是调用数据层
public async static Task<ResponseStatusDto> Register(RegisterUserDto dto)
{
// some code here
var identityLogon = await Data.Commands.ApplicationUsers.Register(dto);
// some code here as well
return new ResponseStatusDto();
}
现在的问题是,如何在Data Register方法中获取UserManager呢?这是一个简单的类,它不从控制器继承,依赖注入不适用于构造函数,如此处的示例所示核心身份 https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity
public class AccountController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly IEmailSender _emailSender;
private readonly ISmsSender _smsSender;
private static bool _databaseChecked;
private readonly ILogger _logger;
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
}
//
// GET: /Account/Login
那么,如何将启动中配置的 UserManager 传递给中间件中某处的某个随机类?我见过这个question https://stackoverflow.com/questions/38253607/creating-a-usermanager-outside-of-built-in-dependency-injection-system,但是将 null 值传递给 UseManager 构造函数的答案不起作用,而且我认为这很好。
//根据Set的答案进行编辑
我已经删除了所有静态引用,但我仍然没有完全做到这一点。我已关注this https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection#registering-your-own-services依赖注入说明,但我不确定如何实例化和调用 Add 方法。
我已经创建了一个界面
public interface IIdentityTransaction
{
Task<IdentityResult> Add(ApplicationUser appUser, string password);
}
并实施了它
public class IdentityTransaction : IIdentityTransaction
{
private readonly ApplicationDbContext _dbContext;
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
public IdentityTransaction(ApplicationDbContext context, UserManager<ApplicationUser> userManager, RoleManager<IdentityRole> roleManager)
{
_roleManager = roleManager;
_userManager = userManager;
_dbContext = context;
}
public async Task<IdentityResult> Add(ApplicationUser applicationUser, string password)
{
return await _userManager.CreateAsync(applicationUser, password);
}
}
然后我将它注入到 Startup.cs 中的服务集合中
services.AddScoped<IIdentityTransaction, IdentityTransaction>();
但如何从 Identity Transaction 服务调用 Add 方法?
我无法实例化它,也无法在构造函数上使用依赖注入,因为它只是循环我的问题。 @Set提到的
或将 UserManager userManager 作为参数传递给方法
从哪里传过来?
我想我已经很接近了,但我错过了一些东西。
我尝试过使用
IIdentityTransaction it = services.GetRequiredService<IIdentityTransaction>();
但是 IServiceProvider 的服务为空,我也不知道从哪里获取它。