将 ApplicationUser 和其他模型移出 MVC 项目 [英] Moving ApplicationUser and other models out of MVC project

查看:20
本文介绍了将 ApplicationUser 和其他模型移出 MVC 项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将属性、功能和类从默认的 ASP.Net Mvc/Identity 2.0 中分离出来?我正在与一些事情作斗争:

How can I split the properties, functionality and classes out of the default ASP.Net Mvc / Identity 2.0? I am battling with a few things:

  • 默认情况下,它想使用 OWIN 的上下文来连接某种依赖注入,并控制 Managers
  • 它将 ApplicationDbContext 置于应用程序级别,我的架构要求它在较低"级别可用.
  • 它要求我在与作用于这些属性的功能(不适合我的架构)相同的类中声明任何属性
  • ApplcationUser 模型依赖于 Asp.Net,如果我要将 POCO 移动到解决方案的非 MVC 层,我想打破这种依赖

应用架构:

我有一个具有多层的解决方案:

I have a solution that has several tiers :

  • Api - 定义服务接口
  • 域 - 存储代表业务域的 POCO 模型
  • 业务 - 存储与域对象交互的逻辑,并使用服务
  • 服务 - 服务的实现,包括实体框架和域对象的结构映射
  • 应用程序 - 在本例中为 MVC 应用程序.

我的业务层只知道服务接口,不知道实现,我使用依赖注入来连接一切.

My business layer only knows about service interfaces, not implementation, and I am using dependency injection to wire everything up.

我有一些接口定义了数据服务的读/写/工作单元操作,以及这些从 DbContext 继承的实现(在我的服务层中).而不是拥有一系列 DbSetMyPocos {get;set;},我通过传递一系列定义关系的类型配置来连接它,然后通过 Set() 访问我的类型.一切都很好.

I have some interfaces defining read/write/unit of work operations for a data service, and an implementation of these that inherit from DbContext (in my Service layer). Instead of having a series of DbSet<MyPoco> MyPocos {get;set;}, I am wiring it up by passing a series of type configurations that define relationships, then accessing my types through Set<Type>(). All that works great.

此堆栈已用于现有应用程序,并且运行良好.我知道它将过渡到 MVC 应用程序,并且只有开箱即用"的 ASP.Net Identity-2 有问题.

This stack has been in place for an existing application, and works well. I know it will transition to an MVC application, and am only having issues with the "out of the box" ASP.Net Identity-2.

推荐答案

我的解决方案是:抽象所有的东西

我通过将身份的大部分功能抽象到自己的项目中来解决这个问题,这允许在其他项目中更轻松地进行单元测试和重用抽象.

I got around this by abstracting most of the functionality of identity into its own project which allowed for easier unit testing and reuse of the abstraction in other projects.

看完这篇文章,我有了想法

I got the idea after reading this article

具有模式的持久性无知 ASP.NET 身份

然后我微调了这个想法以满足我的需求.我基本上只是将我需要的一切从 asp.net.identity 换成了我的自定义接口,这或多或少反映了框架提供的功能,但具有更容易抽象而不是实现的优势.

I then fine tuned the idea to suit my needs. I basically just swapped out everything I needed from asp.net.identity for my custom interfaces which more or less mirrored the functionality provided by the framework but with the advantage of easier abstractions and not implementations.

身份用户

/// <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
}

身份管理器

/// <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
}

IdentityResult

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 类型之间映射结果和功能.

In my default implementation of the identity manager, which also lives in its own project, I simply wrapped the ApplicationManager and then mapped results and functionality between my types and the asp.net.identity types.

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 在更高级别,因为它们都使用本地抽象.

The application layer is only aware of the abstractions and the implementation is configured at startup. I don't have any using Microsoft.AspNet.Identity at the higher level as they are all using the local abstractions.

层可以是这样的:

  • Api - 定义服务接口(包括身份抽象接口)
  • Domain - 存储代表业务领域的 POCO 模型
  • 业务 - 存储与域对象交互的逻辑,并使用服务
  • 服务 - 服务的实现,包括实体框架和域对象的结构映射
  • Identity - Microsoft.AspNet.Identity 特定服务的实现,包括 Microsoft.AspNet.Identity.EntityFramework;和 OWIN 配置
  • 应用程序 - 在本例中为 MVC 应用程序.

在 MVC 应用层中,AccountController 因此只需要

In MVC Application layer the AccountController thus only needed

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 的配置中才提到实现身份的层,将其与需要使用身份的人完全抽象出来.

This assumes you are using some DI framework. It is only in the configuring of the IoC that any mention is made of the layer that implements identity completely abstracting it away from those that have need of using identity.

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

这篇关于将 ApplicationUser 和其他模型移出 MVC 项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