2016-06-12 33 views
5

Wydaje mi się, że mam stosunek nienawiści/miłości do Tożsamości. Uwielbiam to, ponieważ jest kompletnym rozwiązaniem dla większości aplikacji. Ale nienawidzę tego, ponieważ rozszerzanie nie jest łatwym zadaniem. Czuję, że jest bardziej skompleksowany, niż powinien.Jak mogę rozszerzyć tożsamość o niestandardowe atrybuty w ASP.NET MVC?

Próbuję dodać niestandardowe atrybuty i klucze obce do mojego modelu użytkownika, ale wydaje się to bardzo trudne zadanie.

Potrzebuję dodać nowe pole Identity o nazwie UserId, ponieważ Id jest ciągiem, który zostanie automatycznie wygenerowany przez bazę danych. Następnie muszę dodać klucz obcy do modelu Company i inny do modelu Location.

Postępowałem zgodnie z instrukcjami w answer from this other question, próbując dodać dwa nowe klucze obce i móc uzyskać ich wartość od kontrolerów.

Oto, co zrobiłem do tej pory. Moja ApplicationUser klasa po wprowadzone modyfikacje patrzę jak ten

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

ja też stworzył klasę rozszerzeń, które pozwala mi uzyskać wartości z kontrolerami jak tak

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

} 

Ale używam do błędu „poniżej”, gdy próbuję dodać nową migrację

Oto błąd

jeden lub więcej błędów walidacji wykryto duri ng generacji Model

ApplicationUser_Claims_Source_ApplicationUser_Claims_Target:: Wszystkie typy wszystkich właściwości w zależnych rolę referencyjnego ograniczenie musi być taka sama, jak odpowiednich typów własności w główną rolę. Typ właściwości "MyUserId" w obiekcie "IdentityUserClaim" nie jest zgodny z typem właściwości "MyUserId" w jednostce "ApplicationUser" w ograniczeniu referencyjnym "ApplicationUser_Claims". ApplicationUser_Logins_Source_ApplicationUser_Logins_Target:: Typy wszystkich właściwości w roli zależnej więzów referencyjnych muszą być takie same, jak odpowiednie typy właściwości w głównej roli . Typ właściwości "MyUserId" w obiekcie "IdentityUserLogin" nie jest zgodny z typem właściwości "MyUserId" w jednostce "ApplicationUser" w ograniczeniu referencyjnym "ApplicationUser_Logins". ApplicationUser_Roles_Source_ApplicationUser_Roles_Target:: Typy wszystkich właściwości w roli zależnej ograniczenia referencyjnego muszą być takie same, jak odpowiadające im typy właściwości w roli głównej: główna rola . Typ właściwości "MyUserId" w obiekcie "IdentityUserRole" nie jest zgodny z typem właściwości "MyUserId" w podmiocie "ApplicationUser" w ograniczenia referencyjnego "ApplicationUser_Roles".

to polecenie kiedyś stworzył InitialCreate migrację

Add-Migration InitialCreate 

Jak mogę dodać mój klucz obcy i być w stanie uzyskać je z prawidłowo kontrolerów?

+0

Jak zdefiniować 'IdentityUserClaim'? –

+0

Naprawdę uważam, że lepiej jest zachować Tożsamość i resztę twoich jednostek w oddzielnych kontekstach. Tożsamość ma 'UserId', którego możesz później użyć, aby załadować swojego użytkownika z głównego kontekstu. –

+0

@GertArnold Nie dokonałem żadnych zmian w moim 'IdentityUserClaim' –

Odpowiedz

0

Tożsamość pozwala zmienić klucz podstawowy (pole Id) na int. To jest dużo standardowych/pustych klas, ale działa to dla nas. Może to pomogłoby?

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

potem musieliśmy także zwyczaj ApplicationUserStore także

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