And*_*ewP 7 architecture asp.net-mvc asp.net-identity-2
如何从默认的ASP.Net Mvc/Identity 2.0中拆分属性,功能和类?我正在与一些事情作斗争:
应用架构:
我有一个有几层的解决方案:
我的业务层只知道服务接口,而不是实现,我使用依赖注入来连接所有东西.
我有一些接口定义数据服务的读/写/工作单元操作,以及从DbContext(在我的服务层)继承的这些接口的实现.DbSet<MyPoco> MyPocos {get;set;}我通过传递一系列定义关系的类型配置,然后通过访问我的类型,而不是一系列的连接Set<Type>().一切都很好.
此堆栈已用于现有应用程序,并且运行良好.我知道它将转换到MVC应用程序,并且只有"开箱即用"ASP.Net Identity-2的问题.
我的解决方案是:抽象所有的东西
我通过将身份的大部分功能抽象到自己的项目中来解决这个问题,这样可以更容易地进行单元测试并在其他项目中重用抽象.
读完这篇文章后我明白了
然后我调整了这个想法以满足我的需求.我基本上只是将我需要的所有内容从asp.net.identity换成我的自定义接口,这些接口或多或少地镜像了框架提供的功能,但具有更容易抽象而不是实现的优点.
IIdentityUser
/// <summary>
/// Minimal interface for a user with an id of type <seealso cref="System.String"/>
/// </summary>
public interface IIdentityUser : IIdentityUser<string> { }
/// <summary>
/// Minimal interface for a user
/// </summary>
public interface IIdentityUser<TKey>
where TKey : System.IEquatable<TKey> {
TKey Id { get; set; }
string UserName { get; set; }
string Email { get; set; }
//...other code removed for brevity
}
Run Code Online (Sandbox Code Playgroud)
IIdentityManager
/// <summary>
/// Exposes user related api which will automatically save changes to the UserStore
/// </summary>
public interface IIdentityManager : IIdentityManager<IIdentityUser> { }
/// <summary>
/// Exposes user related api which will automatically save changes to the UserStore
/// </summary>
public interface IIdentityManager<TUser> : IIdentityManager<TUser, string>
where TUser : class, IIdentityUser<string> { }
/// <summary>
/// Exposes user related api which will automatically save changes to the UserStore
/// </summary>
public interface IIdentityManager<TUser, TKey> : IDisposable
where TUser : class, IIdentityUser<TKey>
where TKey : System.IEquatable<TKey> {
//...other code removed for brevity
}
Run Code Online (Sandbox Code Playgroud)
IIdentityResult
/// <summary>
/// Represents the minimal result of an identity operation
/// </summary>
public interface IIdentityResult : System.Collections.Generic.IEnumerable<string> {
bool Succeeded { get; }
}
Run Code Online (Sandbox Code Playgroud)
在我的身份管理器的默认实现中,它也存在于自己的项目中,我只是ApplicationManager在我的类型和asp.net.identity类型之间包装然后映射结果和功能.
public class DefaultUserManager : IIdentityManager {
private ApplicationUserManager innerManager;
public DefaultUserManager() {
this.innerManager = ApplicationUserManager.Instance;
}
//..other code removed for brevity
public async Task<IIdentityResult> ConfirmEmailAsync(string userId, string token) {
var result = await innerManager.ConfirmEmailAsync(userId, token);
return result.AsIIdentityResult();
}
//...other code removed for brevity
}
Run Code Online (Sandbox Code Playgroud)
应用程序层只知道抽象,并且在启动时配置实现.我没有任何using Microsoft.AspNet.Identity更高级别,因为他们都使用本地抽象.
这些层可能如下所示:
因此,在MVC应用层中AccountController只需要
using MyNamespace.Identity.Abstractions
public partial class AccountController : Controller {
private readonly IIdentityManager userManager;
public AccountController(IIdentityManager userManager) {
this.userManager = userManager;
}
//...other code removed for brevity
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Signin(LoginViewModel model, string returnUrl) {
if (ModelState.IsValid) {
// authenticate user
var user = await userManager.FindAsync(model.UserName, model.Password);
if (user != null) {
//...code removed for brevity
} else {
// login failed
setFailedLoginIncrementalDelay();
ModelState.AddModelError("", "Invalid user name or password provided.");
}
}
//TODO: Audit failed login
// If we got this far, something failed, redisplay form
return View(model);
}
}
Run Code Online (Sandbox Code Playgroud)
这假设您使用的是一些DI框架.只有在IoC的配置中,任何提及都是由实现身份的层完全抽象而不是那些需要使用身份的层.
//NOTE: This is custom code.
protected override void ConfigureDependencies(IContainerBuilder builder) {
if (!builder.HasHandler(typeof(IIdentityManager))) {
builder.PerRequest<IIdentityManager, DefaultUserManager>();
}
}
Run Code Online (Sandbox Code Playgroud)