Binding Dynamic Menu Depending On User Role In ASP MVC

In this article, we are going to learn how to bind a menu depending on the User Role using ASP MVC.
In our projects, sometimes we need to restrict some modules depending on the user level. Here, we will take a real-time example of a  simple inventory management using ASP MVC. Let's see types of roles and module details in our application.


Types of Roles
  • Admin
  • Manager
  • User 
Modules
  • Home
    • Index
    • About Us 
  • Sales
    • New Invoice
    • Update Invoice
    • Delete Invoice 
  • Report
    • Daily Report
    • Date wise Report 
Description of Roles
  • Admin - Admin can see all the modules
  • Manager - Manager also can see all modules
  • User - User can only see Home (Index, About Us) and Sales (New Invoice). A user cannot have permission to see the report details and he/she doesn't have permission to update or delete the created invoice.
Now, let's see how to implement this in our project, step by step.
Step 1 - Create Database and create the required Tables 
First, we will create a database and create the required tables. Here, I have created my database and named it as "SampleMenuMasterDB".
Now, let's create tables. First, we will create a table "tblRoles" and insert some values.  Please find the below images for your reference.
                   
Next, we will create a table "tblLoginand insert some values. Please find the below images for your reference.
NoteHere, we have mapped foreign key with the table "tblRoles" for column RoleId.
 Next, we will create table Menu Configuration tables. Here, I am going to create a table "tblMainMenu" and "tblSubMenu".
                                         
         

Note
Here, I have mapped the foreign key with tables "tblMainMenu" and "tblRoles" for columns MainMenuId and RoleId.

Step 2
Let's create a simple ASP MVC project and bind the menu according to the user roles. Here, I have created my project and named it as "DynamicMenyBind". 
Note - Here, I have selected internet application while creating the project.
Step 3
Let us add a folder "DataModelto add "ADO.Net Entity Data Model". If you want to know how to add Entity model in our project, please refer here.

 
 
Step 4
Next, we will create a "LoginModels" class in our Models folder. Please find the below code for your reference.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.ComponentModel.DataAnnotations;  
  6.   
  7. namespace DynamicMenyBind.Models  
  8. {  
  9.     public class LoginModels  
  10.     {  
  11.         public int UserId { getset; }  
  12.         [Required(ErrorMessage="Please enter the User Name")]  
  13.         public string UserName { getset; }  
  14.         [Required(ErrorMessage = "Please enter the Password")]  
  15.         [DataType(DataType.Password)]  
  16.         public string Password { getset; }  
  17.         public int? UserRoleId { getset; }  
  18.         public string RoleName { getset; }  
  19.     }  
  20. }  
Now, let us create a Controller and name it as "Login".
 
In the Login Controller, let's create a simple "Login" method.
  1. public ActionResult Login()  
  2.         {  
  3.             return View();  
  4.         }  
 To add a View, right click on the method and select "Add View" option. A new dialog window will appear. In that, select strongly-typed View and select your LoginModels class. In scaffold template, select "Create".
 
Now, the View will be created.
 
Note - Here, I have removed some fields like user role id and user role name etc. Because in login page, we need only username and password. That's enough for this page.
Step 5
Let's make some changes in _layout page and web.config.
To modify your layout page , go to View->Shared->_layout.cshtml. Please find the below changes.
  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3. <head>  
  4.   
  5.         @*This CDN links I got from w3 school for Bootstrap Menu*@  
  6.     <title>Bootstrap Example</title>  
  7.     <meta charset="utf-8">  
  8.     <meta name="viewport" content="width=device-width, initial-scale=1">  
  9.     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">  
  10.     <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>  
  11.     <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>  
  12.     <meta name="viewport" content="width=device-width" />  
  13. </head>  
  14. <body>  
  15.       
  16.     <div id="body">  
  17.         @RenderSection("featured", required: false)  
  18.         <div class="container">  
  19.             @RenderBody();  
  20.         </div>  
  21.     </div>  
  22.     @RenderSection("scripts", required: false)  
  23. </body>  
  24. </html>  
Note - I have removed some HTML code from my custom designing. You can do the changes as per your custom design. 
Next, let's change the Form authentication mode and redirect the URL page for our login page if the user is not authenticated.
Please make the below changes in your web.config file.
  1. <authentication mode="Forms">  
  2.       <forms loginUrl="~/Login/Login" timeout="2880" />  
  3.     </authentication>  
Let's run the project. You must get the similar output as given below. 

