65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET MVC 基于用户角色的菜单管理 - 使用 WEB API 和 AngularJS

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.97/5 (29投票s)

2016年2月2日

CPOL

13分钟阅读

viewsIcon

136292

downloadIcon

6636

在本文中,我们将学习如何使用 ASP.NET MVC、WEB API 和 AngularJS 创建和管理基于用户角色的菜单。

在开始阅读本文之前,请先阅读我之前的文章 ASP.NET MVC 5 安全和创建用户角色。它详细介绍了 ASP.NET Identity 和创建用户角色。

引言

在本文中,我们将学习如何使用 ASP.NET MVC、WEB API 和 AngularJS 创建和管理基于用户角色的菜单。

在这里,我们将学习如何执行以下操作:

  1. 管理员菜单管理(只有管理员用户可以查看所有/创建/删除编辑菜单
  2. 按用户角色创建菜单(管理员可以选择用户角色来创建菜单)
  3. 按用户角色显示和隐藏动态菜单和子菜单
  4. 按用户角色动态显示菜单(这里我们将其称为动态菜单,因为在每个页面或主页面上,我们都将从数据库加载菜单,并根据用户的角色向每个用户显示菜单。)

为什么需要创建动态菜单

如果我们正在创建一个简单的网站,只有很少的页面,并且只有一个程序员负责创建网站,那么我们可以创建一个静态菜单并在我们的网站中使用它。

现在,让我们考虑我们需要为大型 Web 应用程序项目工作。例如,考虑开发一个 ERP Web 应用程序。

但是,如果超过两名开发人员在工作,并且页面数量可能超过 50 到 100 个,那么维护静态菜单将非常困难。

而且,添加或删除新的菜单项到 Web 项目的可能性也会更大,例如,我们的客户可能会要求添加 5 个新菜单或删除 1 个菜单项。

在这种情况下,删除当前正在使用的菜单项将是一项非常困难的任务。

此外,对于像 ERP 这样的大型 Web 项目,我们需要根据用户角色显示菜单。如果我们使用静态菜单,那么管理菜单的用户将非常困难。

为了避免所有这些问题,我们创建了一个带有用户角色设置的菜单管理系统。

谁可以管理菜单

这是非常重要的一部分,因为管理员或超级用户可以添加/编辑/删除菜单。

当管理员登录时,他可以添加新菜单,编辑现有菜单,以及删除要显示的菜单项。

在本文中,我们将详细介绍如何通过管理员用户创建菜单的 CRUD(插入/更新/选择编辑),并使用 ASP.NET MVC、WEB API 和 AngularJS 将管理员创建的菜单显示给已登录的用户,根据他们的角色。

您还可以查看我们之前的文章,其中介绍了如何使用 MVC、AngularJS 和 WCF REST 服务动态显示菜单 链接

必备组件

Using the Code

创建数据库和表

这是我们上一篇文章的延续,因为我们说过我们将为 ASP.NET Identity 表和我们自己的新表使用一个公共数据库。

在我们之前的文章中,我们解释了如何创建用户角色,并且在用户注册时,用户可以选择他们的角色。

在这里,对于基于角色的菜单管理,我们需要在 ASP.NET 角色表和我们的菜单表之间建立一个关系表。

让我们详细了解如何创建我们的新菜单表,该表与 ASP.NET Identity 的 AspNetRoles 表有关系。

在这里,我们可以看到 MenuMaster 使用的字段。

在这里,我们可以看到管理员角色用户登录以及为管理员显示的菜单。

在这里,我们可以看到经理角色用户登录以及为经理显示的菜单。

在这里,我们可以看到员工角色用户登录以及为Employee显示的菜单。

菜单主表和菜单 CRUD 操作的存储过程

我们将使用我们上一篇文章 ASP.NET MVC 5 安全和创建用户角色 中使用的现有数据库。

以下是创建表的脚本,请在您的 SQL Server 中运行此脚本。我使用的是 SQL Server 2014。

USE AttendanceDB    
GO    
  
IF EXISTS ( SELECT [name] FROM sys.tables WHERE [name] = 'MenuMaster' )    
DROP TABLE MenuMaster    
GO    
    
CREATE TABLE MenuMaster    
(    
   MenuIdentity int identity(1,1),    
   MenuID VARCHAR(30)  NOT NULL,    
   MenuName VARCHAR(30)  NOT NULL,  
   Parent_MenuID  VARCHAR(30)  NOT NULL,  
   User_Roll [varchar](256) NOT NULL,   
   MenuFileName VARCHAR(100) NOT NULL,     
   MenuURL VARCHAR(500) NOT NULL,    
   USE_YN Char(1) DEFAULT 'Y',    
   CreatedDate datetime    
CONSTRAINT [PK_MenuMaster] PRIMARY KEY CLUSTERED          
(         
  [MenuIdentity] ASC   ,    
  [MenuID] ASC,    
  [MenuName] ASC      
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, _
 IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]         
) ON [PRIMARY]       
  
select * from MenuMaster  

在创建我们的之后,我们将创建存储过程用于我们的 CRUD 操作。首先,运行以下脚本来创建我们的存储过程。每个过程都有其用途的描述。

-- 1) Stored procedure To Select all user roles   
  
