【问题标题】:How can I abstract dependent type from base C# base project using microsoft identity framework?如何使用微软身份框架从基础 C# 基础项目中抽象依赖类型?
【发布时间】:2018-01-26 13:36:11
【问题描述】:

我有一个想要重用的身份验证项目。

我有一个名为 authentication 的 AspNetCore Identity 项目,它旨在成为一个可重用的身份验证项目。如果您查看过 AspNetCore Identity 实现,您将看到一个名为 UserManager 的类型,其中应用程序用户是您将用户实现存储在 AspNetUsers 数据库表中的类。

public class ApplicationUser : IdentityUser
{
}

我遇到的问题是,在这个独立的身份验证项目中有一个名为 AccountController 的控制器,它包含所有登录/注销、注册和其他相关帐户操作。我希望将应用程序用户从这个项目的类中抽象出来,这样我就可以根据项目对多种解决方案的需求对其进行更改。

身份验证项目有一个启动类,它在使用它的项目中按如下方式启动:

authenticationStartUp.ConfigureServices<ApplicationUser, MyDatabase>
      (services, Configuration);

如您所见,订阅项目添加了自己的 ApplicationUser 实现。接下来是在 services.AddIdentity 调用中引用 TApplicationUser 的身份配置。

    public void ConfigureServices<TApplicationUser, TContext>
          (IServiceCollection services, IConfigurationRoot Configuration)
        where TApplicationUser : IdentityUser
        where TContext : DbContext
    {
        services.AddIdentity<TApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<TContext>()
            .AddDefaultTokenProviders();

不幸的是,现在这在使用注入服务的 AccountController 中发生了故障。如何将 TApplicationUser 添加到控制器中。

public class AccountController : Controller
{
    private readonly UserManager<TApplicationUser> _userManager;

    public AccountController(UserManager<TApplicationUser> userManager) 
    {
        _userManager = userManager;
    }
}

这显然被破坏了,因为没有 TApplicationUser。此外,如果我按如下方式添加 TApplicationUser 控制器将不再被解析并且没有任何反应。

public class AccountController<TApplicationUser> : Controller 
   where TApplicationUser : IdentityUser
{
    private readonly UserManager<TApplicationUser> _userManager;

    public AccountController(UserManager<TApplicationUser> userManager) 
    {
        _userManager = userManager;
    }
} 

是否仍然可以使用包含的类型参数来解析应用程序控制器?

此外,我还发现了另一个问题,即即使我在基类中添加类型参数,我将如何在使用 TApplicationUser 的视图中添加类型参数。这是一个例子

身份验证项目中嵌入的视图

@* TApplicationUser obviously doesn't resolve *@
@inject SignInManager<TApplicationUser> SignInManager 
 @{
    var loginProviders = SignInManager.GetExternalAuthenticationSchemes().ToList();
    if (loginProviders.Count == 0)
    {
        <div>
            <p>
                There are no external authentication services configured. See <a href="https://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
                for details on setting up this ASP.NET application to support logging in via external services.
            </p>
        </div>
    }
    else
    {
        <form asp-controller="Account" asp-action="ExternalLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal">
            <div>
                <p>
                    @foreach (var provider in loginProviders)
                    {
                        <button type="submit" class="btn btn-default" name="provider" value="@provider.AuthenticationScheme" title="Log in using your @provider.DisplayName account">@provider.AuthenticationScheme</button>
                    }
                </p>
            </div>
        </form>
    }
}

【问题讨论】:

  • 将通用控制器作为基本控制器
  • 我应该传递什么作为基本控制器类型参数?
  • 使用项目的应用用户
  • 目前,AccountController 存在于身份验证项目中,因此这是不可能的。也许如果我撤消该操作,我可以将身份验证项目中的所有实现作为基类,并从每个通过 ApplicationUser 的实现继承,如您所说。

标签: c# dependency-injection asp.net-core asp.net-identity code-reuse


【解决方案1】:

将通用控制器作为可重用项目中的基本控制器

public abstract class AccountControllerBase<TApplicationUser> : Controller 
    where TApplicationUser : IdentityUser {
    protected readonly UserManager<TApplicationUser> _userManager;

    protected AccountController(UserManager<TApplicationUser> userManager) {
        _userManager = userManager;
    }
}

使用类/项目将派生自基本控制器并定义通用参数

public class AccountController : AccountControllerBase<ApplicationUser> {

    public AccountController(UserManager<ApplicationUser> userManager) 
        : base(userManager) {  }

}

【讨论】:

  • 这确实有效,但有一个小问题是 RazorView 正在使用@inject SignInManager SignInManager。有没有办法解决这个限制。由于在视图中使用了登录管理器?
  • 好的,你必须为我澄清这部分。为什么以及如何在视图中使用管理器?控制器填充 ViewModel 并将其传递给视图,因此我并不完全清楚您的意思。
  • 我用一些代码更新了原帖。此代码附带我正在使用的 Microsoft Identity 实现。
  • 现在阅读。乍一看,我会将视图重构为不依赖于泛型。我会将它下移一层并从通用管理器继承类
  • 我不确定我是否完全理解如何按照您描述的方式实现它。我创建了一个帮助器类,它将所需的数据设置为属性,并将该帮助器添加到 ViewBag。这应该可以工作,直到我遇到也依赖于 SignInManager/UserManager TApplicationUser 类型的视图。我还没到那里。
猜你喜欢
  • 2012-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-15
  • 1970-01-01
  • 1970-01-01
  • 2018-07-16
相关资源
最近更新 更多