Jak zmienić typ id w Microsoft.AspNet.Tożsamość./ Align = "left" / Identity
(ASP.NET MVC 5, EF6, VS2013)
Próbuję dowiedzieć się, jak zmienić typ pola " Id " z string na int w typie:
Microsoft.AspNet.Identity.EntityFramework.IdentityUser
Aby nowe konta użytkowników były powiązane z identyfikatorem całkowitym, a nie z identyfikatorem GUID. Ale wydaje się, że będzie to bardziej skomplikowane niż po prostu dodanie nowej właściwości Id z typem int w mojej pochodnej klasie użytkownika. Spójrz na podpis tej metody:
(ze Zgromadzenia Microsoft.AspNet.Tożsamość.Rdzeń.dll)
public class UserManager<TUser> : IDisposable where TUser : global::Microsoft.AspNet.Identity.IUser
{
...
public virtual Task<IdentityResult> AddLoginAsync(string userId, UserLoginInfo login);
...
}
Wydaje się więc, że istnieją inne metody pieczenia w ASP.NET Framework tożsamości, które wymagają, aby userId był ciągiem znaków. Czy muszę ponownie wdrożyć te zajęcia?
Wyjaśnienie dlaczego nie chcę przechowywać identyfikatorów GUID w tabeli użytkownika:
- pojawią się inne tabele, które odnoszą dane do tabeli users za pomocą klucza obcego. (Kiedy użytkownicy zapisują treści na stronie.) Nie widzę powodu, aby używać większych wpisz pole i spędź dodatkową przestrzeń bazy danych bez wyraźnych zalet. (Wiem, że istnieją inne posty na temat korzystania GUIDs vs int ids, ale wydaje się, że wiele sugeruje, że INT ids są szybsze i zużywają mniej miejsca, co wciąż pozostawia mnie zastanawiasz.)
-planuję ujawnić restful endpoint, aby umożliwić użytkownikom pobieranie danych o konkretnym użytkowniku. Myślę:
/users/123/name
Jest czystsza niż
/users/{af54c891-69ba-4ddf-8cb6-00d368e58d77}/name
Czy ktoś wie dlaczego ASP.NET zespół zdecydował się wdrożyć ID w ten sposób? Czy jestem niski widziany w próbie zmiany tego na typ int? (Być może brakuje mi korzyści.)
Dzięki...- Ben
5 answers
Więc jeśli chcesz ID int, musisz utworzyć własną klasę POCO IUser i zaimplementować IUserStore dla swojej niestandardowej klasy IUSER w wydaniu 1.0 RTM.
To jest coś, czego nie mieliśmy czasu na wsparcie, ale zamierzam teraz ułatwić to (ier) w wersji 1.1. Mam nadzieję, że wkrótce coś będzie dostępne w nocnych kompilacjach.
Aktualizacja z przykładem 1.1-alpha1: Jak zdobyć nocne budowle
Jeśli zaktualizujesz do najnowszych bitów nocnych, możesz wypróbuj nowe interfejsy API 1.1-alpha1, które powinny to teraz ułatwić: Oto, jak powinno wyglądać Podłączanie GUID zamiast ciągów, na przykład
public class GuidRole : IdentityRole<Guid, GuidUserRole> {
public GuidRole() {
Id = Guid.NewGuid();
}
public GuidRole(string name) : this() { Name = name; }
}
public class GuidUserRole : IdentityUserRole<Guid> { }
public class GuidUserClaim : IdentityUserClaim<Guid> { }
public class GuidUserLogin : IdentityUserLogin<Guid> { }
public class GuidUser : IdentityUser<Guid, GuidUserLogin, GuidUserRole, GuidUserClaim> {
public GuidUser() {
Id = Guid.NewGuid();
}
public GuidUser(string name) : this() { UserName = name; }
}
private class GuidUserContext : IdentityDbContext<GuidUser, GuidRole, Guid, GuidUserLogin, GuidUserRole, GuidUserClaim> { }
private class GuidUserStore : UserStore<GuidUser, GuidRole, Guid, GuidUserLogin, GuidUserRole, GuidUserClaim> {
public GuidUserStore(DbContext context)
: base(context) {
}
}
private class GuidRoleStore : RoleStore<GuidRole, Guid, GuidUserRole> {
public GuidRoleStore(DbContext context)
: base(context) {
}
}
[TestMethod]
public async Task CustomUserGuidKeyTest() {
var manager = new UserManager<GuidUser, Guid>(new GuidUserStore(new GuidUserContext()));
GuidUser[] users = {
new GuidUser() { UserName = "test" },
new GuidUser() { UserName = "test1" },
new GuidUser() { UserName = "test2" },
new GuidUser() { UserName = "test3" }
};
foreach (var user in users) {
UnitTestHelper.IsSuccess(await manager.CreateAsync(user));
}
foreach (var user in users) {
var u = await manager.FindByIdAsync(user.Id);
Assert.IsNotNull(u);
Assert.AreEqual(u.UserName, user.UserName);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-12 18:01:09
Używając odpowiedzi Stefana Cebulakai wspaniałego artykułu na blogu Bena Fostera ASP.NET Identity Stripped Bare wymyśliłem poniżej rozwiązanie, które zastosowałem do ASP.NET tożsamość 2.0 z wygenerowanym przez Visual Studio 2013 AccountController
.
Rozwiązanie wykorzystuje liczbę całkowitą jako klucz podstawowy dla użytkowników, a także pozwala uzyskać identyfikator aktualnie zalogowanego użytkownika bez konieczności przechodzenia do bazy danych.
Oto kroki, musisz follow:
1. Tworzenie niestandardowych klas związanych z użytkownikiem
Domyślnie AccountController
używa klas, które używają string
jako typu klucza podstawowego. Musimy utworzyć poniżej klasy, które zamiast tego użyją int
. Zdefiniowałem wszystkie poniższe klasy w jednym pliku: AppUser.cs
public class AppUser :
IdentityUser<int, AppUserLogin, AppUserRole, AppUserClaim>,
IUser<int>
{
}
public class AppUserLogin : IdentityUserLogin<int> { }
public class AppUserRole : IdentityUserRole<int> { }
public class AppUserClaim : IdentityUserClaim<int> { }
public class AppRole : IdentityRole<int, AppUserRole> { }
Przydatne będzie również posiadanie niestandardowego ClaimsPrincipal, który z łatwością ujawni identyfikator użytkownika.]}
public class AppClaimsPrincipal : ClaimsPrincipal
{
public AppClaimsPrincipal( ClaimsPrincipal principal ) : base( principal )
{ }
public int UserId
{
get { return int.Parse(this.FindFirst( ClaimTypes.Sid ).Value); }
}
}
2. Tworzenie niestandardowego IdentityDbContext
Kontekst bazy danych naszej aplikacji będzie extend IdentityDbContext
, który domyślnie implementuje wszystkie zestawy Dbsetów związane z uwierzytelnieniem. Nawet jeśli DbContext.OnModelCreating
jest metodą pustą, nie jestem pewien co do IdentityDbContext.OnModelCreating
, więc przy nadpisywaniu pamiętaj o wywołaniu base.OnModelCreating( modelBuilder )
AppDbContext.cs
public class AppDbContext :
IdentityDbContext<AppUser, AppRole, int, AppUserLogin, AppUserRole, AppUserClaim>
{
public AppDbContext() : base("DefaultConnection")
{
// Here use initializer of your choice
Database.SetInitializer( new CreateDatabaseIfNotExists<AppDbContext>() );
}
// Here you define your own DbSet's
protected override void OnModelCreating( DbModelBuilder modelBuilder )
{
base.OnModelCreating( modelBuilder );
// Here you can put FluentAPI code or add configuration map's
}
}
3. Utwórz własne UserStore
i UserManager
, które użyją powyższego
AppUserStore.cs
public interface IAppUserStore : IUserStore<AppUser, int>
{
}
public class AppUserStore :
UserStore<AppUser, AppRole, int, AppUserLogin, AppUserRole, AppUserClaim>,
IAppUserStore
{
public AppUserStore() : base( new AppDbContext() )
{
}
public AppUserStore(AppDbContext context) : base(context)
{
}
}
AppUserManager.cs
public class AppUserManager : UserManager<AppUser, int>
{
public AppUserManager( IAppUserStore store ) : base( store )
{
}
}
4. Modyfikuj AccountController
, aby używać własnych klas
Zmień wszystkie UserManager
na AppUserManager
, UserStore
do AppUserStore
itd. Weźmy na przykład konstruktorzy:
public AccountController()
: this( new AppUserManager( new AppUserStore( new AppDbContext() ) ) )
{
}
public AccountController(AppUserManager userManager)
{
UserManager = userManager;
}
5. Pliki cookies wykorzystywane są w celu:]}
W kroku 1 utworzyliśmy AppClaimsPrincipal
, który wyświetla identyfikator UserId usunięty z ClaimType.Sid
. Aby jednak to roszczenie było dostępne, musimy je dodać, podczas logowania użytkownika. W AccountController
za logowanie odpowiada metoda SingInAsync
. Musimy dodać linię do tej metody, aby dodać twierdzenie.
private async Task SignInAsync(AppUser user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
ClaimsIdentity identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
// Extend identity claims
identity.AddClaim( new Claim( ClaimTypes.Sid, user.Id.ToString() ) );
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
6. Tworzenie BaseController
z CurrentUser
właściwością
private async Task SignInAsync(AppUser user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
ClaimsIdentity identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
// Extend identity claims
identity.AddClaim( new Claim( ClaimTypes.Sid, user.Id.ToString() ) );
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
BaseController
z CurrentUser
właściwością Aby mieć łatwy dostęp do aktualnie zalogowanego w ID użytkownika w kontrolerach Utwórz abstrakcję BaseController
, z której będą wywodzić się kontrolerzy. W BaseController
Utwórz CurrentUser
w następujący sposób:
public abstract class BaseController : Controller
{
public AppClaimsPrincipal CurrentUser
{
get { return new AppClaimsPrincipal( ( ClaimsPrincipal )this.User ); }
}
public BaseController()
{
}
}
7. Odziedzicz Kontrolery z BaseController
i ciesz się
Od teraz możesz używać CurrentUser.UserId
w swoich kontrolerach, aby uzyskać dostęp do identyfikatora aktualnie zalogowanego użytkownika bez podróży do bazy danych. Można go używać do odpytywania tylko obiektów, które należą do użytkownika.
Nie musisz dbać o Automatyczne generowanie użytkownika klucze-nic dziwnego, struktura Entity domyślnie używa tożsamości dla kluczy podstawowych integer, podczas tworzenia tabel.
Uwaga! pamiętaj, że jeśli zaimplementujesz go w już wydanym projekcie, dla już zalogowanych użytkowników ClaimsType.Sid
nie będzie istnieć i FindFirst
zwróci null w AppClaimsPrincipal
. W tym celu musisz wymusić wylogowanie wszystkich użytkowników lub obsłużyć ten scenariusz w AppClaimsPrincipal
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:19
@ HaoKung
Udało mi się zrobić int id z Twoimi nocnymi budami. Użytkownik.Tożsamość.Problem z GetUserId() nadal istnieje, ale właśnie zrobiłem int.parse() na razie.Największą niespodzianką było to,że nie musiałem sam tworzyć ID, db zostało wykonane z identity i jakoś automatycznie ustawione dla nowych użytkowników OO...
Model:
public class ApplicationUser : IdentityUser<int, IntUserLogin, IntUserRole, IntUserClaim>
{
public ApplicationUser()
{
}
public ApplicationUser(string name) : this() { UserName = name; }
}
public class ApplicationDbContext : IntUserContext
{
public ApplicationDbContext()
{
}
}
private class IntRole : IdentityRole<int, IntUserRole>
{
public IntRole()
{
}
public IntRole(string name) : this() { Name = name; }
}
private class IntUserRole : IdentityUserRole<int> { }
private class IntUserClaim : IdentityUserClaim<int> { }
private class IntUserLogin : IdentityUserLogin<int> { }
private class IntUserContext : IdentityDbContext<ApplicationUser, IntRole, int, IntUserLogin, IntUserRole, IntUserClaim>
{
public IntUserContext()
: base("DefaultConnection")
{
}
}
private class IntUserStore : UserStore<ApplicationUser, IntRole, int, IntUserLogin, IntUserRole, IntUserClaim>
{
public IntUserStore(DbContext context)
: base(context)
{
}
}
private class IntRoleStore : RoleStore<IntRole, int, IntUserRole>
{
public IntRoleStore(DbContext context)
: base(context)
{
}
}
Kontroler:
public AccountController()
: this(new UserManager<ApplicationUser, int>(new IntUserStore(new ApplicationDbContext())))
{
}
public AccountController(UserManager<ApplicationUser, int> userManager)
{
UserManager = userManager;
}
public UserManager<ApplicationUser, int> UserManager { get; private set; }
Mam nadzieję, że release build już wkrótce: D...
P. S. nie mogę pisać komentarzy więc odpowiedziałem, przepraszam.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-02 02:37:07
W Visual Studio 2013 domyślna aplikacja internetowa używa wartości ciągu dla klucza dla kont użytkowników. ASP.NET tożsamość umożliwia zmianę typu klucza, aby spełnić wymagania dotyczące danych. Na przykład można zmienić typ klucza z ciągu znaków na liczbę całkowitą.
Http://www.asp.net/identity/overview/extensibility/change-primary-key-for-users-in-aspnet-identity
Ten temat na powyższym linku pokazuje jak zacząć od domyślnej aplikacji internetowej i Zmień klucz konta użytkownika na liczbę całkowitą. Możesz użyć tych samych modyfikacji, aby zaimplementować dowolny typ klucza w swoim projekcie. Pokazuje, jak wprowadzić te zmiany w domyślnej aplikacji internetowej, ale można zastosować podobne modyfikacje do niestandardowej aplikacji. Pokazuje zmiany potrzebne podczas pracy z MVC lub formularzami webowymi.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-02 19:19:41
W zasadzie musisz:
- Zmiana typu klucza na int w klasie Identity user
-Dodaj niestandardowe klasy tożsamości, które używają int jako klucza
-Zmień klasę kontekstową i menedżera użytkowników na Int jako klucz
-Zmień konfigurację uruchamiania, aby użyć int jako klucza
-Zmień AccountController, aby przekazać int jako klucz
Tutaj {[10] } jest link, gdzie wszystkie kroki są wyjaśnione, aby to osiągnąć.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-29 09:37:45