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

使用 MVC 和 WCF REST 实现 Angular JS 动态菜单创建

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (30投票s)

2015年6月1日

CPOL

11分钟阅读

viewsIcon

56318

downloadIcon

2655

本文介绍如何使用 AngularJS、MVC 和 WCF REST 服务从数据库动态创建菜单。

引言

您可以通过 MVC 和 WCF REST 服务查看我之前与 AngularJS 相关的文章

为什么我们需要创建动态菜单

如果我们正在创建一个非常简单的网站,只有很少的页面,并且只有一个程序员来创建网站,那么在这种情况下,我们可以创建静态菜单并在我们的网站中使用它。

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

在这种情况下,将有两名以上的开发人员参与,并且页面数量可能超过 50 到 100。在这种情况下,维护静态菜单将很困难。

而且,我们更有可能在我们的 Web 项目中删除和添加新的菜单项,例如,我们的客户可能会要求我们添加 5 个新菜单或删除 1 个菜单项。

在这种情况下,删除当前在线的菜单项将是一项艰巨而困难的任务。

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

为了避免这一切,我们创建了一个带用户角色设置的菜单管理。

谁可以管理菜单?

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

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

本文不侧重于菜单管理,但在本文中,我们将详细介绍如何创建菜单主表和菜单明细表,在我们的数据库表中插入一些示例菜单项,使用 AngularJS 和 WCF REST 服务动态地将菜单显示到我们的 MVC 网页上。

本文将讲解

  1. 如何创建 WCF REST 服务并从数据库检索数据
  2. 如何将 AngularJS 包安装到 MVC 应用程序中
  3. 如何创建我们的 AngularJS 应用程序来进行动态菜单创建
  4. 如何使用 WCS 服务在 AngularJS 中显示动态菜单

注意:先决条件是 Visual Studio 2013(如果您没有 Visual Studio 2013,可以从Microsoft下载)。

在这里,我们可以看到一些关于 Windows Communication Foundation (WCF) 的基础知识和参考链接。WCF 是一个用于构建面向服务应用程序的框架。

面向服务的应用程序:使用此协议,可以在网络上共享和使用该服务。

例如,现在我们正在做一个项目,需要创建一些通用的数据库函数,并且这些函数需要在多个项目中被使用,而这些项目位于多个地方并通过互联网等网络连接。

在这种情况下,我们可以创建一个 WCF 服务,并将所有通用的数据库函数写在我们的 WCF 服务类中。我们可以将 WCF 部署在 IIS 中,并在我们的应用程序中使用 URL 来执行 DB 函数。在代码部分,让我们看看如何创建 WCF REST 服务并在我们的 AngularJS 应用程序中使用它。

如果您对 WCF 的更多详细信息感兴趣,请访问此链接

AngularJS

我们可能熟悉 Model、View 和 View Model (MVVM) 以及 Model、View 和 Controller (MVC)。AngularJS 是一个完全基于 HTML CSS 和 JavaScript 的 JavaScript 框架。

与 MVC 和 MVVM 模式类似,AngularJS 使用 Model、View 和 Whatever (MVW) 模式。

在我们的示例中,我使用了 Model、View 和 Service。在代码部分,让我们看看如何安装和在我们的 MVC 应用程序中创建 AngularJS。

如果您对 WCF 的更多详细信息感兴趣,请访问此链接

Using the Code

我们将在 MenuDB 数据库下创建 MenuMasterMenuDetails 表。

注意MenuMasterMenuDetail 是用于动态加载菜单的重要表。我们需要了解如何向这些表插入菜单详细信息以正确显示我们的菜单。

在本文中,我展示了 3 级层级菜单显示。在这里,您可以看到三级层级示例。

在这里,我们可以看到

  • 第一级层级-> 库存
  • 第二级层级-> 库存明细
  • 第三级层级-> 成品入库和成品出库。

现在,让我们看看如何创建表关系来创建主表和明细菜单。

菜单主表

一级层级插入

Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('Root','Inventory','Shanu',getdate()-23)

二级层级插入

Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('Inventory','INV001','Shanu',getdate()-23)

