12

我正在使用这个示例项目(https://github.com/imranbaloch/ASPNETIdentityWithOnion)作为我的应用程序架构,在这个示例中,核心完全从包括身份框架在内的基础设施中分离出来。

在这个示例中,作者使用了适配器模式来解耦核心身份类(IdentityUser、IdentityRole ...),并在核心层中提供类似的类。

现在这个示例项目中的问题是域模型(产品、图像)没有与模仿身份的虚拟类(AppUser、ApplicationRole、AppliationUserRoles...)链接。

然后我修改了代码以添加对 AppUser 的引用

public sealed class Image : BaseEntity
{
    public Image()
    {
        Products = new HashSet<Product>();
    }

    public string Path { get; set; }

    public AppUser AppUser { get; set; } // The  Added Reference ...

    public ICollection<Product> Products { get; set; }
}

如果我将“AppUser”导航属性放在“Image”类中,则创建的数据库将有四个新表,而不是身份框架的默认五个表。

身份表的洋葱数据库问题

我需要将这些表合并到默认表中。如何 ?

编辑:

这是驻留在数据层中的身份模型(我无法从核心中引用)。

public class ApplicationIdentityUser :
    IdentityUser<int, ApplicationIdentityUserLogin, ApplicationIdentityUserRole, ApplicationIdentityUserClaim>, IDomainUser {

    public ApplicationIdentityUser()
        : base() {
        Images = new HashSet<Image>();
    }

    public string Name { get; set; }
    public virtual ICollection<Image> Images { get; set; }
}


public class ApplicationIdentityRole : IdentityRole<int, ApplicationIdentityUserRole>
{
    public ApplicationIdentityRole(){}

    public ApplicationIdentityRole(string name){Name = name;}
}

public class ApplicationIdentityUserRole : IdentityUserRole<int> {}

public class ApplicationIdentityUserClaim : IdentityUserClaim<int>{}

public class ApplicationIdentityUserLogin : IdentityUserLogin<int>{}

这也是我在 OnModelCreating 方法中的模型构建器:

  modelBuilder.Entity<Image>()
            .Property(e => e.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<Image>()
            .HasMany(e => e.Products)
            .WithRequired(e => e.Image)
            .WillCascadeOnDelete(false);
        modelBuilder.Entity<ApplicationIdentityUser>()
             .Property(e => e.Id)
             .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<ApplicationIdentityRole>()
            .Property(e => e.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<ApplicationIdentityUserClaim>()
             .Property(e => e.Id)
             .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
4

3 回答 3

24

好的,我通过执行以下操作解决了这个问题:

  1. 在核心中包含对 Microsoft.AspNet.Identity.Core 的依赖项
  2. 在 AppUser 上实现IUser接口(该接口来自 Microsoft.AspNet.Identity.Core)。
  3. 在ApplicationRole上实现IRole接口。
  4. 完全摆脱IdentityDbContext并仅从DbContext继承。
  5. 实施您自己的IUserStore*版本,提供您的AppUser
  6. 实现您自己的IRoleStore版本,提供您的ApplicationRole

我知道依赖 Microsoft.AspNet.Identity.Core 听起来很奇怪,但我们只需要 IUser 接口,它基本上也被视为您的应用程序的核心域模型。

这里的终极想法是彻底摆脱 Microsoft.AspNet.Identity.EntityFramework

有兴趣的开发者可以对此 +1,所以我可以在 GitHub 上上传完整的工作示例。

于 2014-10-29T06:08:05.227 回答
2

我正在使用这个框架,不需要在每个实体中都有一个链接为了获取 userID 引用,我在 BaseEntity 中添加了一个属性 UserIDBy ,这样每个实体都会继承它。

public abstract class BaseEntity
{
    public int Id { get; set; }
    public string UserIDBy { get; set; }
}

接下来,在 web 项目中,已经有一个名为GetUserId(this IIdentity identity)in的扩展方法IdentityExtensions.cs,因此要在每个 Create 和 Edit 操作结果中存储 UserIDBy:

创建操作结果:

 // POST: /Region/Create
    [HttpPost]
    public async Task<ActionResult> Create([Bind(Include = "RegionName")] Region region)
    {
        if (ModelState.IsValid)
        {
            // TODO: Add insert logic here
            var id = User.Identity.GetUserId();
            region.UserIDBy = id.ToString(); 

            await _regionService.AddAsync(region);
            return Json(new { success = true });
        }

        return PartialView("_Create", region);
    }

编辑操作结果:

 //// POST: /Region/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "id,RegionName")] Region region)
    {
        if (ModelState.IsValid)
        {
            var id = User.Identity.GetUserId();
            region.UserIDBy = id.ToString(); 
            _regionService.Update(region);
            return Json(new { success = true });
        }
        return PartialView("_Edit", region);
    }

不要忘记导入它:

using Myapp.Web.Extensions;
于 2015-12-03T12:30:18.313 回答
1

偶然发现了这个,遇到了同样的问题。

标记答案的问题在于它仍然引用 Microsoft.AspNet,这使得未来的 .NET Core 计划变得粗糙。

主要问题实际上是在核心中构建身份验证功能的一般尝试,这违背了目的。

考虑让用于 Web 身份验证和授权的内置功能保留在 Web 层中,并引用代表 Core 需求的 Core 用户对象(UserProfile?)。这也将简化切换到另一种身份验证方法 (AD)。

然后,根据您的偏好,您可以从 AspNetUser 引用 Core.UserProfile 以避免多次 SQL 调用,或者只是确保对 Core.UserProfile 操作具有良好的缓存策略。

这允许您控制与您的核心模型分开的身份验证方法。

于 2017-07-19T17:50:31.763 回答