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 "tblLogin" and 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.
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 "DataModel" to 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.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.ComponentModel.DataAnnotations;
- namespace DynamicMenyBind.Models
- {
- public class LoginModels
- {
- public int UserId { get; set; }
- [Required(ErrorMessage="Please enter the User Name")]
- public string UserName { get; set; }
- [Required(ErrorMessage = "Please enter the Password")]
- [DataType(DataType.Password)]
- public string Password { get; set; }
- public int? UserRoleId { get; set; }
- public string RoleName { get; set; }
- }
- }
In the Login Controller, let's create a simple "Login" method.
- public ActionResult Login()
- {
- return View();
- }
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.
- <!DOCTYPE html>
- <html lang="en">
- <head>
- @*This CDN links I got from w3 school for Bootstrap Menu*@
- <title>Bootstrap Example</title>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
- <meta name="viewport" content="width=device-width" />
- </head>
- <body>
- <div id="body">
- @RenderSection("featured", required: false)
- <div class="container">
- @RenderBody();
- </div>
- </div>
- @RenderSection("scripts", required: false)
- </body>
- </html>
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.
- <authentication mode="Forms">
- <forms loginUrl="~/Login/Login" timeout="2880" />
- </authentication>
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.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- namespace DynamicMenyBind.Models
- {
- public class MenuModels
- {
- public string MainMenuName { get; set; }
- public int MainMenuId { get; set; }
- public string SubMenuName { get; set; }
- public int SubMenuId { get; set; }
- public string ControllerName { get; set; }
- public string ActionName { get; set; }
- public int? RoleId { get; set; }
- public string RoleName { get; set; }
- }
- }
Let's add this Menu partial in the layout page. Please add the HTML code in the layout page.
- <nav>
- @Html.Partial("_MenuPartial")
- </nav>
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.
- [HttpPost]
- public ActionResult Login(LoginModels _login)
- {
- if (ModelState.IsValid) //validating the user inputs
- {
- bool isExist = false;
- using (SampleMenuMasterDBEntities _entity = new SampleMenuMasterDBEntities()) // out Entity name is "SampleMenuMasterDBEntites"
- {
- 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
- if (isExist)
- {
- LoginModels _loginCredentials= _entity.tblLogins.Where(x => x.UserName.Trim().ToLower() == _login.UserName.Trim().ToLower()).Select(x => new LoginModels
- {
- UserName=x.UserName,
- RoleName=x.tblRole.Roles,
- UserRoleId=x.RoleId,
- UserId=x.Id
- }).FirstOrDefault(); // Get the login user details and bind it to LoginModels class
- List<MenuModels> _menus = _entity.tblSubMenus.Where(x => x.RoleId == _loginCredentials.UserRoleId).Select(x => new MenuModels
- {
- MainMenuId=x.tblMainMenu.Id,
- MainMenuName=x.tblMainMenu.MainMenu,
- SubMenuId=x.Id,
- SubMenuName=x.SubMenu,
- ControllerName=x.Controller,
- ActionName=x.Action,
- RoleId=x.RoleId,
- RoleName=x.tblRole.Roles
- }).ToList(); //Get the Menu details from entity and bind it in MenuModels list.
- FormsAuthentication.SetAuthCookie(_loginCredentials.UserName, false); // set the formauthentication cookie
- Session["LoginCredentials"] = _loginCredentials; // Bind the _logincredentials details to "LoginCredentials" session
- Session["MenuMaster"] = _menus; //Bind the _menus list to MenuMaster session
- Session["UserName"] = _loginCredentials.UserName;
- return RedirectToAction("Index", "Home");
- }
- else
- {
- ViewBag.ErrorMsg = "Please enter the valid credentials!...";
- return View();
- }
- }
- }
- return View();
- }
Step 8
Let's add the logout option to clear the session.Add some HTML code in _menupartial page.
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".
- <ul class="nav navbar-nav navbar-right">
- @if (Session["LoginCredentials"] != null)
- {
- <li>@Html.ActionLink("Logout", "LogOff", "Login")</li>
- }
- else
- {
- <li>@Html.ActionLink("Login", "Login", "Login")</li>
- }
- </ul>
For logout, we have to add logout action result in the Login Controller. Please refer to the below code.
- public ActionResult LogOff()
- {
- FormsAuthentication.SignOut();
- Session.Abandon();
- Session.Clear();
- Session.RemoveAll();
- return RedirectToAction("Login", "Login");
- }
Thanks for reading my article. If you have any comments or queryies, please mention it in the comment box.
how to navigate to next page
ReplyDelete