三级层级插入

Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('INV001','FG001','Shanu',getdate()-23)

Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('INV001','FG002','Shanu',getdate()-23)

菜单明细表

一级层级插入

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,

MenuURL,UserID,CreatedDate)

values('Inventory','Inventory','Inventory','Index','Inventory',

'Shanu',getdate()-23)

二级层级插入

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,

MenuURL,UserID,CreatedDate)

values('INV001','Inventory','Inventory Details','Index','Inventory',

'Shanu',getdate()-23)

三级层级插入

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,
MenuURL,UserID,CreatedDate)
values('FG001','FGIN','FG Receipt','FGIN','Inventory','Shanu',getdate()-43)
Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,MenuFileName,
MenuURL,UserID,CreatedDate)
values('FG002','FGOUT','FG Issue','FGOUT','Inventory','Shanu',getdate()-13)

在这里,我们可以看到用于菜单明细的字段。我使用了以下字段

在这里,我们可以看到用于菜单主的字段。我使用了以下字段。

以下是创建数据库、表和示例插入查询的脚本。在您的 SQL Server 中运行此脚本。我使用的是 SQL Server 2012。

-- =============================================                             
-- Author      : Shanu                               
-- Create date : 2015-03-20                               
-- Description : To Create Database,Table and Sample Insert Query                            
-- Latest                               
-- Modifier    : Shanu                               
-- Modify date : 2015-03-20                           
-- =============================================
--Script to create DB,Table and sample Insert data
USE MASTER
GO
-- 1) Check for the Database Exists .If the database is exist then drop and create new DB
IF EXISTS (SELECT [name] FROM sys.databases WHERE [name] = 'MenuDB' )
DROP DATABASE MenuDB
GO

CREATE DATABASE MenuDB
GO
USE MenuDB
GO

-- 1) //////////// ToysDetails table
-- Create Table  ToysDetails ,This table will be used 
-- to store the details like Toys Information

