2016-06-12 66 views
5

我似乎與身份有仇恨/愛情關係。我喜歡它,因爲它是大多數應用程序的完整解決方案。但我討厭它,因爲擴展不是一件容易的事。我覺得它比它應該更加複雜。如何使用ASP.NET MVC中的自定義屬性來擴展身份?

我想將自定義屬性和外鍵添加到我的用戶模型,但它似乎是一項非常困難的任務。

我需要添加一個新的Identity字段,名爲UserId,因爲Id是由數據庫自動生成的字符串。然後,我需要添加一個外鍵到Company模型和另一個模型Location

我按照answer from this other question中的說明嘗試添加兩個新的外鍵,並能夠從我的控制器獲取它們的值。

這是我迄今爲止所做的。我修改後ApplicationUser類我做了這個樣子

public class ApplicationUser : IdentityUser 
{ 
    [Key] 
    public int MyUserId { get; set; } 

    [ForeignKey("Company")] 
    public int CompanyId { get; set; } 

    [ForeignKey("Location")] 
    public int CurrentLocationId { get; set; } 

    public virtual Company Company { get; set; } 

    public virtual Location Location { get; set; } 

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager) 
    { 
     // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType 
     var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); 
     // Add custom user claims here 

     userIdentity.AddClaim(new Claim("MyUserId", this.MyUserId.ToString())); 

     userIdentity.AddClaim(new Claim("CompanyId", this.CompanyId.ToString())); 

     userIdentity.AddClaim(new Claim("CurrentLocationId", this.CurrentLocationId.ToString())); 

     return userIdentity; 
    } 
} 

我還創建了一個擴展類,它可以讓我從控制器的價值觀,像這樣

public static class IdentityExtensions 
{ 
    public static int GetComapnyId(this IIdentity identity) 
    { 
     var claim = ((ClaimsIdentity)identity).FindFirst("ComapnyId"); 
     // Test for null to avoid issues during local testing 
     return (claim != null) ? Int32.Parse(claim.Value) : 0; 
    } 

    public static int GetCurrentLocationId(this IIdentity identity) 
    { 
     var claim = ((ClaimsIdentity)identity).FindFirst("CurrentLocationId"); 
     // Test for null to avoid issues during local testing 
     return (claim != null) ? Int32.Parse(claim.Value) : 0; 
    } 


    public static int GetMyUserId(this IIdentity identity) 
    { 
     var claim = ((ClaimsIdentity)identity).FindFirst("MyUserId"); 
     // Test for null to avoid issues during local testing 
     return (claim != null) ? Int32.Parse(claim.Value) : 0; 
    } 

} 

但我遇到了錯誤「下面列出」當我嘗試添加新的遷移

以下是錯誤檢測杜裏

一個或多個驗證錯誤納克模型生成:

ApplicationUser_Claims_Source_ApplicationUser_Claims_Target:該 類型在參考 約束的從屬地位的所有屬性必須是相同的如在 主體作用相應的屬性類型。實體 'IdentityUserClaim'上的屬性'MyUserId'類型與參考約束 'ApplicationUser_Claims'中 實體'ApplicationUser'上屬性'MyUserId'的類型不匹配。 ApplicationUser_Logins_Source_ApplicationUser_Logins_Target :: 約束的從屬角色中的所有屬性的 類型必須與 主體角色中的對應屬性類型相同。實體 'IdentityUserLogin'上的屬性'MyUserId'類型與 實體'ApplicationUser'中屬性'MyUserId'的類型在參考約束 'ApplicationUser_Logins'中不匹配。 ApplicationUser_Roles_Source_ApplicationUser_Roles_Target::參照約束 的從屬角色中所有屬性的類型 必須與主體 角色中的對應屬性類型相同。實體'IdentityUserRole'上屬性'MyUserId'的類型確實與 參考約束'ApplicationUser_Roles'中的實體'ApplicationUser'上的屬性'MyUserId'的類型不匹配。

這是我用的命令創建的0​​遷移

Add-Migration InitialCreate 

我如何可以加我的外鍵,並能夠正確地控制器讓他們?

+0

你怎麼定義'IdentityUserClaim'? –

+0

我真的認爲更好的是將身份和其他實體保持在不同的上下文中。身份有一個'UserId',您可以稍後使用它來從您的主要上下文加載您的用戶。 –

+0

@GertArnold我沒有改變我的'IdentityUserClaim' –

回答

0

Identity可以將主鍵(Id字段)更改爲int。這是很多樣板/空課,但它對我們很有用。也許這會有所幫助?

public class ApplicationUser : IdentityUser<int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim> 
{ 
    [ForeignKey("Company")] 
    public int CompanyId { get; set; } 

    [ForeignKey("Location")] 
    public int CurrentLocationId { get; set; } 

    public virtual Company Company { get; set; } 

    public virtual Location Location { get; set; } 

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager) 
    { 
     // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType 
     var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); 
     // Add custom user claims here 

     userIdentity.AddClaim(new Claim("CompanyId", this.CompanyId.ToString())); 

     userIdentity.AddClaim(new Claim("CurrentLocationId", this.CurrentLocationId.ToString())); 

     return userIdentity; 
    } 
} 

public class ApplicationUserLogin : IdentityUserLogin<int> 
{ 
} 

public class ApplicationUserRole : IdentityUserRole<int> 
{ 
    [ForeignKey("RoleId")] 
    public virtual ApplicationRole Role { get; set; } 

    [ForeignKey("UserId")] 
    public virtual ApplicationUser User { get; set; } 
} 

public class ApplicationRole : IdentityRole<int, UserRole> 
{ 

} 

public class ApplicationUserClaim : IdentityUserClaim<int> 
{ 
} 

那麼我們也需要一個定製ApplicationUserStore以及

public class ApplicationUserStore : UserStore<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim> 
{ 
    public ApplicationUserStore(DbContext context) 
     : base(context) 
    { 
    } 
}