-- Author      : Shanu                                                                  
-- Create date : 2016-01-30                                                                 
-- Description :select all AspNetRoles all roll name to display in Combobox for menu creation.
-- Tables used :  AspNetRoles                                                              
-- Modifier    : Shanu                                                                  
-- Modify date : 2016-01-30                                                                  
-- =============================================    
-- To Select all user roles   
-- EXEC USP_UserRoles_Select ''  
-- =============================================    
CREATE PROCEDURE [dbo].[USP_UserRoles_Select]     
(    
     @Rolename             VARCHAR(30)     = ''   
      )         
AS                                                                  
BEGIN         
         Select ID,Name  
            FROM   
                AspNetRoles   
            WHERE  
                Name like  @Rolename +'%'  
END  
              
-- 2) Stored procedure To Select all  Menu   
  
-- Author      : Shanu                                                                  
-- Create date : 2016-01-30                                                                 
-- Description :select all MenuMaster  detail                                            
-- Tables used :  MenuMaster                                                              
-- Modifier    : Shanu                                                                  
-- Modify date : 2016-01-30                                                                  
-- =============================================    
-- To Select all menu master for Admin user.   
-- EXEC USP_Menu_Select '',''  
-- =============================================    
CREATE PROCEDURE [dbo].[USP_Menu_Select]                                                
   (                              
     @MenuID           VARCHAR(30)     = '',  
     @MenuName         VARCHAR(30)     = ''   
      )                                                          
AS                                                                  
BEGIN  
         Select MenuIdentity ,    
               MenuID ,    
               MenuName ,  
               Parent_MenuID  ,  
               User_Roll,   
               MenuFileName ,     
               MenuURL ,    
               USE_YN ,    
               CreatedDate   
            FROM   
                MenuMaster   
            WHERE  
                MenuID like  @MenuID +'%'  
                AND MenuName like @MenuName +'%'  
            --  AND USE_YN ='Y'  
            ORDER BY  
                MenuName,MenuID       
END  
  
-- 3) Stored procedure To Select Menu by Logged in User Roll  
  
-- Author      : Shanu                                                                  
-- Create date : 2016-01-30                                                                 
-- Description :select all AspNetRoles   all roll name
-- Tables used :  AspNetRoles                                                              
-- Modifier    : Shanu                                                                  
-- Modify date : 2016-01-30                                                                  
-- =============================================    
-- To Select all user roles   
-- EXEC USP_MenubyUserRole_Select 'Admin'  
-- =============================================    
CREATE PROCEDURE [dbo].[USP_MenubyUserRole_Select]     
(    
     @Rolename             VARCHAR(30)     = ''   
      )         
AS                                                                  
BEGIN      
      Select MenuIdentity ,    
               MenuID ,    
               MenuName ,  
               Parent_MenuID  ,  
               User_Roll,   
               MenuFileName ,     
               MenuURL ,    
               USE_YN ,    
               CreatedDate   
            FROM   
                MenuMaster   
            WHERE             
                 User_Roll = @Rolename  
                AND USE_YN ='Y'  
            ORDER BY  
                MenuName,MenuID       
END  
  
-- 4) Stored procedure To Insert  Menu   
  
-- Author      : Shanu                                                                  
-- Create date : 2016-01-30                                                                 
-- Description :To Insert MenuMaster detail                                            
-- Tables used :  MenuMaster                                                              
-- Modifier    : Shanu                                                                  
-- Modify date : 2016-01-30                                                                  
-- =============================================    
-- To Select all user roles   
-- =============================================                                
CREATE PROCEDURE [dbo].[USP_Menu_Insert]                                                
   (                         
     @MenuID            VARCHAR(30)     = '',  
     @MenuName          VARCHAR(30)     = '',  
     @Parent_MenuID     VARCHAR(30)     = '',  
     @User_Roll         VARCHAR(200)     = '',  
     @MenuFileName      VARCHAR(100)     = '',  
     @MenuURL           VARCHAR(500)     = '',  
     @USE_YN            VARCHAR(1)     = ''  
      )                                                          
AS                                                                  
BEGIN         
        IF NOT EXISTS (SELECT * FROM MenuMaster _
        WHERE MenuID=@MenuID and MenuName=@MenuName)  
            BEGIN  
  
                    INSERT INTO MenuMaster  
                    (  MenuID ,     MenuName ,     _
                    Parent_MenuID  ,    User_Roll,      MenuFileName ,     
                     MenuURL ,       USE_YN ,      CreatedDate )  
                     VALUES (  @MenuID ,     @MenuName , _
                     @Parent_MenuID  ,       @User_Roll,     @MenuFileName ,     
                     @MenuURL ,       @USE_YN ,        GETDATE())  
                                 
                    Select 'Inserted' as results  
                          
            END  
         ELSE  
             BEGIN  
                     Select 'Exists' as results  
              END  
  