IF EXISTS ( SELECT [name] FROM sys.tables WHERE [name] = 'MenuMaster' )
DROP TABLE MenuMaster
GO
CREATE TABLE MenuMaster
(
   Menu_ID int identity(1,1),
   Menu_RootID VARCHAR(30)  NOT NULL,
   Menu_ChildID VARCHAR(30)  NOT NULL,
   UserID varchar(50),
   CreatedDate datetime
CONSTRAINT [PK_MenuMaster] PRIMARY KEY CLUSTERED      
(    
  [Menu_ID] ASC   ,
  [Menu_RootID] ASC,
  [Menu_ChildID] ASC 
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, _
 IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]    
) ON [PRIMARY]  
GO
--delete from MenuMaster
-- Insert the sample records to the ToysDetails Table
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('Root','Home','Shanu',getdate()-23)
--Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('Home','Home','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('Home','About','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('Home','Contact','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('Root','Masters','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('Masters','ITM001','Shanu',getdate()-23)
--Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('ITM001','ITM001','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('ITM001','ITM002','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('ITM001','ITM003','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('Masters','CAT001','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('CAT001','CAT001','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('CAT001','CAT002','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('CAT001','CAT003','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('Root','Inventory','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('Inventory','INV001','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('INV001','FG001','Shanu',getdate()-23)
Insert into MenuMaster(Menu_RootID,Menu_ChildID,UserID,CreatedDate) _
values('INV001','FG002','Shanu',getdate()-23)

select * from MenuMaster
-- 1) END //

-- 2) Cart Details Table
IF EXISTS ( SELECT [name] FROM sys.tables WHERE [name] = 'MenuDetails' )
DROP TABLE MenuDetails
GO

CREATE TABLE MenuDetails
(
   MDetail_ID int identity(1,1),
   Menu_ChildID VARCHAR(20) NOT NULL,
   MenuName VARCHAR(100) NOT NULL,
   MenuDisplayTxt VARCHAR(200) NOT NULL,
   MenuFileName VARCHAR(100) NOT NULL,
   MenuURL VARCHAR(500) NOT NULL,
   USE_YN Char(1) DEFAULT 'Y',
   UserID varchar(50),
   CreatedDate datetime
CONSTRAINT [PK_MenuDetails] PRIMARY KEY CLUSTERED     
(    
  [MDetail_ID] ASC,
  [Menu_ChildID] ASC      
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, _
 IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]    
) ON [PRIMARY]  
GO

----delete from MenuDetails

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('Root','Home','Shanu Home',_
'Index','Home','Shanu',getdate()-23)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('Home','Home','Shanu Home',_
'Index','Home','Shanu',getdate()-23)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('About','About','About Shanu',_
'About','Home','Shanu',getdate()-43)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('Contact','Contact','Contact Shanu',_
'Contact','Home','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('Masters','Masters','Masters',_
'ItemDetails','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('ITM001','ItemMaster','Item Master',_
'ItemDetails','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('ITM002','ItemDetail','Item Details',_
'ItemDetails','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('ITM003','ItemManage','Item Manage',_
'ItemManage','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('CAT001','CatMaster','Category Masters',_
'CATDetails','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('CAT002','CATDetail','Category Details',_
'CATDetails','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('CAT003','CATManage','Category Manage',_
'CATManage','Masters','Shanu',getdate()-13)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('Inventory','Inventory','Inventory',_
'Index','Inventory','Shanu',getdate()-23)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('INV001','Inventory','Inventory Details',_
'Index','Inventory','Shanu',getdate()-23)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('FG001','FGIN','FG Receipt',_
'FGIN','Inventory','Shanu',getdate()-43)

Insert into MenuDetails(Menu_ChildID,MenuName,MenuDisplayTxt,_
MenuFileName,MenuURL,UserID,CreatedDate)
values('FG002','FGOUT','FG Issue',_
'FGOUT','Inventory','Shanu',getdate()-13)

select * from MenuMaster

select * from MenuDetails

             select   A.Menu_RootID,
                 B.MDetail_ID,
                 B.Menu_ChildID,
                 B.MenuName,
                 B.MenuDisplayTxt,
                 B.MenuFileName,        
                 B.MenuURL ,          
                 B.UserID                                                     
                 FROM
                 MenuMaster A
                 INNER JOIN MenuDetails B
                 ON A.Menu_ChildID=B.Menu_ChildID

2)创建 WCF REST 服务

打开 Visual Studio 2013,然后选择“文件” -> “新建” -> “项目...”,然后选择 WCF 服务应用程序,然后选择您的项目路径并命名您的 WCF 服务,然后单击 OK

创建 WCF 服务后,我们将在解决方案资源管理器中看到“IService.CS”和“Service1.svc”,如下所示

IService.CS:在“IService.CS”中,默认可以看到三个契约。

  • [ServiceContract]:描述了服务可用的方法或任何操作。服务契约是一个接口,方法可以使用 Operation Contract 属性在服务接口内声明。
  • [OperationContract]:类似于 Web 服务 [WEBMETHOD]。
  • [DataContract]:描述了客户端和服务之间的数据交换。

[ServiceContract]

以下代码将为所有 IService.CS 文件自动创建。我们可以在此处更改并编写自己的代码

    public interface IService1
    {
        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

        // TODO: Add your service operations here
    }
 // Use a data contract as illustrated in the sample below to add 
 // composite types to service operations.

    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }

数据合同

在我们的示例中,我们需要从数据库获取所有菜单明细,所以我创建了一个数据契约“MenuDataContract”。在这里,我们可以看到我们将整个表列名声明为数据成员。

public class MenuDataContract    {
        [DataContract]
        public class MenuMasterDataContract
        {
            [DataMember]
            public string Menu_ID { get; set; }

            [DataMember]
            public string Menu_RootID { get; set; }

            [DataMember]
            public string Menu_ChildID { get; set; }

            [DataMember]
            public string UserID { get; set; }
        }

        [DataContract]
        public class MenuDetailDataContract
        {
            [DataMember]
            public string MDetail_ID { get; set; }

            [DataMember]
            public string Menu_RootID { get; set; }

            [DataMember]
            public string Menu_ChildID { get; set; }

            [DataMember]
            public string MenuName { get; set; }

            [DataMember]
            public string MenuDisplayTxt { get; set; }

            [DataMember]
            public string MenuFileName { get; set; }

            [DataMember]
            public string MenuURL { get; set; }

            [DataMember]
            public string UserID { get; set; }
        }
    }

服务合同

在 Operation Contract 中,我们看到“WebInvoke”和“WebGet”用于在 REST 服务中从数据库检索数据。

RequestFormat = WebMessageFormat.Json,

ResponseFormat = WebMessageFormat.Json,

在这里,我们可以看到请求和响应格式。我在这里使用了 JavaScript 对象表示法 (JSON) 格式。

  • JSON 是一种轻量级的数据交换格式。
  • UriTemplate:在这里我们提供我们的方法名称。

在这里,我声明了三个方法“GetMenuDetails”。“GetMenuDetails”方法获取所有菜单主表和明细,将用于我们的 AngularJs,以便使用过滤器为每个层级显示菜单。

 [ServiceContract]
    public interface IService1
    {
[OperationContract]
        [WebInvoke(Method = "GET",
           RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "/GetMenuDetails/")]
        List<MenuDataContract.MenuDetailDataContract> GetMenuDetails();
 }

Iservice.Cs -> 完整源代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace ShanuMenuCreation_WCF
{
    // NOTE: You can use the "Rename" command on the "Refactor" 
    // menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebInvoke(Method = "GET",
           RequestFormat = WebMessageFormat.Json,
           ResponseFormat = WebMessageFormat.Json,
           UriTemplate = "/GetMenuDetails/")]
        List<MenuDataContract.MenuDetailDataContract> GetMenuDetails();
        // TODO: Add your service operations here
    }

 // Use a data contract as illustrated in the sample below to add composite types 
 // to service operations.
    public class MenuDataContract
    {
        [DataContract]
        public class MenuMasterDataContract
        {
            [DataMember]
            public string Menu_ID { get; set; }

            [DataMember]
            public string Menu_RootID { get; set; }

            [DataMember]
            public string Menu_ChildID { get; set; }

            [DataMember]
            public string UserID { get; set; }
        }

        [DataContract]
        public class MenuDetailDataContract
        {
            [DataMember]
            public string MDetail_ID { get; set; }

            [DataMember]
            public string Menu_RootID { get; set; }

            [DataMember]
            public string Menu_ChildID { get; set; }

            [DataMember]
            public string MenuName { get; set; }

            [DataMember]
            public string MenuDisplayTxt { get; set; }

            [DataMember]
            public string MenuFileName { get; set; }

            [DataMember]
            public string MenuURL { get; set; }

            [DataMember]
            public string UserID { get; set; }
        }
    }
}

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

