(ASP.NET MVC 5、EF6、VS2013)
「Id」フィールドのタイプをstringからintに変更するの方法を見つけようとしています。
Microsoft.AspNet.Identity.EntityFramework.IdentityUser
新しいユーザーアカウントをGUIDではなく整数IDに関連付けるため。しかし、これは単純に、派生ユーザークラスにint型の新しいIdプロパティを追加するよりも複雑になるようです。このメソッドシグネチャを見てください。
(アセンブリMicrosoft.AspNet.Identity.Core.dllから)
public class UserManager<TUser> : IDisposable where TUser : global::Microsoft.AspNet.Identity.IUser
{
...
public virtual Task<IdentityResult> AddLoginAsync(string userId, UserLoginInfo login);
...
}
したがって、ASP.NET IDフレームワークに焼き付けられた他のメソッドがあり、userIdを文字列にする必要があるようです。これらのクラスも再実装する必要がありますか?
IDのGUIDをユーザーテーブルに保存したくない理由の説明:
-外部キーを介してユーザーテーブルにデータを関連付ける他のテーブルがあります。 (ユーザーがサイトにコンテンツを保存するとき。)より大きなフィールドタイプを使用し、明確な利点のない余分なデータベーススペースを使用する理由はありません。 (GUIDとint idの使用に関する他の投稿があることは知っていますが、int idの方が高速でスペースが少ないことを多くの人が示唆しているようです。
-ユーザーが特定のユーザーに関するデータを取得できるように、安らかなエンドポイントを公開する予定です。おもう:
/users/123/name
よりきれいです
/users/{af54c891-69ba-4ddf-8cb6-00d368e58d77}/name
ASP.NETチームがこの方法でIDを実装することにした理由は誰にもわかりますか?これをint型に変更しようとすると、近視眼的ですか? (おそらく私が見逃している利点があります。)
ありがとう...
-ベン
したがって、int idが必要な場合は、独自のPOCO IUserクラスを作成し、1.0 RTMリリースでカスタムIUserクラスのIUserStoreを実装する必要があります。
これはサポートする時間がありませんでしたが、現時点では1.1でこれを簡単にすることを検討しています。うまくいけば、すぐにナイトリービルドで何かが利用できるようになります。
1.1-alpha1の例で更新:ナイトリービルドの入手方法
毎晩最新のビットに更新する場合は、新しい1.1-alpha1 APIを試してみてください。これにより、これがより簡単になります。
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);
}
}
Stefan Cebulak の回答とBen Fosterの素晴らしいブログ記事を使用 ASP.NET Identity Stripped Bare ASP.NETに適用した以下のソリューションを思い付きましたID2.0とVisual Studio 2013 AccountController
によって生成されます。
このソリューションでは、整数をユーザーの主キーとして使用し、データベースにアクセスせずに現在ログインしているユーザーのIDを取得することもできます。
手順は次のとおりです。従う必要があります。
デフォルトでは、AccountController
は、string
を使用しているクラスを主キーのタイプとして使用します。代わりにint
を使用する以下のクラスを作成する必要があります。 1つのファイルで以下のすべてのクラスを定義しました: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> { }
また、ユーザーのIDを簡単に公開するカスタムClaimsPrincipalがあると便利です。
public class AppClaimsPrincipal : ClaimsPrincipal
{
public AppClaimsPrincipal( ClaimsPrincipal principal ) : base( principal )
{ }
public int UserId
{
get { return int.Parse(this.FindFirst( ClaimTypes.Sid ).Value); }
}
}
IdentityDbContext
を作成しますアプリケーションのデータベースコンテキストはIdentityDbContext
を拡張し、デフォルトですべての認証関連のDbSetを実装します。 DbContext.OnModelCreating
が空のメソッドであっても、IdentityDbContext.OnModelCreating
がわからないため、オーバーライドするときは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
}
}
UserStore
およびUserManager
を作成します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 )
{
}
}
AccountController
を変更してカスタムクラスを使用するすべてのUserManager
をAppUserManager
に、UserStore
をAppUserStore
などに変更します。このコンストラクターの例を挙げます。
public AccountController()
: this( new AppUserManager( new AppUserStore( new AppDbContext() ) ) )
{
}
public AccountController(AppUserManager userManager)
{
UserManager = userManager;
}
ClaimIdentity
へのクレームとしてユーザーのIDを追加しますステップ1では、ClaimType.Sid
から取得したUserIdを公開するAppClaimsPrincipal
を作成しました。ただし、この要求を使用可能にするには、ユーザーのログイン時に要求を追加する必要があります。 AccountController
では、SingInAsync
メソッドがログインを担当します。クレームを追加するには、このメソッドに行を追加する必要があります。
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
プロパティでCurrentUser
を作成しますコントローラーで現在ログインしているユーザーのIDに簡単にアクセスできるようにするには、抽象BaseController
を作成します。これからコントローラーが派生します。 BaseController
で、次のようにCurrentUser
を作成します。
public abstract class BaseController : Controller
{
public AppClaimsPrincipal CurrentUser
{
get { return new AppClaimsPrincipal( ( ClaimsPrincipal )this.User ); }
}
public BaseController()
{
}
}
BaseController
からコントローラーを継承してお楽しみくださいこれ以降、コントローラーでCurrentUser.UserId
を使用して、データベースにアクセスせずに現在ログインしているユーザーのIDにアクセスできます。これを使用して、ユーザーに属するオブジェクトのみを照会できます。
ユーザーの主キーの自動生成を行う必要はありません-驚くことではありませんが、Entity Frameworkは、テーブルを作成するときにデフォルトで整数の主キーにIdentityを使用します。
警告!既にリリースされたプロジェクトに実装する場合、すでにログインしているユーザーはClaimsType.Sid
は存在せず、FindFirst
はAppClaimsPrincipal
にnullを返します。すべてのユーザーを強制的にログアウトするか、AppClaimsPrincipal
でこのシナリオを処理する必要があります。
しゅう
あなたのナイトリービルドでint idを作ることに成功しました。 User.Identity.GetUserId()の問題はまだありますが、とりあえずint.parse()をしました。
最大の驚きは、自分でIDを作成する必要がなかったことです。dbはID idで作成され、新しいユーザー向けに自動的に設定されました。
型:
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)
{
}
}
コントローラ:
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; }
リリースビルドがすぐに来ることを願っています:D ...
追伸コメントを書くことができないので、回答しました、ごめんなさい。
述べたように ここ :
Visual Studio 2013では、デフォルトのWebアプリケーションはユーザーアカウントのキーに文字列値を使用します。 ASP.NET Identityを使用すると、データ要件に合わせてキーのタイプを変更できます。たとえば、キーのタイプを文字列から整数に変更できます。
上記のリンクのこのトピックでは、デフォルトのWebアプリケーションから開始し、ユーザーアカウントキーを整数に変更する方法を示します。同じ変更を使用して、プロジェクトに任意のタイプのキーを実装できます。デフォルトのWebアプリケーションでこれらの変更を行う方法を示していますが、カスタマイズされたアプリケーションに同様の変更を適用することもできます。 MVCまたはWebフォームで作業するときに必要な変更を示しています。
基本的にあなたがする必要があります:
-Identityユーザークラスでキーのタイプをintに変更する
-intをキーとして使用するカスタマイズされたIdentityクラスを追加します
-コンテキストクラスとユーザーマネージャーを変更して、intをキーとして使用する
-起動設定を変更して、intをキーとして使用する
-AccountControllerを変更して、intをキーとして渡す
here は、これを達成するためのすべての手順が説明されているリンクです。