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






4.97/5 (29投票s)
在本文中,我们将学习如何使用 ASP.NET MVC、WEB API 和 AngularJS 创建和管理基于用户角色的菜单。
在开始阅读本文之前,请先阅读我之前的文章 ASP.NET MVC 5 安全和创建用户角色。它详细介绍了 ASP.NET Identity 和创建用户角色。
引言
在本文中,我们将学习如何使用 ASP.NET MVC、WEB API 和 AngularJS 创建和管理基于用户角色的菜单。
在这里,我们将学习如何执行以下操作:
- 管理员菜单管理(只有管理员用户可以查看所有/创建/删除和编辑菜单)
- 按用户角色创建菜单(管理员可以选择用户角色来创建菜单)
- 按用户角色显示和隐藏动态菜单和子菜单
- 按用户角色动态显示菜单(这里我们将其称为动态菜单,因为在每个页面或主页面上,我们都将从数据库加载菜单,并根据用户的角色向每个用户显示菜单。)
为什么需要创建动态菜单
如果我们正在创建一个简单的网站,只有很少的页面,并且只有一个程序员负责创建网站,那么我们可以创建一个静态菜单并在我们的网站中使用它。
现在,让我们考虑我们需要为大型 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_Start
的 WebApiConfig.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
/Put
和 Delete
,其中
- `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 名称和方法来获取详细信息。在这里,我们可以看到我传递了OrderNO
和TableID
的搜索参数,使用
{ 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”。
在这里,我们可以看到管理员已创建新菜单,并为新菜单选择了用户角色为Employee
,parentMenuID
为‘*
’,这意味着此新创建的菜单仅对 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
"。此UserName
和password
将用于登录管理员用户。您可以根据需要更改此用户名和密码。出于安全原因,以管理员身份登录后,您可以根据需要更改管理员用户的密码。
历史
- 2016 年 2 月 2 日:初始版本