右键单击您的 WCF 项目,选择 添加新项,然后选择 ADO.NET 实体数据模型,然后单击 添加

选择“从数据库的 EF Designer”并单击“下一步”。

单击 新建连接

在这里,我们可以选择我们的数据库服务器名称,并输入您的 DB 服务器 SQL Server 身份验证用户 ID 和密码。我们已经创建了名为“MenuDB”的数据库,所以我们可以选择该数据库并单击 OK

单击 下一步,选择我们需要使用的表,然后单击 完成

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

Service1.SVC

Service.SVC.CS”实现了 IService 接口,并重写并定义了 Operation Contract 的所有方法。例如,这里可以看到我在 Service1 类中实现了 IService1。为我们的实体模型创建了对象,并在 GetMenuDetails 中使用 LINQ 连接查询,我获取了菜单主表和明细数据。

public class Service1 : IService1
    {
        ShanuMenuCreation_WCF.MenuDBEntities OME;

        public Service1()
        {
            OME = new ShanuMenuCreation_WCF.MenuDBEntities();
        }

        public List<MenuDataContract.MenuDetailDataContract> GetMenuDetails()
        {
            ////var query = (from a in OME.MenuDetails
            ////             select a).Distinct();
             var query = (from A in OME.MenuMaster  
                         join B in OME.MenuDetails on A.Menu_ChildID equals B.Menu_ChildID
                         select new  
                         {  
                            A.Menu_RootID,
                            B.MDetail_ID,
                            B.Menu_ChildID,
                            B.MenuName,
                            B.MenuDisplayTxt,
                            B.MenuFileName,
                            B.MenuURL ,
                            B.UserID
                         }).ToList().OrderBy(q => q.MDetail_ID); 

            List<MenuDataContract.MenuDetailDataContract> MenuList = 
                      new List<MenuDataContract.MenuDetailDataContract>();

            query.ToList().ForEach(rec =>
            {
                MenuList.Add(new MenuDataContract.MenuDetailDataContract
                {
                    MDetail_ID = Convert.ToString(rec.MDetail_ID),
                    Menu_RootID = rec.Menu_RootID,
                    Menu_ChildID = rec.Menu_ChildID,
                    MenuName = rec.MenuName,
                    MenuDisplayTxt = rec.MenuDisplayTxt,
                    MenuFileName = rec.MenuFileName,
                    MenuURL = rec.MenuURL,
                    UserID = rec.UserID,
                });
            });
            return MenuList;
       }    
    }

