我有一个多层应用程序,开始时使用ASP.NET Core 1.1编写,但我仍在学习过程中。我像以前做的Web API一样组织了它,我有主机服务(net core app),业务层和数据层,这些都在数据库之上。业务和数据层是net core标准库,但当我想添加实体框架时,我不得不修改数据层,使其看起来像net core应用程序,因此现在我有了Startup.cs和配置。这使我能够配置实体框架服务并在数据层创建迁移。但现在我有一个问题,因为我想添加asp.net身份验证。网上的每个教程都是关于将所有内容放在一个项目中的SPAs。 我已经将身份验证添加到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?它是一个简单的类,没有从控制器继承,也不像这里的例子那样可以通过构造函数进行依赖注入。请参考Core 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传递给中间某个随机类?我看到这个问题,但是直接将null值传递给UseManager构造函数的答案既不起作用,也不好。//根据Set的答案进行编辑。 我已经删除了所有的静态引用,但我还没有完全解决问题。我遵循了这个依赖注入说明,但是我不知道如何实例化并调用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>();
如何从IdentityTransaction服务调用Add方法呢?
我无法实例化它,也不能在构造函数中使用依赖注入,因为这只会让我的问题循环。@Set提到:
或将UserManager userManager作为参数传递给方法 从哪里传递?
我认为我很接近答案,但是还缺少一些东西。 我已经尝试过使用:
IIdentityTransaction it = services.GetRequiredService<IIdentityTransaction>();
但是,服务(即IServiceProvider)为空,我也不知道从哪里获取它。