Dowemo
0 0 0 0


Question:

I have an ASP.NET Identity 2 implementation (no user data yet just base tables) that I have with a userId of type UNIQUEIDENTIFIER.

The application is a code first and I am using EF6.

Here's the DDL:

CREATE TABLE [dbo].[AspNetUsers] (
    [Id]                   UNIQUEIDENTIFIER NOT NULL,
    [FirstName]            NVARCHAR (MAX) NULL,
    [LastName]             NVARCHAR (MAX) NULL,
    [Email]                NVARCHAR (256) NULL,
    [EmailConfirmed]       BIT            NOT NULL,
    [PasswordHash]         NVARCHAR (MAX) NULL,
    [SecurityStamp]        NVARCHAR (MAX) NULL,
    [PhoneNumber]          NVARCHAR (MAX) NULL,
    [PhoneNumberConfirmed] BIT            NOT NULL,
    [TwoFactorEnabled]     BIT            NOT NULL,
    [LockoutEndDateUtc]    DATETIME       NULL,
    [LockoutEnabled]       BIT            NOT NULL,
    [AccessFailedCount]    INT            NOT NULL,
    [UserName]             NVARCHAR (256) NOT NULL,
    [SubjectId]            INT            DEFAULT ((0)) NOT NULL,
    [SubjectIds]           VARCHAR (50)   NULL,
    [OrganizationId]       INT            DEFAULT ((0)) NOT NULL,
    [OrganizationIds]      VARCHAR (50)   NULL,
    [RoleId]               INT            DEFAULT ((0)) NOT NULL,
    CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE UNIQUE NONCLUSTERED INDEX [UserNameIndex]
    ON [dbo].[AspNetUsers]([UserName] ASC);

I understand that normal the GUID create is a normal GUID.

Can someone tell me how I can make this create a newSequential GUID?

Please note

I am looking for the correct way to do this specifically with ASP.Net Identity 2. In particular I would like to know if any changes are needed to the Identity 2 UserManager etc.


Best Answer:


I was finally able to build the project and run it. A newsequentialid() is assigned to the ID field after creation using Fluent API:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<ApplicationUser>().Property(t => t.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<CustomUserRole>().HasKey(x => new
        {
            x.RoleId,
            x.UserId
        });
        modelBuilder.Entity<CustomUserLogin>().HasKey(x => new
        {
            x.UserId,
            x.ProviderKey,
            x.LoginProvider
        });
    }

The result was SQL table that scripted as:

/****** Object:  Table [dbo].[AspNetUsers]    Script Date: 4/11/2015 3:40:51 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[AspNetUsers](
    [Id] [uniqueidentifier] NOT NULL,
    [Email] [nvarchar](256) NULL,
    [EmailConfirmed] [bit] NOT NULL,
    [PasswordHash] [nvarchar](max) NULL,
    [SecurityStamp] [nvarchar](max) NULL,
    [PhoneNumber] [nvarchar](max) NULL,
    [PhoneNumberConfirmed] [bit] NOT NULL,
    [TwoFactorEnabled] [bit] NOT NULL,
    [LockoutEndDateUtc] [datetime] NULL,
    [LockoutEnabled] [bit] NOT NULL,
    [AccessFailedCount] [int] NOT NULL,
    [UserName] [nvarchar](256) NOT NULL,
 CONSTRAINT [PK_dbo.AspNetUsers] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[AspNetUsers] ADD  DEFAULT (newsequentialid()) FOR [Id]
GO

Had to change the other Entity Types:

public class ApplicationUser : IdentityUser<Guid, CustomUserLogin, CustomUserRole,
    CustomUserClaim>
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public override Guid Id { get; set; }
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, Guid> 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
        return userIdentity;
    }
}
public class CustomUserRole : IdentityUserRole<Guid> { }
public class CustomUserClaim : IdentityUserClaim<Guid> { }
public class CustomUserLogin : IdentityUserLogin<Guid> { }
public class CustomRole : IdentityRole<Guid, CustomUserRole>
{
    public CustomRole() { }
    public CustomRole(string name) { Name = name; }
}
public class CustomUserStore : UserStore<ApplicationUser, CustomRole, Guid,
    CustomUserLogin, CustomUserRole, CustomUserClaim>
{
    public CustomUserStore(ApplicationDbContext context)
        : base(context)
    {
    }
}
public class CustomRoleStore : RoleStore<CustomRole, Guid, CustomUserRole>
{
    public CustomRoleStore(ApplicationDbContext context)
        : base(context)
    {
    }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole,
    Guid, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }

In the Startup.Auth.cs, I changed

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                // Enables the application to validate the security stamp when the user logs in.
                // This is a security feature which is used when you change a password or add an external login to your account.  
                OnValidateIdentity = SecurityStampValidator
                    .OnValidateIdentity<ApplicationUserManager, ApplicationUser, Guid>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentityCallback: (manager, user) =>
                            user.GenerateUserIdentityAsync(manager),
                        getUserIdCallback: (id) => new Guid(id.GetUserId()))
            }
        });            
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

In the IdentityConfig.cs, I changed altered the ApplicationUserManager

Here:

public class ApplicationUserManager : UserManager<ApplicationUser, Guid>
{
    public ApplicationUserManager(IUserStore<ApplicationUser, Guid> store)
        : base(store)
    {
    }
    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    {
        var manager = new ApplicationUserManager(
            new CustomUserStore(context.Get<ApplicationDbContext>()));
        // Configure validation logic for usernames             manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        manager.UserValidator = new UserValidator<ApplicationUser, Guid>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

And

        manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser, Guid>
        {
            MessageFormat = "Your security code is {0}"
        });
        manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser, Guid>
        {
            Subject = "Security Code",
            BodyFormat = "Your security code is {0}"
        });
        manager.EmailService = new EmailService();
        manager.SmsService = new SmsService();
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider =
                new DataProtectorTokenProvider<ApplicationUser, Guid>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
        return manager;
    }
}
// Configure the application sign-in manager which is used in this application.
public class ApplicationSignInManager : SignInManager<ApplicationUser, Guid>

In ManageController.cs, I added

public class ManageController : Controller
{
    private ApplicationSignInManager _signInManager;
    private ApplicationUserManager _userManager;
    private Guid userGuidId;
    public ManageController()
    {
        userGuidId= new Guid(User.Identity.GetUserId());
    }

Replacing userGuidId instead everywhere that I saw userId

I had to use a ToString() here:

BrowserRemembered = await AuthenticationManager.TwoFactorBrowserRememberedAsync(userGuidId.ToString())

In Account Controller, I seem to have only changed

    [AllowAnonymous]
    public async Task<ActionResult> ConfirmEmail(string userId, string code)
    {
        Guid GuidUserId = new Guid(userId);
        if (userId == null || code == null)
        {
            return View("Error");
        }
        var result = await UserManager.ConfirmEmailAsync(GuidUserId, code);
        return View(result.Succeeded ? "ConfirmEmail" : "Error");
    }



Copyright © 2011 Dowemo All rights reserved.    Creative Commons   AboutUs