Web.Config

在 WCF 项目“Web.Config”中

  1. <add binding="basicHttpsBinding" scheme="https" /> 更改为 <add binding="webHttpBinding" scheme="http" />
  2. </behaviors> 替换为
    <endpointBehaviors>
            <behavior>
              <webHttp helpEnabled="True"/>
            </behavior>
          </endpointBehaviors>   

运行 WCF 服务:现在我们已经创建了 WCF REST 服务,让我们运行并测试我们的服务。在我们的服务 URL 中,我们可以添加方法名称,并可以看到来自数据库的 JSON 结果数据。

创建 MVC Web 应用程序

现在我们已经完成了 WCF,现在是时候创建我们的 MVC AngularJS 应用程序了。我们可以向现有项目添加一个新项目,并创建一个新的 MVC Web 应用程序,如下所示。右键单击解决方案中的项目,然后单击 添加新项目,然后输入您的项目名称,然后单击“OK”。

选择 MVC 并单击“OK”。

现在我们已经创建了 MVC 应用程序,是时候添加 WCF 服务并安装 AngularJS 包到我们的解决方案中了。

添加 WCF 服务:右键单击 MVC 解决方案,然后单击 添加,然后单击 服务引用

输入您的 WCF URL 并单击 GO。我的 WCF URL 是 https://:3514/Service1.svc/。

添加您的名字,然后单击 确定

现在我们已成功将 WCF 服务添加到我们的 MVC 应用程序中。

安装 Angular JS 包的步骤

右键单击您的 MVC 项目,然后单击 -> 管理 NuGet 程序包

选择 Online,然后搜索 Angular JS。选择 AngularJs,然后单击 安装

现在我们已经将 AngularJS 包安装到我们的 MVC 项目中。现在让我们创建我们的 AngularJs。

  • Modules.js
  • Controllers.js
  • Services.js

创建 AngularJs 脚本文件的过程

右键单击 Script 文件夹,创建您自己的文件夹来创建 AngularJS 模型/控制器和服务 JavaScript。在您的脚本文件夹中,添加三个 JavaScript 文件,并将它们命名为Modules.jsControllers.jsServices.js,如下所示

Modules.js:在这里,我们添加对Angular.js JavaScript 的引用。我们将模块名称设置为“RESTClientModule”。

/// <reference path="../angular.js" />
/// <reference path="../angular.min.js" />  

var app;
(function () {
    app = angular.module("RESTClientModule", []);
})();

Services.js:在这里,我们为我们的服务提供一个名称,并在 shanucontroller.js 中使用此名称。对于 Angular 服务,我将其命名为“AngularJs_WCFService”。您可以自行命名,但请注意在Controllers.js 中更改名称。Angularjs 可以接收 json 数据;在这里,我们可以看到我提供了我们的 WCS 服务 URL 来获取 Item 详细信息作为 JSON 数据。要将 Item 信息结果插入数据库,我们将数据作为 JSON 数据传递给我们的 WCF 插入方法作为参数。