END  
  
-- 5) Stored procedure To Update  Menu   
  
-- Author      : Shanu                                                                  
-- Create date : 2016-01-30                                                                 
-- Description :To Update MenuMaster detail                                            
-- Tables used :  MenuMaster                                                              
-- Modifier    : Shanu                                                                  
-- Modify date : 2016-01-30                                                                  
-- =============================================    
-- To Select all user roles   
-- =============================================                                  
CREATE PROCEDURE [dbo].[USP_Menu_Update]                                                
   ( @MenuIdentity             Int=0,                             
     @MenuID            VARCHAR(30)     = '',  
     @MenuName          VARCHAR(30)     = '',  
     @Parent_MenuID     VARCHAR(30)     = '',  
     @User_Roll         VARCHAR(200)     = '',  
     @MenuFileName      VARCHAR(100)     = '',  
     @MenuURL           VARCHAR(500)     = '',  
     @USE_YN            VARCHAR(1)     = ''  
      )                                                          
AS                                                                  
BEGIN         
        IF  EXISTS (SELECT * FROM MenuMaster WHERE MenuIdentity=@MenuIdentity )  
            BEGIN  
                    UPDATE MenuMaster SET  
                            MenuID=@MenuID,  
                            MenuName=MenuName,  
                            Parent_MenuID=@Parent_MenuID,  
                            User_Roll=@User_Roll,  
                            MenuFileName=@MenuFileName,  
                            MenuURL=@MenuURL,  
                            USE_YN=@USE_YN  
                    WHERE  
                    MenuIdentity=@MenuIdentity  
                                 
                    Select 'updated' as results                       
            END  
         ELSE  
             BEGIN  
                     Select 'Not Exists' as results  
              END  
END  
  
-- 6) Stored procedure To Delete  Menu   
  
-- Author      : Shanu                                                                  
-- Create date : 2016-01-30                                                                 
-- Description :To Delete MenuMaster detail                                            
-- Tables used :  MenuMaster                                                              
-- Modifier    : Shanu                                                                  
-- Modify date : 2016-01-30                                                                  
-- =============================================    
-- To Select all user roles   
-- =============================================
Create PROCEDURE [dbo].[USP_Menu_Delete]                                                
   ( @MenuIdentity   Int=0 )                                                          
AS                                                                  
BEGIN         
        DELETE FROM MenuMaster WHERE MenuIdentity=@MenuIdentity              
END  

2. 在 Visual Studio 2015 中创建您的 MVC Web 应用程序

正如我们所提到的,这是我们上一篇文章的延续。我们将使用我们之前文章中使用的现有项目,您可以下载源代码。

单击开始,然后单击程序,然后选择Visual Studio 2015 - 单击Visual Studio 2015

单击打开项目,转到您下载的项目文件夹,然后打开解决方案文件。

使用 ADO.NET 实体数据模型添加数据库

右键单击我们的项目,然后单击添加,然后单击新建项。选择数据,然后选择ADO.NET Entity Data Model,并为我们的 EF 命名,然后单击。

选择“从数据库创建 EF 设计器”,然后单击下一步

在这里,我们不需要创建新的连接,因为我们可以使用我们为 ASP.NET Identity 用户注册和登录使用的现有连接。单击下一步以选择我们的表和存储过程以进行菜单管理。

在这里,我们可以看到新创建的MenuMaster表以及现有的 ASP.NET Identity 表,并且所有新创建的存储过程都已被选中,用于执行我们的菜单 CRUD 操作。

在这里,我们可以看到我们已经创建了我们的UsermenuModel

创建实体后,下一步是将 Web API 添加到我们的控制器,并编写用于选择/插入/更新删除的函数。

添加 Web API 控制器的过程

右键单击Controllers文件夹,单击添加,然后单击Controller

选择Web API 2 Controller - Empty,单击Add并为我们的 WEB API 控制器命名。

注意:我们这里使用的是现有的 MVC 项目,而不是选择 WEB API 选项创建的 MVC 项目。因此,当我们添加 WEB API 控制器时,我们可以看到以下自述文本。

要在非 WEB API MVC 项目中使用 WEB API,我们需要在Global.asax文件中添加上述引用的配置,如下所示。

当我们打开Global.asax文件时,我们可以看到缺少 System.Web.Http 引用,并且 GlobalConfiguration 未添加到 Application_Start 中。

在这里,我们添加引用和 GlobalConfiguration,如下所示,以使用 WEB API。

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Mvc;  
using System.Web.Optimization;  
using System.Web.Routing;  
using System.Web.Http;  
  
