Git Product home page Git Product logo

userandroles's Introduction

UserAndRoles

This demo shows a way to extend ASP .NET Identity 2 - adding navigation properties between ApplicatiionUser and IdentityRole.

Requirements

  • Visual studio 2015
  • SQL Server
  • 2 GB RAM
  • ASP .NET knowledge

Installation

  • Download this repository or clone it.
  • Open .sln file with Visual Studio.
  • Check Web.Config and set the server.
  • Compile the project and run.

Source code

UserAndRoles/UserAndRolesDemo/UserAndRolesDemo/

Description

For this tutorial is used default ASP .Net MVC 5 Template with Individual users. By default when you try access the roles of a user it will return a collection of IdentityUserRole which is a relation mapping between users and roles:

ICollection<IdentityUserRole> roles = new ApplicationDbContext().Users.FirstOrDefault().Roles;
    
foreach(var role in roles)
{
    Console.WriteLine($"{role.UserId} {role.RoleId}");
    // But how to get the role name ?
}

Of course UserManager<User> can be used. It have a method for GetRoles(stirng id). But in most situations a user can be associated with many roles, so this method must be called for each user. RoleManage doesn't have an option to get users for a role.

To deal with User and Roles in ASP. NET, you should make some changes:

  • Open IdentityModels.cs.
  • Create class UserRoles that inherits IdentityUserRole and add two navigation properties:
public class UserRoles : IdentityUserRole
{
    public virtual User User { get; set; }
    public virtual Role Role { get; set; }
}
  • Create class Role that inherits IdentityRole<string, UserRoles>.
  • Don't forget to generate Id for the role. (If the Id is number, you can set the auto-increment option when OnModelCreating occurs):
public class Role : IdentityRole<string, UserRoles>
{
    public Role()
    {
        this.Id = Guid.NewGuid().ToString();
    }
}
  • You can rename ApplicationUser as in this example it is just User.
  • Inherit IdentityUser<string, IdentityUserLogin, UserRoles, IdentityUserClaims>:
  • GenerateUserIdentityAsync should change the type of parameter to UserManager<User, string>
  • Don't forget to generate Id. Same as the Role class.
  • You can extend this class with additional properties.
public class User : IdentityUser<string, IdentityUserLogin, UserRoles, IdentityUserClaim>
{
   public User()
   {
      this.Id = Guid.NewGuid().ToString();
   }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User, string> 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 int Age { get; set; }
   
    public string Description { get; set; }
}
  • Now ApplicationDbContext should inherits IdentityDbContext<User, Role, string, IdentityUserLogin, UserRoles, IdentityUserClaim>
public class ApplicationDbContext : IdentityDbContext<User, Role, string, IdentityUserLogin, UserRoles, IdentityUserClaim>
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

When you try to compile the project you will receive few errors. In IdentityConfig.cs ApplicationUserManager shoud be changed a little. Inherit UserManager<User, string>, change the type of parameter in the constructor to IUserStore<User, string>. In Create method: initializtion of UserStore should be changed. Everywhere UserStore is required, use it like : new UserStore<User, Role, string, IdentityUserLogin, UserRoles, IdentityUserClaim>(context):

public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
{
    var store = new UserStore<User, Role, string, IdentityUserLogin, UserRoles, IdentityUserClaim>(context.Get<ApplicationDbContext>());
    new ApplicationUserManager(store);
    var manager = new ApplicationUserManager(store);
    // Configure validation logic for usernames
    manager.UserValidator = new UserValidator<User>(manager)
    {
        AllowOnlyAlphanumericUserNames = false,
        RequireUniqueEmail = true
    };
    
  /// the rest of the code is not changed.

After run this project. The database structure remains the same. Diagram

Let's check GetUsersAndTheirRoles() method in HomeController.cs. The old way to get roles is not good, because it makes many queries to the database and it may be slow.

var userManager = new UserManager<IdentityUser>(new UserStore<IdentityUser>());
IEnumerable<IdentityUser> dbUsers = userManager.Users.ToList();

foreach (var user in dbUsers)
{
    model.Add(new UserViewModel()
    {
        UserName = user.UserName,
        Roles = userManager.GetRoles(user.Id)
    });
}

The SOLUTION :

model = new ApplicationDbContext().Users.Include(u => u.Roles).Select(u => new UserViewModel()
{
    Age = u.Age,
    UserName = u.UserName,
    Roles = u.Roles.Select(r => r.Role.Name) // now "r" will have the Role class which has a "Name"
}) 
.ToList();

Now this gets all users with their roles with minimum effort (one query).

In this tutorial the best code practices are not applied, example: Initializing the context in the controller. It is just for example how IdentityUserRole can be extended. Also view models are used for displaying inforamtion from database. (It's is highly recommended to use View Models in MVC).

Note: copy-pasting may cause many errors, so read carefully.

Web-Site Explanation

  • When the site is initialized, Global.asax.cs is configured to create 5 roles (Admin,Editor,Manager,Developer,Tester) and 1 user associated with Admin and Manager roles. And all this into the database.
  • To login use Administrator for username(email) and 123456 for password
  • In the home screen you will see in top information for current logged user and a dropdown menu with roles allows to add current user to the role.

  • Below are two tables. In the first table are all users and roles for each one. First column represents the user name and the second column represents the roles associated.
  • In the second table are listed all roles and users associated with each one. First column represents the role name and the second users associated with this role.

  • To test functionallity: register few users and associate this user in roles of your choice.
  • Sample screenshots:

*There are typo Rditor shoild be Editor

Resources

Extending identityuserrole in identity 2

ASP NET Identity Customizing Users and Roles

applicationuser and applicationrole navigation properties in identity 2

Extending primarykey of identityuserrole in identity 2

Questions & Issues

If you have questions, ideas or you found a bug, feel free to submit an issue here.

All Issues.

Tags

ASP .NET ASP Identity Entity Framework ASP .NET MVC MSSQL IdentityUserRole Microsoft Extends Navigation property Relation Users ASP User Role ASP Roles

userandroles's People

Contributors

m-yankov avatar

Watchers

 avatar  avatar

userandroles's Issues

Can this be used in NET Core

I am almost 100% sure that there is a way to make a Navigation properties between Users and Roles, except there is already implemented such functionallity.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.