/// <reference path="../angular.js" /> 
/// <reference path="../angular.min.js" />  
/// <reference path="Modules.js" />    

app.service("AngularJs_WCFService", function ($http) {
    //Get Order Master Records 
    this.geMenuDetails = function () {
        return $http.get("https://:3514/Service1.svc/GetMenuDetails");
    };    
});

AngularJs Controller:在这里,我们添加对Angular.js JavaScript、我们的Module.jsServices.js 的引用。与服务相同。对于控制器,我将其命名为“AngularJsShanu_WCFController”。在控制器中,我完成了所有业务逻辑,并将数据从 WCF JSON 数据返回到我们的 MVC HTML 页面。

  1. 变量声明

    首先,我声明了所有需要使用的局部变量和当前日期,并将日期存储在 $scope.date 中。

    注意$scope.subChildIDS = "ITM001"; 此变量已用于过滤第二级层级。

  2. 方法

    getAllMenuDetails():在此方法中,我将获取所有菜单明细作为 JSON,并将结果绑定到主页面。

    $scope.showsubMenu = function (showMenus,ids) {}

    在此方法中,鼠标悬停时,我将过滤第二级层级菜单明细,并将菜单项添加到列表中。

shanuController.js 完整源代码

/// <reference path="../angular.js" /> 
/// <reference path="../angular.min.js" />  
/// <reference path="Modules.js" />  
/// <reference path="Services.js" />  

app.controller("AngularJsShanu_WCFController", 
function ($scope, $window, AngularJs_WCFService) {
    $scope.date = new Date();
    $scope.showDetails = false;
    $scope.showSubDetails = false;
    $scope.subChildIDS = "ITM001";
    $scope.Imagename = "R1.png";
    getAllMenuDetails();
    //To Get All Records  
    function getAllMenuDetails() {
        var promiseGet = AngularJs_WCFService.geMenuDetails();
        promiseGet.then(function (pl) {
            $scope.MenuDetailsDisp = pl.data
        },
             function (errorPl) {
             });
    }

    $scope.showMenu = function (showMenus) {

        if (showMenus == 1) {
            $scope.Imagename = "R2.png"
            $scope.showDetails = true;
        }
        else {
            $scope.Imagename = "R1.png"
            $scope.showDetails = false;
        }
    }

    $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;       
        }      
    }
});

现在,我们已经创建了 Angular Js 模块/控制器和服务。接下来是什么?

创建 MVC Controller 和 View 以显示我们的结果。

添加 Controller

右键单击Controllers,选择Add Controller,然后选择MVC 5 Controller –Empty,然后单击Add

public class MastersController : Controller
    {
        // GET: Masters
        public ActionResult Index()
        { return View(); }

        public ActionResult ItemDetails()
        { return View(); }

        public ActionResult ItemManage()
        { return View(); }
        public ActionResult CATDetails()
        { return View(); }

        public ActionResult CATManage()
        { return View(); }
    }

添加另一个控制器,名为 InventoryController

public class InventoryController : Controller
    {
        // GET: Inventory
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult FGIN()
        {
            return View();
        }
        public ActionResult FGOUT()
        {
            return View();
        }
    }

1) Index 视图

将视图命名为“Index”。

在视图中,设计您的页面并引用angular.JsModules.jsServices.jsControllers.js

在 Angular JS 中,我们使用 {{ }} 来绑定或显示数据。

在这里,我们可以看到我首先创建了一个表以及与该表相关的一些内容。

首先,在表格中,我使用了 data-ng-controller="AngularJsShanu_WCFController",在这里我们可以看到 data-ng-controller 将用于将控制器的数据绑定到 HTML 表。

使用 < li data-ng-repeat="menus in MenuDetailsDisp | filter:{Menu_RootID:'Root'}" >,我们可以获取所有菜单明细并将第一级层级菜单明细显示为顶部菜单。

