Asp.net AspNetCore中间件UserManager依赖项注入
我有一个多层应用程序,我开始用ASP.NETCore1.1编写,我还在学习。我像以前在WebAPI中做的应用一样组织它,我有主机服务(NetCore应用)、业务层和数据库之上的数据层。业务层和数据层是net core标准库,但当我想添加实体框架时,我必须修改数据层,使其看起来像net core应用程序,所以现在我有了Startup.cs,其中有配置。这使我能够配置实体框架服务并在数据层中创建迁移。但现在我有一个问题,因为我想添加asp.net标识。网络上的每一个教程都是关于水疗中心的,它们在一个项目中拥有一切。 我已经向Startup.cs添加了标识,并且数据库生成良好Asp.net AspNetCore中间件UserManager依赖项注入,asp.net,asp.net-core,asp.net-identity-3,Asp.net,Asp.net Core,Asp.net Identity 3,我有一个多层应用程序,我开始用ASP.NETCore1.1编写,我还在学习。我像以前在WebAPI中做的应用一样组织它,我有主机服务(NetCore应用)、业务层和数据库之上的数据层。业务层和数据层是net core标准库,但当我想添加实体框架时,我必须修改数据层,使其看起来像net core应用程序,所以现在我有了Startup.cs,其中有配置。这使我能够配置实体框架服务并在数据层中创建迁移。但现在我有一个问题,因为我想添加asp.net标识。网络上的每一个教程都是关于水疗中心的,它们在一个
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();
}
public void配置服务(IServiceCollection服务)
{
var connectionString=Configuration.GetConnectionString(“DefaultConnection”);
服务.附加框架(connectionString);
services.AddMyIdentity();
配置(选项=>
{
//密码设置
options.Password.RequireDigit=true;
options.Password.RequiredLength=8;
options.Password.RequireNonAlphanumeric=false;
options.Password.RequireUppercase=true;
options.Password.RequireLowercase=false;
//锁定设置
options.Lockout.DefaultLockoutTimeSpan=TimeSpan.FromMinutes(30);
options.locket.MaxFailedAccessAttempts=10;
//用户设置
options.User.RequireUniqueEmail=true;
});
}
公共void配置(IApplicationBuilder应用程序)
{
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);
}
[HttpPost]
[路线(“登记”)]
公共异步任务寄存器([FromBody]寄存器UserDTO)
{
var result=wait Business.Commands.Accounts.Register(dto);
返回Ok(结果);
}
业务层只调用数据层
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();
}
公共异步静态任务寄存器(RegisterUserDto)
{
//这里有一些代码
var identityLogon=wait Data.Commands.ApplicationUsers.Register(dto);
//这里也有一些代码
将新响应返回到();
}
现在的问题是,如何在数据寄存器方法中获取UserManager?它是一个简单的类,它不从控制器继承,依赖项注入不适用于构造函数,如这里的示例所示
公共类AccountController:控制器
{
private readonly UserManager,但是只将null值传递给UseManager构造函数的答案不起作用,我认为这也不好
//根据集合的答案进行编辑
我已经删除了所有的静态引用,但还没有完全删除。我遵循了依赖项注入说明,但我不确定如何实例化和调用Add方法
我已经创建了一个接口
public interface IIdentityTransaction
{
Task<IdentityResult> Add(ApplicationUser appUser, string password);
}
公共接口IIdentityTransaction
{
任务添加(ApplicationUser appUser,字符串密码);
}
并付诸实施
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);
}
}
public class IdentityTransaction:IIdentityTransaction
{
私有只读应用程序dbContext_dbContext;
专用只读用户管理器
我不能实例化它,也不能在构造函数上使用依赖项注入,因为它只是循环我的问题。@Set
或者将UserManager作为参数传递给方法
从哪里传过来
我想我很接近,但我错过了一些东西。
我试过使用
IIdentityTransaction it = services.GetRequiredService<IIdentityTransaction>();
IIdentityTransaction it=services.GetRequiredService();
但是作为IServiceProvider的服务是空的,我也不知道从哪里获得它。ASP.NET核心中的DI使用“构造函数注入”方法对控制器类和非控制器类的工作原理相同
您有问题,因为Register
方法是static
,因此无法访问实例变量/属性。您需要
- 使
寄存器方法非静态
- 或者将
UserManager UserManager
作为参数传递给方法
一般来说,您应该避免在业务逻辑中使用静态类,因为它们无助于正确测试您的代码并产生代码耦合。通过internet/SO搜索,您将发现许多为什么静态不好的主题
使用DI获取控制器中的Data.Commands.ApplicationUsers
类的实例。如果应用程序只需要此类的一个实例,请使用单实例生存期
更新。再次使用构造函数注入:修改“数据层”类,以便它可以将IIdentityTransaction
的实例作为构造函数参数:
public class YourDataLayerClass : IYourDataLayerClass
{
private IIdentityTransaction _identityTransaction;
public YourDataLayerClass(IIdentityTransaction identityTransaction)
{
_identityTransaction = identityTransaction;
}
public void MethodWhereYouNeedToCallAdd()
{
_identityTransaction.Add(...);
}
}
对于IYourDataLayerClass
实例,想法也是一样的:寄存器依赖性
services.AddScoped<IYourDataLayerClass, YourDataLayerClass>();
是的,你很接近
首先,从IdentityTransaction构造函数中删除上下文参数,因为在您的代码中,它似乎是无用的。或者,如果您计划稍后使用它,请在DI容器中声明它:
services.AddScoped<ApplicationDbContext, ApplicationDbContext>();
services.addScope();
第二件事,您只需在控制器的构造函数中添加IIdentityTransaction作为依赖项,并从其依赖项中删除SignInManager和UserManager,因为最终您不会在控制器中直接使用它们:
public class AccountController : Controller
{
private readonly IEmailSender _emailSender;
private readonly ISmsSender _smsSender;
private static bool _databaseChecked;
private readonly ILogger _logger;
IIdentityTransaction _identityTransaction;
public AccountController(
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory,
IIdentityTransaction identityTransaction)
{
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_identityTransaction = identityTransaction;
}
公共类AccountController:控制器
{
私人只读IEmailSender\u emailSender;
私有只读ISmsSender(U SMSENDER);
检查私有静态bool_数据库;
专用只读ILogger\u记录器;
身份交易(身份交易);;
公共账户控制员(
电邮发送者,
伊斯姆森德·斯姆森德,
伊洛格工厂伐木厂,
IIdentityTransaction(身份交易身份交易)
{
_emailSender=emailSender;
_斯姆森德
public class YourMiddleware
{
private IYourDataLayerClass _yourDataLayerClass;
public YourMiddleware(IYourDataLayerClass yourDataLayerClass)
{
_yourDataLayerClass = yourDataLayerClass;
}
...
}
services.AddScoped<ApplicationDbContext, ApplicationDbContext>();
public class AccountController : Controller
{
private readonly IEmailSender _emailSender;
private readonly ISmsSender _smsSender;
private static bool _databaseChecked;
private readonly ILogger _logger;
IIdentityTransaction _identityTransaction;
public AccountController(
IEmailSender emailSender,
ISmsSender smsSender,
ILoggerFactory loggerFactory,
IIdentityTransaction identityTransaction)
{
_emailSender = emailSender;
_smsSender = smsSender;
_logger = loggerFactory.CreateLogger<AccountController>();
_identityTransaction = identityTransaction;
}
services.AddScoped<IIdentityTransaction, IdentityTransaction>();
IIdentityTransaction it = services.GetRequiredService<IIdentityTransaction>();