namespace shanuMVCUserRoles  
{  
    public class MvcApplication : System.Web.HttpApplication  
    {  
        protected void Application_Start()  
        {  
            AreaRegistration.RegisterAllAreas();  
            GlobalConfiguration.Configure(WebApiConfig.Register);  
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);  
            RouteConfig.RegisterRoutes(RouteTable.Routes);  
            BundleConfig.RegisterBundles(BundleTable.Bundles);  
        }  
    }  
}  

App_StartWebApiConfig.cs 中,将 routeTemplate 更改为如下:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web.Http;  
  
namespace shanuMVCUserRoles  
{  
    public static class WebApiConfig  
    {  
        public static void Register(HttpConfiguration config)  
        {  
            // Web API configuration and services  
  
            // Web API routes  
            config.MapHttpAttributeRoutes();  
  
            config.Routes.MapHttpRoute(  
                name: "DefaultApi",  
               // routeTemplate: "api/{controller}/{id}",  
               routeTemplate: "api/{controller}/{action}/{id}",  
                defaults: new { id = RouteParameter.Optional }  
            );  
        }  
    }  
}  

使用 WEBAPI 控制器进行 CRUD 操作

选择Controller并添加Empty Web API 2 Controller。为 Web API 控制器提供名称,然后单击OK。在这里,我为我的 Web API 控制器命名为MenuAPIController

由于我们创建了 Web API 控制器,我们可以看到我们的控制器已继承了 ApiController

众所周知,Web API 是构建浏览器和移动设备 HTTP 服务的简单易行的方法。

Web API 具有以下四种方法:Get/Post/PutDelete,其中

  • `Get` 用于请求数据(`Select`)
  • `Post` 用于创建数据(`Insert`)
  • `Put` 用于更新数据。
  • `Delete` 用于删除数据。

Get 方法

在我们的示例中,我只使用了Get方法,因为我只使用存储过程。我们需要创建一个我们的实体的对象,并编写我们的Get方法来执行选择/插入/更新删除操作。

查询操作

我们使用一个get方法,通过实体对象获取 MenuMasters 表的所有详细信息,并将结果作为 IEnumerable 返回。我们在 AngularJS 中使用此方法,并在 AngularJS 控制器中将结果显示在 MVC 页面上。使用 Ng-Repeat,我们可以绑定详细信息。

在这里,我们可以看到在 getMenuCRUDSelect 方法中,我将搜索参数传递给了 USP_Menu_Select 存储过程。在存储过程中,如果搜索参数为空,我使用“%”来返回所有记录。

// to Search Menu Details and display the result  
        [HttpGet]  
        public IEnumerable<USP_Menu_Select_Result> 
               getMenuCRUDSelect(string menuID, string menuName)  
        {  
            if (menuID == null)  
                menuID = "";  
            if (menuName == null)  
                menuName = "";        
            return objapi.USP_Menu_Select(menuID, menuName).AsEnumerable();  
        }  

我们创建了另一个select方法来获取所有用户角色,以便在我们的 MVC 视图中使用 AngularJS 的ComboBox中进行绑定。

// To get all user role from ASPNETRoels Table  
        [HttpGet]  
        public IEnumerable<USP_UserRoles_Select_Result> getUserRoleDetails(string UserRole)  
        {  
            if (UserRole == null)  
                UserRole = "";  
            return objapi.USP_UserRoles_Select(UserRole).AsEnumerable();  
        }   

接下来,我们还有另一个Select方法。此方法将用于通过登录的角色为每个用户显示菜单。

// To get all Menu by User role to bind the menu dynamically in user pages  
        [HttpGet]  
        public IEnumerable<USP_MenubyUserRole_Select_Result> getMenubyUserRole(string UserRole)  
        {  
            if (UserRole == null)  
                UserRole = "";  
            return objapi.USP_MenubyUserRole_Select(UserRole).AsEnumerable();  
        }    

在这里,在我们的示例中,我们对选择/插入/更新删除操作使用了get方法,因为在我的存储过程中,在插入/更新删除之后,我从数据库返回了消息。

插入操作

select类似,我们将所有参数传递给insert过程。此insert方法将返回数据库中的结果,说明记录是否已插入。我们将获取结果并从 AngularJS 控制器显示到 MVC 应用程序。

// To Insert new Menu Details  
        [HttpGet]  
        public IEnumerable<string> insertMenu(string menuID, string menuName, 
        string parentMenuID, string UserRole, 
               string menuFileName, string MenuURL, string UseYN)  
        {  
            return objapi.USP_Menu_Insert(menuID, menuName, parentMenuID, 
            UserRole, menuFileName, MenuURL, UseYN).AsEnumerable();  
        }   

更新操作

Insert一样,我们将所有参数传递给Update过程。此Update方法将返回数据库中的结果,说明记录是否已更新。