在这里,我们可以看到我使用过滤器按rootId与‘Root’进行过滤。在我们的insert查询中,我已经解释过,对于每个顶级菜单,我都会给Rootid为‘Root’。首先,我们添加所有顶级菜单,对于每个顶级菜单,如果存在任何第二级层级,我将加载第二级菜单明细,按第一级RootID进行过滤,如下所示。

<li data-ng-repeat="menus in MenuDetailsDisp | filter:{Menu_RootID:'Root'}">
                                  @{
                                       var url = Url.Action("{{menus.MenuFileName}}", 
                                       "{{menus.MenuURL}}", 
                                       new { id = "{{id=menus.MenuURL}}" });
                                       url = HttpUtility.UrlDecode(url);
                                   }
                                   <a data-ng-href="@url">
                                   {{menus.MenuDisplayTxt}}</a>
                                   <ul class="sub-menu">
                                       <li data-ng-repeat="submenus in MenuDetailsDisp | 
                                       filter:{Menu_RootID:menus.Menu_ChildID}" 
                                       ng-mouseover="showsubMenu(1,submenus.Menu_ChildID);" 
                                       ng-mouseout="showsubMenu(0,submenus.Menu_ChildID);">
                                           @{
                                               var url1 = Url.Action
                                               ("{{submenus.MenuFileName}}", 
                                               "{{submenus.MenuURL}}", 
                                               new { id = "{{id=submenus.MenuURL}}" });
                                               url1 = HttpUtility.UrlDecode(url1);
                                           }
                                           <a data-ng-href="@url1">
                                           {{submenus.MenuDisplayTxt}}</a>

在这里,我们可以看到对于第二级层级,我按 data-ng-repeat="submenus in MenuDetailsDisp | filter :{Menu_RootID:menus.Menu_ChildID}" 进行过滤,其中 menus.Menu_ChildID 是顶级菜单 ID。

与此类似,对于第三级层级,我将使用第二级层级的根 ID 如下

<div style="overflow:visible;height:100px;">
                 <ul class="menu">
                 <li data-ng-repeat="menus in MenuDetailsDisp | filter:{Menu_RootID:'Root'}">
                            @{
                                var url = Url.Action("{{menus.MenuFileName}}", 
                                "{{menus.MenuURL}}", new { id = "{{id=menus.MenuURL}}" });
                                url = HttpUtility.UrlDecode(url);
                             }
                               <a data-ng-href="@url">
                               {{menus.MenuDisplayTxt}}</a>
                               <ul class="sub-menu">
                               <li data-ng-repeat="submenus in MenuDetailsDisp | 
                                filter:{Menu_RootID:menus.Menu_ChildID}" 
                                ng-mouseover="showsubMenu(1,submenus.Menu_ChildID);" 
                                ng-mouseout="showsubMenu(0,submenus.Menu_ChildID);">
                                @{
                                     var url1 = Url.Action("{{submenus.MenuFileName}}", 
                                                "{{submenus.MenuURL}}", 
                                                new { id = "{{id=submenus.MenuURL}}" });
                                                url1 = HttpUtility.UrlDecode(url1);
                                 }
                                     <a data-ng-href="@url1">
                                     {{submenus.MenuDisplayTxt}}</a>
                                     <ul ng-show="showSubDetails" class="sub-menu2">
                                     <li data-ng-repeat="sub1menus in MenuDetailsDisp  | 
                                      filter:{Menu_RootID:subChildIDS}" 
                                      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.MenuDisplayTxt}}</a>
                                        </li>
                                    </ul>
                              </li>
                          </ul>
                        </li>
                    </ul>
               </div>

运行程序

(输出菜单类型 1)

(输出菜单类型 2)

注意:此代码可以用于我们的 MVC 视图页面,或者此代码可以用于 Shared>Layout.Cshtml,以便菜单作为通用菜单,可用于所有页面。在这里,我们可以看到上面相同的菜单代码已添加到Layout.cshtm页面中,这样菜单将全局添加,并且可以从所有页面访问。

您可以根据您的需求扩展此应用程序,并添加更多功能,如用户管理、菜单管理等。

支持的浏览器:Chrome 和 Firefox。

历史

  • 2015 年 6 月 1 日:初始版本
© . All rights reserved.