การแยก ASP.NET IdentityUser จากเอนทิตีอื่นของฉัน


11

ฉันมีProjectName.Coreห้องสมุดที่มีตรรกะทางธุรกิจของฉันและหน่วยงานของฉันและพฤติกรรมของพวกเขา ขณะนี้ไม่มีความสัมพันธ์ใด ๆ กับ Entity Framework หรือ DAL อื่นใดเพราะฉันต้องการแยกสิ่งเหล่านั้นออกจากกัน การกำหนดค่า Entity Framework (ใช้ Fluent API) อยู่ในProjectName.Infrastructureโครงการเพื่อดูแลผลักดันเอนทิตีของฉันไปที่ EF โดยทั่วไปฉันจะไปในทิศทางของสถาปัตยกรรมที่คล้ายกับหัวหอม

อย่างไรก็ตามเมื่อเพิ่มกรอบงาน ASP.NET Identity ลงในการผสมฉันต้องทำให้ApplicationUserเอนทิตีของฉันสืบทอดจากIdentityUserคลาส แต่ApplicationUserคลาสของฉันมีความสัมพันธ์กับเอนทิตีอื่น ในการสืบทอดจากIdentityUserฉันแนะนำการอ้างอิงถึง Entity Framework ในโครงการเอนทิตีของฉันที่เดียวที่ฉันไม่ต้องการทำ การดึงApplicationUserคลาสออกจากโครงการเอนทิตีและเข้าสู่Infrastructureโครงการ (เนื่องจากใช้ระบบเอกลักษณ์ของ Entity Framework) จะส่งผลให้มีการอ้างอิงแบบวงกลมดังนั้นจึงไม่มีทางที่จะไป

มีวิธีใดบ้างรอบนี้เพื่อให้ฉันสามารถแยกสะอาดระหว่างสองชั้นนอกเหนือจากไม่ใช้ ASP.NET Identity?


1
คุณไม่สามารถสร้างอินเทอร์เฟซ IApplicationUser ในโครงการหลักของคุณและดำเนินการต่อในโครงสร้างพื้นฐานได้หรือไม่? ในความคิดของฉันเว้นแต่ว่าคุณกำลังสร้าง API หรือคุณจำเป็นต้องสลับการใช้งานอินเทอร์เฟซที่รันไทม์เพียงเก็บรหัส UI ที่ไม่ใช่ทั้งหมดของคุณไว้ในโครงการเดียว การมีโปรเจ็กต์ที่แตกต่างกันมากมายช่วยเพิ่มค่าใช้จ่ายด้านการจัดการจิตใจและรหัสของคุณโดยไม่ได้รับประโยชน์มากนัก
mortalapeman

คำตอบ:


12

คุณสามารถสร้างคลาสผู้ใช้ที่ไม่มีส่วนเกี่ยวข้องกับ ASP.NET Identity ในไลบรารีหลักของคุณ

public class User {
    public Guid UserId { get; set; }
    public string UserName { get; set; }
    public string EmailAddress { get; set; }
    public string EmailAddressConfirmed { get; set; }
    public string PhoneNumber { get; set; }
    public string PhoneNumberConfirmed { get; set; }
    public string PasswordHash { get; set; }
    public string SecurityStamp { get; set; }

    ...

    public virtual ICollection<Role> Roles { get; set; }
    public virtual ICollection<UserClaim> UserClaims { get; set; }
    public virtual ICollection<UserLogin> UserLogins { get; set; }
}

หากคุณใช้ Entity Framework ให้สร้างคลาสการกำหนดค่าสำหรับเอนทิตีของคุณ (เลือกได้)

internal class UserConfiguration : EntityTypeConfiguration<User>
{
    internal UserConfiguration()
    {
        ToTable("User");

        HasKey(x => x.UserId)
            .Property(x => x.UserId)
            .HasColumnName("UserId")
            .HasColumnType("uniqueidentifier")
            .IsRequired();

        Property(x => x.PasswordHash)
            .HasColumnName("PasswordHash")
            .HasColumnType("nvarchar")
            .IsMaxLength()
            .IsOptional();

        Property(x => x.SecurityStamp)
            .HasColumnName("SecurityStamp")
            .HasColumnType("nvarchar")
            .IsMaxLength()
            .IsOptional();

        Property(x => x.UserName)
            .HasColumnName("UserName")
            .HasColumnType("nvarchar")
            .HasMaxLength(256)
            .IsRequired();

        // EmailAddress, PhoneNumber, ...

        HasMany(x => x.Roles)
            .WithMany(x => x.Users)
            .Map(x =>
            {
                x.ToTable("UserRole");
                x.MapLeftKey("UserId");
                x.MapRightKey("RoleId");
            });

        HasMany(x => x.UserClaims)
            .WithRequired(x => x.User)
            .HasForeignKey(x => x.UserId);

        HasMany(x => x.UserLogins)
            .WithRequired(x => x.User)
            .HasForeignKey(x => x.UserId);
    }
}