//to Update Menu Details  
        [HttpGet]  
        public IEnumerable<string> updateMenu(int MenuIdentity, 
        string menuID, string menuName, string parentMenuID, 
        string UserRole, string menuFileName, string MenuURL, string UseYN)  
        {  
            return objapi.USP_Menu_Update(MenuIdentity, menuID, menuName, 
            parentMenuID, UserRole, menuFileName, MenuURL, UseYN).AsEnumerable();  
        }  

删除操作

Insert相同,我们将所有参数传递给Delete过程。此Delete方法将返回数据库中的结果,说明记录是否已删除。

//to Delete Menu Details  
        [HttpGet]  
        public string deleteMenu(int MenuIdentity)  
        {  
            objapi.USP_Menu_Delete(MenuIdentity);  
            objapi.SaveChanges();  
            return "deleted";  
        }  

创建 AngularJS 控制器

首先,在Scripts文件夹内创建一个文件夹,我们将文件夹命名为“MyAngular”。

现在将您的 Angular Controller 添加到该文件夹中。

右键单击MyAngular文件夹,单击Add,然后单击New Item。选择Web,然后选择AngularJS Controller,并为 Controller 提供一个名称。我将我的 AngularJS Controller 命名为“Controller.js”。

创建 AngularJS Controller 后,我们可以看到默认情况下 Controller 将包含带有默认模块定义的代码等。

如果 AngularJS 包缺失,请将该包添加到您的项目中。

右键单击您的 MVC 项目,然后单击 Manage NuGet Packages。搜索 AngularJS,然后单击Install

创建菜单 CRUD 的 AngularJS 脚本文件的过程

Modules.js:在这里,我们将添加对

// <reference path="../angular.js" />    
/// <reference path="../angular.min.js" />     
/// <reference path="../angular-animate.js" />     
/// <reference path="../angular-animate.min.js" />     
var app;  
(function () {  
    app = angular.module("RESTClientModule", ['ngAnimate']);  
})();  

Controllers:在 AngularJS Controller 中,我完成了所有业务逻辑,并将数据从 Web API 返回到我们的 MVC HTML 页面。

变量声明

首先,我们声明了所有需要使用的局部变量。

