0
votes

I'm using ASP.Net Identity 2 and EF6 code first migrations for this project and I'm struggling to create a table to link 3 other tables. I have the following:

  • Company
  • ApplicationUser (AspNetUsers)
  • ApplicationRole (AspNetRoles)
  • AspNetUserRoles

The tricky bit is to relate the AspNetUserRoles with the Company table, because a user can have roles in different companies and can also have a role that's not related to any company. So ideally the resulting table I need would be something like:

  • CompanyUserRoles(companyId, UserRoleId[this is not roleID]) or even (companyId, roleid,userid)

Another option would be to add another field (companyId) to the AspNetUserRoles table.

It's kind of confusing how can I achieve this with code first and what implications would it have when it comes to the UserManager and RoleManager (do I need to create custom ones?).

Any guidance would be greatly appreciated.

1
did you find any solutions to this?Safi Mustafa

1 Answers

0
votes

According to the same source code and write the code yourself walking assumptions now. First, you create new project in vs with mvc(c#) and select project type on mvc. Then, after create project you should change some classes Identity. I want change to type UserId that has been Nvarchar(128) to Bigint in table AspNetUsers. Step one to seven are in IdentityModels.cs.

step one: you change class IdentityModels.cs to according to the:

ApplicationUser : IdentityUser

change to : ApplicationUser : IdentityUser<long, CustomUserLogin, CustomUserRole, CustomUserClaim>.

Step two: create classes:

public class CustomUserRole : IdentityUserRole<long> { }
public class CustomUserClaim : IdentityUserClaim<long> { }
public class CustomUserLogin : IdentityUserLogin<long> { }

step three: change class according to the :

public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, long> manager)

Step four: change class according to the :

 public class CustomRole : IdentityRole<long, CustomUserRole>

Step five: change class according to the :

 public class CustomUserStore : UserStore<ApplicationUser, CustomRole, long, CustomUserLogin, CustomUserRole, CustomUserClaim>

Step six: change class according to the :

public class CustomRoleStore : RoleStore<CustomRole, long, CustomUserRole>

Step seven: change class according to the :

 public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole, long, CustomUserLogin, CustomUserRole, CustomUserClaim>

and add method below to IdentityModels.cs according your table field:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        //modelBuilder.Entity<CustomUserLogin>()
        //.HasKey(r => new { r.UserId })
        //.ToTable("tblRoles");

        //modelBuilder.Entity<CustomUserLogin>()
        //    .HasKey(l => new { l.LoginProvider, l.ProviderKey, l.UserId })
        //    .ToTable("tblMembers");

        modelBuilder.Entity<IdentityUser>().HasKey(r => new { r.Id }).ToTable("tblMembers1").Property(p => p.Id).HasColumnName("UserID");
        modelBuilder.Entity<ApplicationUser>().HasKey(r => new { r.Id }).ToTable("tblMembers").Property(p => p.Id).HasColumnName("UserID");
        modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId }).ToTable("tblRoless");
        modelBuilder.Entity<IdentityUserLogin>().HasKey(r => new { r.UserId }).ToTable("tblLogins");
        modelBuilder.Entity<IdentityUserClaim>().HasKey(r => new { r.Id }).ToTable("tblUserClaims");
        modelBuilder.Entity<IdentityRole>().HasKey(r => new { r.Id }).ToTable("tblRoloess");
    }

In AccountControllers.cs change according to the :

 private bool HasPassword()
    {
        var user = UserManager.FindById(User.Identity.GetUserId<long>());

        if (user != null)
        {
            return user.PasswordHash != null;
        }

        return false;
    }
    public virtual ActionResult RemoveAccountList()
    {
        var linkedAccounts = UserManager.GetLogins(User.Identity.GetUserId<long>());
        ViewBag.ShowRemoveButton = HasPassword() || linkedAccounts.Count > 1;
        return PartialView("_RemoveAccountPartial", linkedAccounts);
    }
    public virtual async Task<ActionResult> Disassociate(string loginProvider, string providerKey)
    {
        ManageMessageId ? message = null;
        IdentityResult result = await UserManager.RemoveLoginAsync(
            User.Identity.GetUserId<long>(),
            new UserLoginInfo(loginProvider, providerKey));

        if (result.Succeeded)
        {
            var user = await UserManager.FindByIdAsync(User.Identity.GetUserId<long>());
            await SignInAsync(user, isPersistent: false);
            message = ManageMessageId.RemoveLoginSuccess;
        }
        else
        {
            message = ManageMessageId.Error;
        }

        return RedirectToAction("Manage", new { Message = message });
    }

    private async Task SignInAsync(ApplicationUser user, bool isPersistent)
    {
        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
        AuthenticationManager.SignIn(new AuthenticationProperties()
        { IsPersistent = isPersistent },
                                        await user.GenerateUserIdentityAsync(UserManager));
    }

And IdentityConfig.cs change according to the :

  public class EmailService : IIdentityMessageService
{
    public Task SendAsync(IdentityMessage message)
    {
        // Plug in your email service here to send an email.
        return Task.FromResult(0);
    }
}

public class SmsService : IIdentityMessageService
{
    public Task SendAsync(IdentityMessage message)
    {
        // Plug in your SMS service here to send a text message.
        return Task.FromResult(0);
    }
}

// Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application.
public class ApplicationUserManager : UserManager<ApplicationUser, long>
{
    public ApplicationUserManager(IUserStore<ApplicationUser, long> 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, long>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };
        // Configure validation logic for passwords 
        manager.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };
        // Register two factor authentication providers. This application uses Phone 
        // and Emails as a step of receiving a code for verifying the user 
        // You can write your own provider and plug in here. 
        manager.RegisterTwoFactorProvider("PhoneCode",
            new PhoneNumberTokenProvider<ApplicationUser, long>
            {
                MessageFormat = "Your security code is: {0}"
            });
        manager.RegisterTwoFactorProvider("EmailCode",
            new EmailTokenProvider<ApplicationUser, long>
            {
                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, long>(
                    dataProtectionProvider.Create("ASP.NET Identity"));
        }
        return manager;
    }

    // Configure the application sign-in manager which is used in this application.
}

public class ApplicationSignInManager : SignInManager<ApplicationUser, long>
{
    public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) : base(userManager, authenticationManager)
    {
    }

    public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
    {
        return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
    }

    public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
    {
        return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
    }
}

Then, in windows Package Manager Console in Tools menu write commands below for add migration :

Enable migrations  

Then :

Add-migration TestMig

According the image: enter image description here

Best regards.