คุณต้องสร้างคลาสสำหรับบทบาท UserClaim และ UserLoginด้วย คุณสามารถตั้งชื่อสิ่งที่คุณเลือกหากคุณไม่ชอบชื่อด้านบน

ในเลเยอร์เว็บสร้างคลาสที่ชื่อว่าAppUser (หรือชื่ออื่นถ้าคุณเลือก) คลาสนี้ควรใช้อินเทอร์เฟซASP.NET Identity IUser <TKey>โดยที่TKeyเป็นชนิดข้อมูลสำหรับคีย์หลัก ( Guidในตัวอย่างด้านบน)

public class AppUser : IUser<Guid>
{
    public AppUser()
    {
        this.Id = Guid.NewGuid();
    }

    public AppUser(string userName)
        : this()
    {
        this.UserName = userName;
    }

    public Guid Id { get; set; }
    public string UserName { get; set; }
    public string EmailAddress { get; set; }
    public string EmailAddressConfirmed { get; set; }
    public string PhoneNumber { get; set; }
    public string PhoneNumberConfirmed { get; set; }
    public string PasswordHash { get; set; }
    public string SecurityStamp { get; set; }
}

เปลี่ยนการอ้างอิงทั้งหมดเพื่อ UserManager ในโครงการเว็บเพื่อUserManager <AppUser, Guid>

สุดท้ายสร้างของคุณเองuserStore โดยพื้นฐานแล้ว UserStore แบบกำหนดเองจะใช้ในวัตถุAppUserแปลงเป็นวัตถุเอนทิตีผู้ใช้จากนั้นยืนยัน ตัวอย่างหนึ่งในวิธีการเหล่านี้แสดงไว้ด้านล่าง:

public class UserStore : 
    IUserLoginStore<AppUser, Guid>, 
    IUserClaimStore<AppUser, Guid>, 
    IUserRoleStore<AppUser, Guid>, 
    IUserPasswordStore<AppUser, Guid>, 
    IUserSecurityStampStore<AppUser, Guid>, 
    IUserStore<AppUser, Guid>, 
    IDisposable
{
    private User MapFromAppUser(AppUser appUser)
    {
        if (appUser == null)
            return null;

        var userEntity = new User();

        PopulateUser(userEntity, appUser);

        return userEntity;
    }

    private void PopulateUser(User user, AppUser appUser)
    {
        user.UserId = appUser.Id;
        user.UserName = appUser.UserName;
        user.EmailAddress = appUser.EmailAddress;
        user.EmailAddressConfirmed = appUser.EmailAddressConfirmed;
        user.PhoneNumber = appUser.PhoneNumber;
        user.PhoneNumberConfirmed = appUser.PhoneNumberConfirmed;
        user.PasswordHash = appUser.PasswordHash;
        user.SecurityStamp = appUser.SecurityStamp;

        // First name, last name, ... 
    }

    #region IUserStore<AppUser, Guid> Members

    public Task CreateAsync(AppUser appUser)
    {
        if (appUser == null)
            throw new ArgumentNullException("appUser");

        var userEntity = MapFromAppUser(appUser);

        // Persist the user entity to database using a data repository.
        // I'll leave this to you.
    }

    ...

    #endregion
}

เพื่อให้ได้รายละเอียดทั้งหมดของการดำเนินงานที่เป็นไปได้คลิกที่นี่

ในที่สุดมันก็เป็นทางเลือกของคุณ วัดจำนวนของความพยายามที่จะให้คุณรักษาการใช้งานนี้เมื่อเทียบกับการอ้างอิงกรอบงานประจำตัวในห้องสมุดหลักของคุณ โดยส่วนตัวฉันคิดว่าทำตามที่อธิบายไว้ข้างต้น แต่ฉันไม่ได้เพราะฉันอาจต้องเปลี่ยนรหัสทุกครั้งที่มีการอัพเดตกรอบงาน ASP.NET Identity

หวังว่านี่จะช่วยและตอบคำถามของคุณ!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.