app.controller("AngularJs_Controller", 
                function ($scope, $timeout, $rootScope, $window, $http) {  
    $scope.date = new Date();  
    $scope.MyName = "shanu";  
    $scope.sMenuID = "";  
    $scope.sMenuName = "";  
  
    $scope.showMenuAdd = true;  
    $scope.addEditMenu = false;  
    $scope.MenuList = true;  
    $scope.showItem = true;  
    $scope.userRoleName = $("#txtuserRoleName").val();// this is hidden textbox 
    //which will be storing our logged in user Role Name.  
    //This variable will be used for Insert/Edit/Delete menu details.
    //menuID, menuName, parentMenuID, UserRole, menuFileName, MenuURL, UseYN  
    $scope.MenuIdentitys = 0;  
    $scope.menuIDs = "";  
    $scope.menuNames = "";  
    $scope.parentMenuIDs = "";  
    $scope.selectedUserRole = "";  
    $scope.menuFileNames = "";  
    $scope.MenuURLs = "";  
    $scope.UseYNs = true;  
    $scope.searchRoleName = "";  

2. 方法

Select 方法

select方法中,我使用了$http.get从 Web API 获取详细信息。在get方法中,我将提供我们的 API Controller 名称和方法来获取详细信息。在这里,我们可以看到我传递了OrderNOTableID的搜索参数,使用

{ params: { menuID: menuID, menuName: menuName }  

最终结果将使用 data-ng-repeat 显示在 MVC HTML 页面上。

//This method is used to search and display the Menu Details for display,Edit and Delete  
    select MenuDetails($scope.sMenuID, $scope.sMenuName);  
  
    function selectMenuDetails(menuID, menuName) {  
       
        $http.get('/api/MenuAPI/getMenuCRUDSelect/', 
        { params: { menuID: menuID, menuName: menuName } }).success(function (data) {  
            $scope.MenuData = data;  
            $scope.showMenuAdd = true;  
            $scope.addEditMenu = false;  
            $scope.MenuList = true;  
            $scope.showItem = true;  
  
            if ($scope.MenuData.length > 0) {  
            }  
        })  
   .error(function () {  
       $scope.error = "An Error has occurred while loading posts!";  
   });  
  
        //Here we call all the created menu details 
        //to bind in select list for creating sub menu  
        $http.get('/api/MenuAPI/getMenuCRUDSelect/', 
        { params: { menuID: "", menuName: "" } }).success(function (data) {  
            $scope.MenuDataSelect = data;              
        })  
  .error(function () {  
      $scope.error = "An Error has occurred while loading posts!";  
  });           
    }  
  
    //Search  
    $scope.searchMenuDetails = function () {  
  
        selectMenuDetails($scope.sMenuID, $scope.sMenuName);  
    }   

搜索按钮点击

<table style="color:#9F000F;font-size:large" 
    cellpadding="4" cellspacing="6">  
  
      <tr>  
          <td>  
              <b>Menu ID</b>  
          </td>  
          
          <td>  
              : <input type="text" name="txtMenuID" 
              ng-model="sMenuID" value="" />  
              <br />  
          </td>  
          
          <td>  
              <b>   Menu Name </b>  
          </td>  
          
          <td>  
              :  
              <input type="text" name="txtMenuName" 
              ng-model="sMenuName" />  
              
          </td>  
          <td>  
              <input type="submit" value="Search" 
              style="background-color:#336699;color:#FFFFFF" 
              ng-click="searchMenuDetails()" />  
              
          </td>  
      </tr>  
      
  </table> 

插入新的菜单主记录

在 ADD/Edit 菜单详细信息按钮点击时,我们将使 MenuAdd 表详细信息可见,管理员用户可以在其中输入新菜单信息。对于新菜单,我们将 Menu ID 设置为0。在 New Menu 保存按钮点击时,我们将调用 save 方法。

// New Menu Add Details  
    $scope.showMenuAddDetails = function () {  
        cleardetails();  
        $scope.showMenuAdd = true;  
        $scope.addEditMenu = true;  
        $scope.MenuList = true;  
        $scope.showItem = true;    
    }  

将用户角色绑定到组合框

为了创建新菜单,管理员需要选择用户角色。为此,我们将 ASP.NET 角色表的所有角色详细信息绑定到combobox

AngularJS 控制器部分

使用我们的 WebAPI,我们获取所有用户角色并将结果存储在 $scope.userRoleData 中。

// This method is to get all the UserRole and bind to 
// dropdownbox selection for creating menu by User Role.   
select userRoleDetails($scope.searchRoleName);  
// This method is to get all the UserRole and bind to 
// dropdownbox selection for creating menu by User Role.   
function selectuerRoleDetails(UserRole) {        
    $http.get('/api/MenuAPI/getUserRoleDetails/', 
    { params: { UserRole: UserRole } }).success(function (data) {  
       
        $scope.userRoleData = data;  
    })  
rror(function () {  
  $scope.error = "An Error has occurred while loading posts!";    
}   

将组合框与用户角色绑定的 HTML 部分

<select name="opSelect" id="opSelect" ng-model="selectedUserRole">  
 <option value="" selected>-- Select --</option>  
 <option ng-repeat="option in userRoleData" 
 value="{{option.Name}}">{{option.Name}}</option>  
</select>  

将父菜单 ID 绑定到组合框

对于创建子菜单,管理员可以从ComboBox中选择父菜单。每次管理员创建菜单时,主菜单 ID 将添加到此combobox中,用于创建子菜单。

AngularJS 控制器部分

使用我们的 WebAPI,我们获取所有用户角色并将结果存储在 $scope.userRoleData 中。

将组合框与父菜单 ID 绑定的 HTML 部分

<select name="opSelect" id="opSelect" ng-model="parentMenuIDs">  
<option value="*" selected>*</option>  
  <option ng-repeat="option in MenuDataSelect" 
  value="{{option.MenuID}}">{{option.MenuID}}</option>  
</select>  

Save方法中,我将检查MenuIdentity。如果MenuIdentitys是“0”,那么它将插入新的 Menu Master。在这里,我们将调用 Insert Web API 方法;如果MenuIdentitys大于0,则表示要更新 Menu 记录,然后我们将调用 Update Web API 方法。

//Save Menu  
    $scope.saveDetails = function () {  
        if ($scope.selectedUserRole == "")  
        {  
            alert("Select User Role");  
            return;  
        }  
        
        if ($scope.parentMenuIDs == "") {  
            alert("Select parent ID");  
            return;  
        }  
  
        $scope.IsFormSubmitted = true;  
        if ($scope.IsFormValid) {  
            
            if ($scope.UseYNs == true)  
            {  
                $scope.UseYNsN = "Y";  
            }  
            else  
            {  
                $scope.UseYNsN = "N";  
            }               
  
            //if the MenuIdentity ID=0 means its new Menu insert 
            //here I will call the Web API insert method  
            if ($scope.MenuIdentitys == 0) {  
  
                $http.get('/api/MenuAPI/insertMenu/', { params: 
                { menuID: $scope.menuIDs, menuName: $scope.menuNames, 
                parentMenuID: $scope.parentMenuIDs, UserRole: $scope.selectedUserRole, 
                menuFileName: $scope.menuFileNames, MenuURL: $scope.MenuURLs, 
                UseYN: $scope.UseYNsN } }).success(function (data) {  
  
                    $scope.menuInserted = data;  
                    alert($scope.menuInserted);   
  
                    cleardetails();  
                    selectMenuDetails('', '');  
                    selectMenubyUserRoleDetails($scope.userRoleName);  
                })  
         .error(function () {  
             $scope.error = "An Error has occurred while loading posts!";  
         });  
            }              
  
            else {  // to update to the Menu details  
                $http.get('/api/MenuAPI/updateMenu/', { params: 
                { MenuIdentity: $scope.MenuIdentitys, menuID: $scope.menuIDs, 
                menuName: $scope.menuNames, parentMenuID: $scope.parentMenuIDs, 
                UserRole: $scope.selectedUserRole, menuFileName: $scope.menuFileNames, 
                MenuURL: $scope.MenuURLs, UseYN: $scope.UseYNsN } }).success(function (data) {  
                    $scope.menuUpdated = data;  
                    alert($scope.menuUpdated);  
  
                    cleardetails();  
                    selectMenuDetails('', '');  
                    selectMenubyUserRoleDetails($scope.userRoleName);  
                })  
        .error(function () {  
            $scope.error = "An Error has occurred while loading posts!";  
        });  
            }    
        }  
        else {  
            $scope.Message = "All the fields are required.";  
        }  
  
        $scope.IsFormSubmitted = false;  
    } 

首先,我们检查管理员是否为创建新菜单选择了用户角色和ParentMenuID。然后我们检查菜单是否对用户可见。如果选中,则插入状态为‘Y’,否则为‘N’。为了显示菜单,我们选择菜单可见状态仅为‘Y’。要调用 Insert Web API 方法,我们将传递所有输入参数。在我们的存储过程中,我们将检查菜单 ID 是否已存在于数据库中。如果菜单 ID 在数据库中不存在,我们将插入记录并返回成功消息“inserted”;如果菜单 ID 已存在,我们将返回消息“Exists”。

在这里,我们可以看到管理员已创建新菜单,并为新菜单选择了用户角色为EmployeeparentMenuID为‘*’,这意味着此新创建的菜单仅对 Employee Role 用户可见,甚至对管理员也不可见,父菜单 ID 为‘*’,表示将菜单显示为根菜单项。在这里,我们将控制器名称指定为‘Message’。现在我们将创建一个名为“message”的新 Controller,并为该 Controller 添加一个默认的 index 视图,用于显示简单的消息。

让我们以 Employee 用户身份登录我们的 MVC 应用程序,看看新创建的菜单是如何显示的。

更新菜单主记录

在这里,我们再次以管理员用户身份登录以编辑新创建的菜单。现在我们可以看到我们可以点击编辑图标来编辑选定的菜单详细信息。现在我们将父MenuID从‘*’更改为显示菜单作为Employee Dashboard 的子菜单。

现在,我们再次以 Employee 用户身份登录,看看菜单将如何显示为子菜单。

更新菜单显示状态

现在让我们看看如何更新菜单,使其对用户不可见。我们以管理员用户身份登录,编辑菜单,取消选中“菜单可见(是/否)”复选框,然后单击Save

如果 Employee 用户登录,且此菜单可见性设置为‘N’,则菜单将不会显示给他。在这里,我们可以看到 Employee 角色用户已登录,他/她只能看到一个菜单,而之前显示的“message”菜单现在不显示了。

删除订单主详细信息

Delete按钮点击时,我们将向用户显示确认消息,询问是否删除菜单。如果用户单击OK按钮,我们将 menuID 传递给 Web API 的delete方法,以从数据库中删除记录。

//Delete Menu Detail  
    $scope.MenuDelete = function MenuDelete(MenuIdentity, menuName) {  
        cleardetails();  
        $scope.MenuIdentitys = MenuIdentity;  
        var delConfirm = confirm
        ("Are you sure you want to delete the Student " + menuName + " ?");  
        if (delConfirm == true) {  
  
            $http.get('/api/MenuAPI/deleteMenu/', 
            { params: { MenuIdentity: $scope.MenuIdentitys } }).success(function (data) {  
                alert("Menu Deleted Successfully!!");  
                cleardetails();  
                selectMenuDetails('', '');  
            })  
      .error(function () {  
          $scope.error = "An Error has occurred while loading posts!";  
      });    
        }  
    }  

按用户角色显示菜单

要按用户角色显示菜单,我们将登录的用户角色传递给 webAPI 方法,以获取登录用户角色用户的所有菜单详细信息。在 AngularJS 控制器中,我们将从隐藏字段获取登录用户角色,在我们的 MVC 页面中,我们将登录用户角色绑定到hidden字段。

<input type="hidden" id="txtuserRoleName" 
 value="@ViewBag.UserRole" />  

我们在 AngularJS 控制器中获取此hidden字段值,并将用户角色传递给获取登录用户角色的所有菜单。

$scope.userRoleName = $("#txtuserRoleName").val();  
  
//********** ---------------- for Display Menu by User Role -------------   ***************  
    // This method is to get all the menu details of logged in users.
    // Bind this result for creating Menu  
    selectMenubyUserRoleDetails($scope.userRoleName);  
    // This method is to get all the menu details of logged in users.
    // Bind this result for creating Menu  
    function selectMenubyUserRoleDetails(UserRole) {  
       // alert($scope.userRoleName);  
        $http.get('/api/MenuAPI/getMenubyUserRole/', 
        { params: { UserRole: $scope.userRoleName } }).success(function (data) {  
            $scope.generateMenuData = data;  
        })  
 .error(function () {  
     $scope.error = "An Error has occurred while loading posts!";  
 });    
    }  
  
    $scope.showDetails = false;  
    $scope.showSubDetails = false;  
    $scope.subChildIDS = "";  
    $scope.Imagename = "R1.png";  
    $scope.showsubMenu = function (showMenus, ids) {    
        if (showMenus == 1) {  
            $scope.subChildIDS = ids;  
  
            $scope.showSubDetails = true;  
        }  
        else if (showMenus == 0) {  
            $scope.showSubDetails = false;  
        }  
        else {  
  
            $scope.showSubDetails = true;  
        }  
    }  
  
    //********** ---------------- End Display Menu -------------   ***************   

在我们的视图页面中,我们将菜单结果绑定到表中,如下所示显示所有菜单和子菜单:

<div style="overflow:visible;height:100px;">  
         <ul class="menu">  
             <li data-ng-repeat="menus in generateMenuData | 
             filter:{Parent_MenuID:'*'}">  
                 @{var url = Url.Action("{{menus.MenuFileName}}", 
                 "{{menus.MenuURL}}", new { id = "{{id=menus.MenuURL}}" });  
                     url = HttpUtility.UrlDecode(url);  
                 }  
                 <a data-ng-href="@url">{{menus.MenuName}}</a>  
                 
                 <ul class="sub-menu">  
                     <li data-ng-repeat="submenus in generateMenuData | 
                     filter:{Parent_MenuID:menus.MenuID}" 
                     ng-mouseover="showsubMenu(1,submenus.MenuID);" 
                     ng-mouseout="showsubMenu(0,submenus.MenuID);">  
                         @{var url1 = Url.Action("{{submenus.MenuFileName}}", 
                         "{{submenus.MenuURL}}", 
                         new { id = "{{id=submenus.MenuURL}}" });  
                             url1 = HttpUtility.UrlDecode(url1);  
                         }  
                         <a data-ng-href="@url1">{{submenus.MenuName}}</a>  
                         
                         <ul ng-show="showSubDetails" 
                         class="sub-menu2">  
                             <li data-ng-repeat="sub1menus in generateMenuData  | 
                             filter:{Parent_MenuID:submenus.MenuID}" 
                             ng-mouseover="showsubMenu(3,9);">  
                                 @{var url2 = Url.Action("{{sub1menus.MenuFileName}}", 
                                 "{{sub1menus.MenuURL}}", 
                                 new { id = "{{id=sub1menus.MenuURL}}" });  
                                     url2 = HttpUtility.UrlDecode(url2);  
                                 }  
                                 <a data-ng-href="@url2">{{sub1menus.MenuName}}</a>  
                             </li>  
                         </ul>  
                     </li>  
                 </ul>  
             </li>  
         </ul>  
     </div>  

MVC Controller

在 MVC Controller 中,我们检查身份验证和授权。只有登录用户才能查看此页面,并在 Controller 中,我们为每个用户角色进行检查,并将角色从 Controller 传递到 View,以按用户角色显示菜单。

public string RoleName { get; set; }  
        // GET: Users  
          
        public ActionResult Index()  
        {  
            if (User.Identity.IsAuthenticated)  
            {  
                var user = User.Identity;  
                ViewBag.Name = user.Name;  
                ApplicationDbContext context = new ApplicationDbContext();  
                var UserManager = new UserManager<ApplicationUser>
                (new UserStore<ApplicationUser>(context));  
                var s = UserManager.GetRoles(user.GetUserId());  
                RoleName = s[0].ToString();  
                ViewBag.displayMenu = "No";  
                ViewBag.UserRole = RoleName;  
                if (RoleName == "Admin")  
                {                 
                    ViewBag.displayMenu = "Yes";  
                }  
                  
                return View();  
            }  
            else  
            {  
            return  RedirectToAction("Index", "Home");  
            }    
        }  

关注点

首先,将所有脚本运行到您的 SQL Server。您也可以在附加的 zip 文件中找到 SQL 脚本文件。下载源代码后,请更改 Web.Config 文件中的 DefaultConnection 连接字符串以匹配您的 SQL Server 连接。在 Startup.cs 文件中,我们创建了一个默认的管理员用户,UserName 为“shanu”,password 为“A@Z200711"。此UserNamepassword将用于登录管理员用户。您可以根据需要更改此用户名和密码。出于安全原因,以管理员身份登录后,您可以根据需要更改管理员用户的密码。

历史

  • 2016 年 2 月 2 日:初始版本
© . All rights reserved.