2016-07-30 37 views
6

如何從默認的ASP.Net Mvc/Identity 2.0中分離屬性,功能和類?我有幾件事情爭奪:將ApplicationUser和其他模型移出MVC項目

  • 在默認情況下,它要使用OWIN的背景下,以線了某種依賴注入,並控制經理
  • 它把ApplicationDbContext在應用層面,那裏有我體系結構要求它在「較低」級別可用。
  • 它需要我聲明與作用於這些屬性的功能相同的任何屬性(這不適用於我的體系結構)
  • ApplcationUser模型對Asp.Net有依賴關係,我希望打破,如果我到POCO移動到該解決方案的非MVC層

應用架構:

我有了幾個層次的解決方案:

  • API - 定義接口的服務
  • 域 - 存儲代表業務領域
  • 企業POCO模式 - 專賣店邏輯與域對象進行交互,並消耗服務
  • 服務 - 實施服務,包括實體框架,和的域對象的結構映射
  • 應用程序 - 在這種情況下,是一個MVC應用程序。

我的業務層只知道服務接口,而不是實現,我使用依賴注入來連接所有東西。

我有一些接口定義數據服務的讀/寫/工作操作單元,以及從DbContext(在我的服務層)繼承的這些接口的實現。我不是通過一系列DbSet<MyPoco> MyPocos {get;set;},而是通過傳遞一系列定義關係的類型配置,然後通過Set<Type>()訪問我的類型來連接它。所有這一切都很好。

這個堆棧已經適用於現有的應用程序,並且運行良好。我知道它將轉變爲一個MVC應用程序,並且只有「開箱即用」的ASP.Net Identity-2存在問題。

回答

7

我對這個解決方案是:摘要所有的東西

我身邊這讓通過抽象大部分身份的功能集成到自己的項目,該項目允許抽象的其他方便單元測試和重用項目。

我讀這篇文章

Persistence-Ignorant ASP.NET Identity with Patterns

然後我微調的思路,以適合我的需要後,計上心來。我基本上只是從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 
} 

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 
} 

IIdentityResult

/// <summary> 
/// Represents the minimal result of an identity operation 
/// </summary> 
public interface IIdentityResult : System.Collections.Generic.IEnumerable<string> { 
    bool Succeeded { get; } 
} 

在我的身份管理器,它也住在自己的項目的默認實現,我只是包裹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 
} 

應用程序層只知道抽象,並在啓動時配置實現。我沒有更高層的using Microsoft.AspNet.Identity,因爲他們都使用本地抽象。

該層可以是這樣的:

  • API - 定義了服務(包括身份抽象接口)
  • 域接口 - 商店POCO模型代表業務領域
  • 業務 - 存儲邏輯對於域對象的交互,以及消費服務
  • 服務 - 實施服務,包括實體框架,結構圖,爲域對象
  • 身份 - 實施Microsoft.AspNet.Identity特殊服務,包括Microsoft.AspNet.Identity.EntityFramework;和OWIN配置
  • 應用 - 在這種情況下,MVC應用程序。

在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); 
    } 
} 

這裏假設你使用的是一些DI框架。只有在IoC的配置中,任何提到的實現身份的層完全將其從需要使用身份的人身上抽象出來。

//NOTE: This is custom code. 
protected override void ConfigureDependencies(IContainerBuilder builder) { 
    if (!builder.HasHandler(typeof(IIdentityManager))) { 
     builder.PerRequest<IIdentityManager, DefaultUserManager>(); 
    } 
} 
+2

感謝您的詳細答覆!它看起來會直接下降。你的架構與我的基本相同。我正在使用DI(簡單注入器),因此將用戶管理器注入控制器應該沒問題。 – AndrewP

相關問題