Step 6
Let's create one more model class in Models folder for Menu Master. Here, I have created a class and named it as "MenuModels". Please refer the below code for your reference.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5.   
  6. namespace DynamicMenyBind.Models  
  7. {  
  8.     public class MenuModels  
  9.     {  
  10.          
  11.         public string MainMenuName { getset; }  
  12.         public int MainMenuId { getset; }  
  13.         public string SubMenuName { getset; }  
  14.         public int SubMenuId { getset; }  
  15.         public string ControllerName { getset; }  
  16.         public string ActionName { getset; }  
  17.         public int? RoleId { getset; }  
  18.         public string RoleName { getset; }  
  19.     }  
  20. }  
Next, let's create a simple Partial View in the shared folder for menu binding.
 
Let's add this Menu partial in the layout page. Please add the HTML code in the layout page. 
  1. <nav>  
  2.     @Html.Partial("_MenuPartial")  
  3.     </nav>  
Let's run and check wether the menu is loaded in top navigation.


Step 7
Now, create another action result method in Login Controller to receive the user input. Then, validate the user input and create the session to maintain the user details.
  1. [HttpPost]  
  2. public ActionResult Login(LoginModels _login)  
  3. {  
  4.     if (ModelState.IsValid) //validating the user inputs  
  5.     {  
  6.         bool isExist = false;  
  7.         using (SampleMenuMasterDBEntities _entity = new SampleMenuMasterDBEntities())  // out Entity name is "SampleMenuMasterDBEntites"  
  8.         {   
  9.             isExist = _entity.tblLogins.Where(x => x.UserName.Trim().ToLower() == _login.UserName.Trim().ToLower()).Any(); //validating the user name in tblLogin table whether the user name is exist or not  
  10.             if (isExist)   
  11.             {  
  12.                 LoginModels _loginCredentials= _entity.tblLogins.Where(x => x.UserName.Trim().ToLower() == _login.UserName.Trim().ToLower()).Select(x => new LoginModels  
  13.                 {  
  14.                     UserName=x.UserName,  
  15.                     RoleName=x.tblRole.Roles,  
  16.                     UserRoleId=x.RoleId,  
  17.                     UserId=x.Id  
  18.                 }).FirstOrDefault();  // Get the login user details and bind it to LoginModels class  
  19.                 List<MenuModels> _menus = _entity.tblSubMenus.Where(x => x.RoleId == _loginCredentials.UserRoleId).Select(x => new MenuModels  
  20.                 {  
  21.                     MainMenuId=x.tblMainMenu.Id,  
  22.                     MainMenuName=x.tblMainMenu.MainMenu,  
  23.                     SubMenuId=x.Id,  
  24.                     SubMenuName=x.SubMenu,  
  25.                     ControllerName=x.Controller,  
  26.                     ActionName=x.Action,  
  27.                     RoleId=x.RoleId,  
  28.                     RoleName=x.tblRole.Roles  
  29.                 }).ToList(); //Get the Menu details from entity and bind it in MenuModels list.  
  30.                 FormsAuthentication.SetAuthCookie(_loginCredentials.UserName, false); // set the formauthentication cookie  
  31.                 Session["LoginCredentials"] = _loginCredentials; // Bind the _logincredentials details to "LoginCredentials" session  
  32.                 Session["MenuMaster"] = _menus; //Bind the _menus list to MenuMaster session  
  33.                 Session["UserName"] = _loginCredentials.UserName;  
  34.                 return RedirectToAction("Index""Home");  
  35.             }  
  36.             else  
  37.             {  
  38.                 ViewBag.ErrorMsg = "Please enter the valid credentials!...";  
  39.                 return View();  
  40.             }  
  41.         }  
  42.     }  
  43.     return View();  
  44. }  
Run the project and test whether the user can see the list of menus or not.


Step 8
Let's add the logout option to clear the session.Add some HTML code in _menupartial page.
  1. <ul class="nav navbar-nav navbar-right">  
  2.     @if (Session["LoginCredentials"] != null)  
  3.     {  
  4.          <li>@Html.ActionLink("Logout", "LogOff", "Login")</li>  
  5.     }  
  6.     else  
  7.     {  
  8.          <li>@Html.ActionLink("Login", "Login", "Login")</li>  
  9.     }  
  10.       
  11.    </ul>  
NoteHere, I have validated - if the LoginCredentials session has a null value, the label will be shown like Login. If it is not, it will be shown like "logoff".
For logout, we have to add logout action result in the Login Controller. Please refer to the below code.
  1. public ActionResult LogOff()  
  2.         {  
  3.             FormsAuthentication.SignOut();  
  4.             Session.Abandon();  
  5.             Session.Clear();  
  6.             Session.RemoveAll();  
  7.             return RedirectToAction("Login""Login");  
  8.         }  
Let's run the project. See the demo output here. 
 

Thanks for reading my article. If you have any comments or queryies, please mention it in the comment box.

Comments

Post a Comment