ASP.NET MVC和Web API中的Angular2 - 第1部分
内容
第1部分:Visual Studio 2017中的Angular2设置,基本CRUD应用程序,第三方模态弹出控件
第2部分:使用Angular2管道进行过滤/搜索,全局错误处理,调试客户端
介绍
由于Angular2广泛应用于Web和移动开发的客户端框架,在本文中,我将尝试解释一步一步的指导,使用Angular2和MVC Web API创建基本的CRUD(创建,读取,更新和删除)应用程序作为后端RESTful API 。我将创建空白的ASP.NET MVC应用程序,然后设置Angular2环境,然后创建将有两个页面的Web应用程序,一个仅用于一个图像的主页,另一个将是用户管理页面,其中将从SQL加载数据服务器数据库和用户可以选择添加新用户,更新和删除现有用户。对于所有数据库操作,Anguar2将调用使用ASP.NET MVC Web API开发的RESTful API。
这是一个初级文章,目的是为初学者和具有编程基础知识的学生撰写,并希望从头开始学习Angular2,C#和RESTful API。如果您是经验丰富的开发人员,只需要概述,您可以下载附件项目并进行浏览。您需要Visual Studio和SQL Server Management Studio在文章中开发项目并编译附加的项目。下载Visual Studio 2017社区和SQL Server Management Studio。
开始吧
设置Angular2环境
- 打开Visual Studio,我正在使用Visual Studio 2017社区,您可以使用Visual Studio 2015社区和更新3安装
Node.js
和TypeScript
包。(阅读更多关于Visual Studio 2015更新3) - 转到文件菜单,然后选择
File -> New -> Project
:
- 输入项目名称并选择所需的.Net框架(我正在
.Net Framework 4.6
为本文使用 )。点击OK
按钮:
MVC
从下一个屏幕中选择并检查Web API
添加文件夹和核心参考选项,因为我们将为CRUD操作创建RESTful API。点击OK
按钮:
- 创建基本的ASP.NET MVC项目,下一步是为Angular2应用程序做准备。我们来做下一步。
- 右键单击项目
Angular2MVC
并选择Add -> New Item
:
- 输入
package.json
右上角的搜索文本框,npm Configuration File
将被过滤。点击Add
按钮添加package.json
项目:
- 我们将使用
NPM (Node Package Manager)
配置文件来管理所有Angular2包。要了解有关NPM的更多信息,请查看此链接。 - 接下来,从Angular2 Quick Start GitHub链接复制Package.json,并将其粘贴
package.json
到Angular2MVC
项目中新增的文件中:
- 在
package.json
文件的依赖部分,我们可以看到所有Angular2相关的软件包,看看这里有什么区别^
和~
签名。 - 右键单击
package.json
文件并选择选项Restore Packages
,Visual StudioNode.js
工具将下载package.json
文件中提到的所有相关软件包,将来如果您需要任何其他软件包,只需将其添加到DevDepnedencies
部分并将其还原,这将使生活更轻松:
- 您将
node_modules
在项目中找到包含所有下载的软件包的新文件夹:
- 下一步让我们的项目知道如何获取这些包,我们将添加
systemjs.config.js
文件。右键单击Angular2MVC
项目并选择Add -> JavaScript file
:
systemjs.config.js
在Item name
字段中输入名称,然后单击OK
按钮:
systemjs.config.js
从Angular2快速启动GitHub 复制文件的内容,并将其粘贴systemjs.config.js
到Angular2MVC
项目中新添加的文件中:
- 接下来,我们
TypeScript JSON Configuration File
通过右键单击Angular2MVC
项目和Add -> New Item
。选择TypeScript JSON Configuration File
并点击OK
按钮:
tsconfig.js
从Angular2快速启动GitHub 复制文件的内容,并将其替换tsconfig.js
为Angular2MVC
项目中新添加的文件:
- 如果您在尝试构建时遇到编译错误,请不用担心。一旦我们开始添加任何
typescript file
,这些错误就会消失。 - 现在,我们在ASP.NET MVC中的Angular2设置几乎完成了,现在是开发应用
User Management
程序的时候了,但是首先我们需要一个数据库,一个表将保存用户信息。
创建用户数据库和实体框架模型
- 右键单击
App_Data
文件夹并选择Add -> New item
。在数据部分,您可以找到该SQL Server Database
选项。选择它并指定名称UserDB
。
- 创建数据库后,双击
UserDB.mdf
数据库文件打开Tables
:
- 右键单击
UserDB.mdf
并选择New Query
。粘贴以下SQL查询来创建TblUser
表,单击Execute
按钮创建表:
<span id="ArticleContent">CREATE TABLE [dbo].[TblUser] ( [Id] INT IDENTITY (1, 1) NOT NULL, [FirstName] NVARCHAR (250) NULL, [LastName] NVARCHAR (250) NULL, [Gender] NVARCHAR (250) NULL, PRIMARY KEY CLUSTERED ([Id] ASC) );</span>
- 右键单击
Tables
文件夹并选择选项Refresh
:
- 接着让开发
ASP.NET MVC
,其包括设置侧Layout
和Index
页面加载Angular2主页沿MVC控制器加载索引视图和Web API 2.0控制器,用于基于REST CRUD( ,,Create
和)用户的API。Read
Update
Delete
- 我们首先去
App_Start
文件夹并配置路由以接受任何URL,因为我们可以在Angular2中定义我们的自定义路由(将在以后的步骤中进行)。双击RouteConfig.cs
文件进行编辑,并按默认路径更改URL,如下所示:
- 接下来,我们打开我们的
_Layout.cshtml,
清理一点,并添加重要JavaScripts
文件来运行Angular2应用程序。打开Views -> Shared -> _Layout.cshtml
文件 删除预先添加的顶层菜单和页面链接。system.import
在标题部分中添加以下JS文件和语句:
<span id="ArticleContent"><script src="/node_modules/core-js/client/shim.min.js"></script> <script src="/node_modules/zone.js/dist/zone.js"></script> <script src="/node_modules/systemjs/dist/system.src.js"></script> <script src="/systemjs.config.js"></script> <script> System.import('app').catch(function(err){ console.error(err); }); </script></span>
只是一个简短的介绍这些JS文件是什么。
Zone.js:
区域是一个持续异步任务的执行上下文。欲了解更多信息,请点击这里。
System.src.js & system.import(‘app’):
可配置模块加载器,可在浏览器和NodeJS中启用动态ES模块工作流程。欲了解更多信息,请点击这里。
- 你的决赛
_Layout.cshtml
应该如下所示:
- 接下来我们来创建
ADO.NET Entity Data Modal
forUserDB
数据库。右键单击Angular2MVC
项目并选择Add -> New Folder
,指定名称DBContext
或任何您想要的:
- 右键单击新创建的文件夹
DBContext
,然后选择Add -> New Item
:
- 从左侧面板下方
Visual C#
选择Data
。在右侧选择ADO.NET Entity Data Model
。输入名称UserDBEntities
或您选择的任何一种。点击Add
按钮。
- 从下一个屏幕,选择
EF Designer for Data
,点击Next
按钮:
- 点击
New Connection
下一个屏幕上的按钮:
- 在下一个屏幕上,如果未选择“数据源”
Microsoft SQL Server Database file (SqlClient)
,请单击Change
按钮并选择它:
- 在
Database file name
,点击Browse
按钮:
- 浏览到
UserDB
在早期步骤中创建并保存在App_Data
文件夹中的数据库,单击OK
两者Select SQL Server Database File
和Connection Properties
窗口上的按钮:
- 选中该
Save Connection Settings in Web.Config as
复选框,然后单击Next
按钮:
- 在下一个屏幕中,您可以选择Entity Framework版本,我正在使用
6.x
,可以根据您的选择使用:
- 在下一个屏幕上单击
Tables
复选框,您将看到唯一的一个表TblUser
,点击Finish
按钮结束向导:
- 这将需要几秒钟,最后你会看到我们的数据库实体模型有一个表:
- 仍然在这一点上,如果你尝试编译你的项目,你可能会收到很多
typescript
错误,为了解决它,创建名称的文件夹app
,右键单击它并选择Add -> TypeScript File
:
- 输入名称
main.ts
并单击OK
(我们将在以后的步骤中使用此文件)。现在重建项目,应该成功建成。
开发用户管理RESTful API
- 下一步是创建
ASP.NET MVC Web APIs
为read
,add
,update
和delete
用户。 - 首先,我们将创建具有所有API控制器共享的常用方法的Parent API控制器,因为现在我们将只有一种方法将类对象序列化为Angular2前端的JSON字符串,也可以为
UserDB
数据库DBContext
对象执行数据库操作子控制器。右键单击Controllers
文件夹,然后选择Add -> Controller…
:
- 选择
Web API 2 Controller – Empty
并点击Add
按钮:
- 输入名称
BaseAPIController
并点击Add
按钮:
- 在下列代码中添加
BaseAPIController
:
<span id="ArticleContent">protected readonly UserDBEntities UserDB = new UserDBEntities(); protected HttpResponseMessage ToJson(dynamic obj) { var response = Request.CreateResponse(HttpStatusCode.OK); response.Content = new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json"); return response; }</span>
-
以上给出的代码是非常不言自明的,我们正在创建
UserDBEntities
名为的类对象,UserDB
通过它可以调用加载,添加,更新和删除用户的方法。ToJson
方法是使用任何类对象,HTTP Response object
使用OK
HttpStatusCode 创建并通过JsonConvert
从Newtonsoft.json
库调用方法将对象序列化为JSON字符串。最终代码应如下所示:
- 接下来,我们来创建
RESTful Web APIs
用户管理,即加载数据库中的所有用户,添加新用户,更新和删除现有用户。我们正在创建以下方法:GET
方法来读取所有用户。POST
创建新用户的方法。PUT
方法来更新现有用户。DELETE
方法删除现有用户。
- 要了解更多关于
HTTP Verbs
和方法,请点击这里 - 右键单击
Controllers
文件夹并选择Add -> Controller…
- 选择
Web API 2 Controller – Empty
并点击Add
按钮:
- 输入名称
UserAPIController
并点击Add
按钮:
- 将UserAPIController类代码替换为以下内容:
<span id="ArticleContent">public class UserAPIController : BaseAPIController { public HttpResponseMessage Get() { return ToJson(UserDB.TblUsers.AsEnumerable()); } public HttpResponseMessage Post([FromBody]TblUser value) { UserDB.TblUsers.Add(value); return ToJson(UserDB.SaveChanges()); } public HttpResponseMessage Put(int id, [FromBody]TblUser value) { UserDB.Entry(value).State = EntityState.Modified; return ToJson(UserDB.SaveChanges()); } public HttpResponseMessage Delete(int id) { UserDB.TblUsers.Remove(UserDB.TblUsers.FirstOrDefault(x => x.Id == id)); return ToJson(UserDB.SaveChanges()); } }</span>
UserAPIController
继承自BaseAPIController
使用UserDB
对象和ToJson
方法将User
实体转换为JSON字符串并将其保存在HTTP响应消息中。Get()
:从数据库加载所有用户,并将包含用户实体的HTTP响应消息转换为JSON
字符串。Post([FromBody]TblUser value)
:从前端取出用户信息并保存到数据库。返回1成功保存。Put(int id, [FromBody]TblUser value)
:取现有的用户ID和更新的信息并将其更新到数据库。返回1成功更新。Delete(int id)
:取现有用户ID,通过id加载用户并删除它。返回1成功删除。
- 最终
UserAPIController
课程应如下所示:
开发Angular2应用程序
- 现在让我们开始编写
Angular2
代码的令人兴奋的部分。在编写代码之前,了解架构是非常重要的Angular2
,因为我不是专注于写Angular2,因为您可以找到大量的教程和免费的视频,让我们修改基本的结构,Angular2
如果你懒得到从这里转到angular.io网站:Modules
:每个Angular应用程序至少有一个Angular模块类,该root
模块。该应用程序bootstrapping
由其根模块启动。在开发过程中,您可能会在随后的步骤中创建AppModule
的main.ts
文件中引导。根模块通常命名AppModule
。在AppModule
我们指定所有components
,services
或自定义pipe
使用的应用程序过滤器。Components
:组件控制屏幕上的视图,您可以定义properties
和methods
控制视图。如果你曾经使用ASP.NET表单,我会说组件就像aspx.cs文件中的代码一样,通过方法和属性来交互aspx文件。Templates
:您可以使用其伴随模板定义组件的视图。Atemplate
是一种HTML形式,它告诉Angular如何渲染组件。它就像aspx
ASP.NET表格中的一个文件,根据我之前的步骤的例子。Metadata
:元数据告诉Angular如何处理一个类。如果您看到该组件,它只是一个类,MetaData告诉您与该组件,任何样式表关联的模板(代码在后面或可以是HTML),或者如何使用通过Selector
属性指定的组件。Data binding
:简单来说,信息或控件之间如何在模板中单击任何按钮之间传播template
,component
例如,如何click
在组件中获取事件并执行逻辑。Angular2提供以下类型的数据绑定:{{}} interpolation
显示组件中声明的任何变量值。[ ] property binding
用于将值从父组件发送到子组件。我们将在未来的章节中使用它。( ) event binding
用于从模板到组件获取任何事件。例如(点击)。
Directives
:两种指令的存在:structural
和attribute
指令。Structural directives
通过添加,删除和替换DOM中的元素来改变布局。例如*ngFor
,*ngIf
用于循环HTML元素并显示/隐藏元素。Attribute directives
改变现有元素的外观或行为。在模板中,它们看起来像常规的HTML属性,因此名称。例如ngStyle
用于样式表,ngModel
用于双向数据绑定。
Services
:服务是一个广泛的类别,涵盖您的应用程序需要的任何价值,功能或功能。关于服务没有什么具体的Angular2。Angular2没有定义服务。没有服务基础类,没有注册服务的地方。服务的例子是Error
,Log
,HTTP
等Component
只能起到模板和用户之间的调解人角色。它应该委托其他功能,例如从服务器获取数据,删除或更新,记录,显示错误等等。Dependency injection
:依赖注入是一种提供一个新实例的方法,它class
具有所需的完全形成的依赖关系。大多数依赖是服务。Angular2使用依赖注入为新组件提供所需的服务。例如,对于HTTP
服务,我们将使用依赖注入来为即将到来的步骤中的组件提供服务实例。- 欲了解更多信息,请点击此处。
- 希望你已经有大约Angular2建筑的基本理念,让创造用户管理页面(
Add
,Update
,Delete
和View
在ASP.NET MVC使用角2使用RESTful API中作为后端服务的用户)。 - 在我们的项目中,我们将在
app
文件夹中创建所有Angular2相关代码,如下所示,如果您尚未创建app
文件夹,请继续创建。如果您遵循以前的步骤,应该main.ts
在应用程序文件夹中有一个typescript文件,我们将用于引导AppModule
:
- 在进一步移动之前,让我展示我们的最终应用程序将如何,它将有两个页面,一个是只有大图像的主页,第二个将具有与用户信息一样的表格,每个记录旁边的编辑和删除按钮一个添加按钮在表的顶部添加新用户。每个按钮将打开模式弹出窗口,您可以在其中执行相应的功能,以下是两页和每个功能的屏幕截图:
- 现在,您已经有了关于我们最终应用程序的基本想法,让我们开始研究Angular2应用程序,让我们牢记Angular2架构并创建应用程序的基本架构。
- 首先让我们创建Angular2
Module
,这将是应用程序的入口点。右键单击app
文件夹,然后选择Add -> TypeScript File
:
- 如果没有看到
TypeScript File
第二个菜单,右键单击app
文件夹,选择Add -> New Item
,搜索TypeScrript
并选择TypeScript file
,输入名称并选择OK
按钮:
- 输入新的TypeScript文件的名称,
app.module.ts
然后单击OK
按钮:
- 在新添加的代码中添加以下代码
app.module.ts
:
<span id="ArticleContent">import { NgModule } from '@angular/core'; import { APP_BASE_HREF } from '@angular/common'; import { BrowserModule } from '@angular/platform-browser'; import { ReactiveFormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; @NgModule({ imports: [BrowserModule, ReactiveFormsModule, HttpModule], declarations: [], providers: [{ provide: APP_BASE_HREF, useValue: '/' }], bootstrap: [] }) export class AppModule { }</span>
- 只是为了刷新你的记忆,我们正在使用
TypeScipt
Angular2。如果您想了解更多关于TypeScript的信息,请点击这里。 - 如果您快速
AppModule
上课,您可以看到我们正在导入所需的库,例如NgModule
从角度核心,类似地,我们将为Reactive forms
用户使用,我们ReactiveFormModule
从角度格式包导入。我们将app.module.ts
通过添加用户组件,服务,模式弹出等继续扩展文件。- 在
NgModule
元数据部分:Imports
包含模块列表。Declarations
包含组件列表,我们将在后续步骤中添加用户组件。Providers
包含服务列表。我们将添加HTTP
操作以执行用户读取,添加,更新和删除操作。现在,它有基本href
路径。Bootstrap
包含条目组件,我们将app.component.ts
在后续步骤中创建文件,并将其添加到此处。
- 在
- 下一步是编辑
main.ts
的app
文件夹并添加下面的代码是:
<span id="ArticleContent">import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app.module'; platformBrowserDynamic().bootstrapModule(AppModule);</span>
main.ts
代码是非常不言自明的。AppModule
引用是从当前文件夹导入,将其作为模块,并使用plateformBrowserDynamic
模块的bootstrapModule
功能加载其他帮助资源(Bootstrapping)以供应用。Bootstrap
函数初始化Angular2应用程序,加载所需的组件,服务或其他帮助资源来运行应用程序。尝试构建项目以避免后续步骤中的任何错误。- 接下来,创建两个TypeScripts文件
app.component.ts
,并app.routing.ts
为主应用程序组件和路由表创建。稍后再回来,右键点击app
文件夹,选择Add -> TypeScript File
:
- 输入名称
app.component.ts
并点击OK
按钮:
- 再次点击
app
文件夹并选择Add -> TypeScript File
,输入名称app.routing.ts
并点击OK
按钮: - 下面我们来创建
Home
一个只有一个大图片的组件: - 我们将在新文件夹中创建所有用户组件,右键单击
app
文件夹并选择Add -> New Folder
,输入名称Components
: - 右键单击新创建的文件夹
Component
,然后选择Add -> TypeScript File
: - 输入名称
home.component.ts
并点击OK
按钮:
- 在新创建的
home.component.ts
文件中添加以下代码:
<span id="ArticleContent">import { Component } from "@angular/core"; @Component({ template: `<img src="../../images/users.png" style="text-align:center"/>` }) export class HomeComponent{ }</span>
- 在
HomeComponent
,您可以在MetaData的模板属性中看到,我们将users.png
在屏幕上显示的根图像文件夹中显示纯HTML图像元素。您可以获取任何图片,将其保存在图像文件夹中并加载HomeComponent
。 - 右键单击
Angular2MVC
项目并选择Add -> New Folder
,输入文件夹名称为images
:
- 右键单击新添加的文件夹
images
,然后选择Open Folder in File Explorer
,在打开的位置复制下面给出的图像: - 我们
HomeComponent
完成了,让屏幕上看到它。我们需要做更多的步骤来做到这一点。我们首先要做的就是创建Routing
表。如果您使用ASP.NET MVC,此路由表与MVC路由表相同。我们将为不同的视图组件定义自定义路由。第二步,我们将创建我们的主要应用程序组件,我们将在此创建导航菜单并加载所有视图组件。- 双击
app.routing.ts
应用程序文件夹进行编辑并添加以下代码:
- 双击
<span id="ArticleContent">import { ModuleWithProviders } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './components/home.component'; const appRoutes: Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', component: HomeComponent } ]; export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);</span>
- 在上面的代码中,我们从角度路由器包导入路由库,最近
HomeComponent
从components文件夹创建。在应用路由器中,该path
属性是浏览器地址栏中可见的实际URL,例如http:// localhost:4500 / home。一旦我们创建UserComponent
,我们将为它添加另一个路由。 - 接下来请双击
app.component.ts
在app
文件夹中进行编辑,并添加以下代码:
<span id="ArticleContent">import { Component } from "@angular/core" @Component({ selector: "user-app", template: ` <div> <nav class='navbar navbar-inverse'> <div class='container-fluid'> <ul class='nav navbar-nav'> <li><a [routerLink]="['home']">Home</a></li> </ul> </div> </nav> <div class='container'> <router-outlet></router-outlet> </div> </div> ` }) export class AppComponent { }</span>
AppComponent
是超薄的模板与已知的引导代码创建导航栏只有一个家庭链接。home
主页的routerlink 名称是我们在app.routing.ts
路由表中定义的。您可以定义任何对您方便的内容,例如默认值,索引等router-outlet
作为动态加载视图组件的占位符。我们还定义selector
属性(user-app
)中的AppComponent
元数据部分,因为我们将引导AppComponent
中AppModule
,并使用这个selector
MVC中的视图(index.cshtml)加载它。有关router-outlet
点击此处的更多信息。- 所以我们创建了应用程序组件(
AppComponent
),让我们去AppModule
和注册HomeComponent
和AppComponent
沿routing
表。之后,我们将添加AppComponent
到bootstrap,为了做到这一切,根据以下更新app.module.ts
:
<span id="ArticleContent">import { NgModule } from '@angular/core'; import { APP_BASE_HREF } from '@angular/common'; import { BrowserModule } from '@angular/platform-browser'; import { ReactiveFormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { AppComponent } from './app.component'; import { routing } from './app.routing'; import { HomeComponent } from './components/home.component'; @NgModule({ imports: [BrowserModule, ReactiveFormsModule, HttpModule, routing], declarations: [AppComponent, HomeComponent], providers: [{ provide: APP_BASE_HREF, useValue: '/' }], bootstrap: [AppComponent] }) export class AppModule { }</span>
- 你可以看到,我们进口
HomeComponent
和AppComponent
还表示,它在声明和自举AppComponent
为切入点,以我们的应用程序。(Bootstrapping不仅仅是前面步骤中讨论的一个入口点,您可以在Google上进行搜索,以完全理解它。为了简单起见,我仅将其称为入口点)。 - 我们几乎可以运行我们的Angular2应用程序并查看主页。转到
Views -> Home
并双击Index.cshtml
进行编辑:
- 删除现有代码并输入以下代码行:
<span id="ArticleContent">@{ ViewBag.Title = "Index"; } <body> <user-app>Loading…<user-app> </body></span>
user-app
是selector
为了AppComponent
,这是我们如何使用HTML中的组件:
- 接下来,在
Solution Explorer
上双击systemjs.config.js
,并在底部添加main.js
的packages
部分:
- 运行该项目,你应该会看到下面的Web应用程序
Home
页面和大的图像,你可以在地址栏看到页面的URL与结尾home
这是我们在主页的路由表中定义相同的URL:
- 到目前为止,我们已经在ASP.NET MVC应用程序中为Angular2创建了一个静态页面的基础架构。下一步是创建
User Management
包括加载所有用户,添加新用户,更新和删除现有用户的页面:
- 在用户管理页面中,我们将使用
TypeScript Interface
(用户模型)Reactive forms
和一个第三方组件Ng2-Bs3-Modal进行模态弹出。 - 接下来让我们创建用户
interface
。右键单击app
文件夹并选择Add -> New Folder
。输入文件夹的名称为Models
:
- 右键单击新创建的
Models
文件夹,然后选择Add -> TypeScript File
,输入文件名为user.ts
:
- 在新创建的用户界面中输入以下变量:
<span id="ArticleContent">export interface IUser { Id: number, FirstName: string, LastName: string, Gender: string }</span>
- 这些
interface
属性与User
数据库中的表相同。关于Angular2的令人敬畏的是,IUser
当我们从数据库中加载数据时,用户对象将自动映射到接口数组RESTful API
,在接下来的步骤中,我们将看到如何完成。 - 在移动之前
UserComponent
,让我们创建一些帮助文件,即Global
变量和Enumeration
。我更喜欢保存文件中的所有端点,错误消息和其他共享变量Global
,我将为CRUD操作创建枚举。右键单击app
文件夹,然后选择Add ->New Folder
,将文件夹命名为shared
:
- 右键单击新创建的
shared
文件夹,然后选择Add -> TyepScript File
,输入名称为global.ts
:
- 复制以下代码
global.ts
:
<span id="ArticleContent">export class Global { public static BASE_USER_ENDPOINT = 'api/userapi/'; }</span>
- 这是
exportable
具有单个静态属性的简单类,BASE_USER_ENDPOINT
具有用于用户管理RESTful API的基本端点。 - 再次右键单击
shared
文件夹并选择Add -> TypeScript File
,输入名称为enum.ts
:
- 输入以下
enum.ts
文件中的代码:
<span id="ArticleContent">export enum DBOperation { create = 1, update = 2, delete =3 }</span>
- 枚举是不言自明的,而不是用于CRUD操作(“创建”,“更新”,“删除”)的硬编码字符串,我们将使用
DBOperation
枚举。 - 接下来,让我们创建一些重要的功能来调用ASP.NET RESTful Web API,以便使用Angular2
HTTP
服务进行用户管理。如前面的步骤所述,我们将为RESTful用户API创建GET,POST,PUT和DELETE请求,这些API已经使用ASP.NET MVC Web API在前面的步骤中创建。右键单击app
文件夹,然后选择Add -> New Folder
,输入名称Service
。
- 右键单击新创建的
Service
文件夹,然后选择Add -> TypeScript File
,输入名称为user.service.ts
:
- 在user.service.ts文件中复制以下代码:
<span id="ArticleContent">import { Injectable } from '@angular/core'; import { Http, Response, Headers, RequestOptions} from '@angular/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/do'; import 'rxjs/add/operator/catch'; @Injectable() export class UserService { constructor(private _http: Http) { } get(url: string): Observable<any> { return this._http.get(url) .map((response: Response) => <any>response.json()) // .do(data => console.log("All: " + JSON.stringify(data))) .catch(this.handleError); } post(url: string, model: any): Observable<any> { let body = JSON.stringify(model); let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); return this._http.post(url, body, options) .map((response: Response) => <any>response.json()) .catch(this.handleError); } put(url: string, id: number, model: any): Observable<any> { let body = JSON.stringify(model); let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); return this._http.put(url+id, body, options) .map((response: Response) => <any>response.json()) .catch(this.handleError); } delete(url: string, id: number): Observable<any> { let headers = new Headers({ 'Content-Type': 'application/json' }); let options = new RequestOptions({ headers: headers }); return this._http.delete(url+id,options) .map((response: Response) => <any>response.json()) .catch(this.handleError); } private handleError(error: Response) { console.error(error); return Observable.throw(error.json().error || 'Server error'); } }</span>
为了了解上述代码,我们需要了解一下Observable
,只需在Google上搜索即可轻松获取相关信息,但我希望能够快速浏览以下链接:
https://scotch.io/tutorials/angular-2-http-requests-with-observables
-
在几行中,
Observable
更像数据流,与promise
方法(Angular 1.x)相反,Observable
不会立即返回响应,而是在流中,它提供了非常有用的方法,例如map
(用于将结果映射到接口),filter
(过滤器来自数据数组的任何特定记录)等Observable
也提供HTTP
请求处理。Rxjs
是一个永恒的图书馆,为我们提供所有的Observable
方法。 -
第一种方法是
get
将RESTful API URL作为参数并返回Observable<any>
,还可以指定interface
返回的特定类型,Observable<IUser[]>
但是我尽量保持通用。在下一行中,通过提供输入RESTful API用户来调用http get方法,调用map
方法将JSON响应映射到any
类型,您可以指定特定类型<IUser[]>response.json()
。类型any
就像dynamic
在C#中,它执行编译类型检查。
- 关于RESTful API的一个很棒的事情是HTTP动词,如函数名称,即如果函数名是从GET,PUT,POST或DELETE开始,我们只需要基本URL(端点),通过HTTP调用,它自动确定相应的函数。很明显,一个Web API控制器应该有一个HTTP动词方法。
- POST,PUT和DELETE的其他方法具有几乎相同的功能体,创建http头,并
IUser
在Web API控制器功能中接收正文的接口,并自动将user
列转换为实体,因为列名匹配。 - 现在我们创建了这个
user
服务,我们把它添加到AppModule
。双击app.module.ts
文件app
夹中的文件夹进行编辑。UserService
通过添加以下行导入:
<span id="ArticleContent">import { UserService} from './Service/user.service'</span>
- 添加在
UserService
提供AppModule
程序部分。
- 之后,让创建
UserComponent
。右键单击Components
文件夹,然后选择Add -> TypeScript File
:
- 输入名称为
user.component.ts
:
- 我们将
template
在单独的html文件中创建,因此右键单击Components
文件夹再次选择Add-> HTML Page
:
- 输入名称为
user.component.html
:
- 之前
UserComponent
,请配置一个第三方组件的模式popng2 -bs3-modal。使用起来非常简单。 Package.json
在Angular2MVC
项目中双击文件,并在以下devDependencies
部分添加以下包:
“ng2-bs3-modal”:“0.10.4”
- 现在让我们从NPM下载这个包,右键点击
package.json
并选择Restore Packages
:
- 双击
systemjs.config.js
的Angular2MVC
项目: - 在以下
map
部分中添加以下文本:
'ng2-bs3-modal':'npm:/ ng2-bs3-modal'
- 在软件包部分添加以下文本:
'NG2-BS3模态':
{main:'/bundles/ng2-bs3-modal.js',defaultExtension:'js'}
- 最终更新应如下所示:
- 现在,由于我们的模态弹出,我们创建
UserComponent
将查看所有用户,添加新用户,编辑和删除现有用户。双击user.component.ts
文件app -> components
夹中的文件夹进行编辑:
- 首先添加以下
import
语句:
<span id="ArticleContent">import { Component, OnInit, ViewChild } from '@angular/core'; import { UserService } from '../Service/user.service'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { ModalComponent } from 'ng2-bs3-modal/ng2-bs3-modal'; import { IUser } from '../Model/user'; import { DBOperation } from '../Shared/enum'; import { Observable } from 'rxjs/Rx'; import { Global } from '../Shared/global';</span>
- 我们正在导入组件
OnInit
(使用OnInit事件)ViewChild
(访问Modal弹出属性)。 - 然后我们导入
UserSerivce
执行对服务器的HTTP调用。 - 在
UserComponent
我们将使用Reactive
(模型驱动)表单,我发现方式比模板驱动的表单更有条理和易于使用。对我来说,它看起来像一个强力类型的ASP.NET MVC剃刀视图,它也是好的unit testing
。表单域,验证和验证错误可以在TypeScript端进行管理,HTML视图具有最小的形式逻辑,这是将代码保存在一个地方的良好做法。要了解有关活动表单的更多信息,请点击此处。 ModalComponent
是我们以前的步骤下载的第三方模态弹出窗口。IUser
是我们将用作模型的界面,用于存储用户信息。DBOperation
并且Global
是枚举和全局变量。Observable
我们在前面的步骤中简要讨论过。我们将使用subscribe
并filter
从Rxjs库函数。- 下面复制以下元素元数据信息的import语句:
<span id="ArticleContent">@Component({ templateUrl: 'app/Components/user.component.html' })</span>
- 既然
User
是一个父组件,我们不会在任何其他组件中使用它,所以我们没有指定Selector
属性。用户组件的HTML将被user.component.html
存档。 - 接下来让我们启动
UserComponent
类体,并声明所需的变量:
<span id="ArticleContent">export class UserComponent implements OnInit { @ViewChild('modal') modal: ModalComponent; users: IUser[]; user: IUser; msg: string; indLoading: boolean = false; userFrm: FormGroup; dbops: DBOperation; modalTitle: string; modalBtnTitle: string; }</span>
- 我们正在开始我们的课程
export
,然后与我们的UserComponent
名字,因为我们将使用onInit
事件,我们的班级应该实施这个。 - 下一行开头
@ViewChild(‘modal’)
,则modal
是占位符模态弹出组件,我们将在HTML模板创建。如果您要访问TypeScript中的任何HTML元素,这是语法。:ModalComponent
指定元素的类型。 - 接下来,我们创建一个
IUser
接口数组来保存用户列表,并使用一个IUser来保存一个用户信息进行添加,编辑和删除。其他几个字符串和布尔变量,我们将在后续步骤中使用来显示一些消息。 - 正如我们在之前的步骤中讨论的,我们将使用
Reactive
(Model-driven)形式,因此我们创建了userform
Formgroup类型。 - 接下来是
constructor
为UserComponent类添加:
<span id="ArticleContent">constructor(private fb: FormBuilder, private _userService: UserService) { }</span>
- 关于Angular2的伟大事情是依赖注入,在构造函数中可以看到,我们通过DI 获取
FormBuilder
和UserService
实例。要了解更多DI,请点击这里。 - 到目前为止,我们
UserComponent
应该如下所示:
- 在这一点上,您可能会收到错误,因为
ngOnInit
尚未实现ngOnInit
事件,我们继续添加事件,我们将创建并初始化“活动用户”窗体:
<span id="ArticleContent">ngOnInit(): void { this.userFrm = this.fb.group({ Id: [''], FirstName: ['', Validators.required], LastName: [''], Gender: [''] }); this.LoadUsers(); }</span>
- 我们正在初始化用户表单,指定表单元素和验证规则。现在窗体用空字符串“'初始化。
- 接下来让我们创建一个
LoadUsers
方法,如name所示,这个方法将调用get方法UserService
从数据库中通过RESTful API加载所有用户:
<span id="ArticleContent">LoadUsers(): void { this.indLoading = true; this._userService.get(Global.BASE_USER_ENDPOINT) .subscribe(users => { this.users = users; this.indLoading = false; }, error => this.msg = <any>error); }</span>
-
Subscribe
是Observable
我们以前步骤讨论的一部分。一旦用户加载完成,它将保存在users
变量中。如果有任何错误,错误信息将被保存在msg
变量中。indLoading
是我们在这里使用的布尔变量来显示加载消息,直到完全响应被加载。 -
接下来,我们添加三种方法来显示添加,更新和删除用户的模态弹出窗口。添加以下函数的代码:
<span id="ArticleContent">addUser() { this.dbops = DBOperation.create; this.SetControlsState(true); this.modalTitle = "Add New User"; this.modalBtnTitle = "Add"; this.userFrm.reset(); this.modal.open(); } editUser(id: number) { this.dbops = DBOperation.update; this.SetControlsState(true); this.modalTitle = "Edit User"; this.modalBtnTitle = "Update"; this.user = this.users.filter(x => x.Id == id)[0]; this.userFrm.setValue(this.user); this.modal.open(); } deleteUser(id: number) { this.dbops = DBOperation.delete; this.SetControlsState(false); this.modalTitle = "Confirm to Delete?"; this.modalBtnTitle = "Delete"; this.user = this.users.filter(x => x.Id == id)[0]; this.userFrm.setValue(this.user); this.modal.open(); } </span>
-
这些所有的方法都是类似的,所以让我们来看看AddUser方法并理解它。首先,我们将当前的DB操作存储在枚举类型的
dpops
变量中DBOperation
。接下来,我们正在调用SetControlsState
将启用或禁用表单控件的方法。下一个变量是设置模态弹出标题和按钮标题。在AddUser函数中,我们正在重置表单以清除表单。接下来,我们调用modal.open()
函数来查看模态弹出窗口。在编辑和删除用户方法中,我们获得UserID
了参数,调用了Observable的过滤方法,从用户列表中获取单个用户。过滤器语法就像C#中的匿名方法。下一行是将单个用户分配给用户表单,该值将设置为前端,一块蛋糕。 -
我们来创建
SetControlsState
它将启用或禁用该表单。Reactive
窗体具有启用和禁用的方法,使控件只读和可编辑。
<span id="ArticleContent">SetControlsState(isEnable: boolean) { isEnable ? this.userFrm.enable() : this.userFrm.disable(); }</span>
-
接下来的方法是
onSubmit
实际获取表单值并基于DBOperation
枚举值,它执行添加,更新和删除操作,我们使用简单的switch语句,粘贴以下代码:
<span id="ArticleContent">onSubmit(formData: any) { this.msg = ""; switch (this.dbops) { case DBOperation.create: this._userService.post(Global.BASE_USER_ENDPOINT, formData._value).subscribe( data => { if (data == 1) //Success { this.msg = "Data successfully added."; this.LoadUsers(); } else { this.msg = "There is some issue in saving records, please contact to system administrator!" } this.modal.dismiss(); }, error => { this.msg = error; } ); break; case DBOperation.update: this._userService.put(Global.BASE_USER_ENDPOINT, formData._value.Id, formData._value).subscribe( data => { if (data == 1) //Success { this.msg = "Data successfully updated."; this.LoadUsers(); } else { this.msg = "There is some issue in saving records, please contact to system administrator!" } this.modal.dismiss(); }, error => { this.msg = error; } ); break; case DBOperation.delete: this._userService.delete(Global.BASE_USER_ENDPOINT, formData._value.Id).subscribe( data => { if (data == 1) //Success { this.msg = "Data successfully deleted."; this.LoadUsers(); } else { this.msg = "There is some issue in saving records, please contact to system administrator!" } this.modal.dismiss(); }, error => { this.msg = error; } ); break; } }</span>
-
代码是非常简单和不言而喻的,一旦我们提交表单,它会发送我们可以通过
.value
属性获取的所有值。这在TypeScript方面几乎是这样。 -
我们来写一下HTML模板
UserComponent
。双击user.component.html
进行编辑:
-
复制以下代码
user.component.html
:
<span id="ArticleContent"><div class='panel panel-primary'> <div class='panel-heading'> User Management </div> <div class='panel-body'> <div class='table-responsive'> <div style="padding-bottom:10px"><button class="btn btn-primary" (click)="addUser()">Add</button></div> <div class="alert alert-info" role="alert" *ngIf="indLoading"><img src="../../images/loading.gif" width="32" height="32" /> Loading...</div> <div *ngIf='users && users.length==0' class="alert alert-info" role="alert">No record found!</div> <table class='table table-striped' *ngIf='users && users.length'> <thead> <tr> <th>First Name</th> <th>Last Name</th> <th>Gender</th> <th></th> </tr> </thead> <tbody> <tr *ngFor="let user of users"> <td>{{user.FirstName}}</td> <td>{{user.LastName}}</td> <td>{{user.Gender}}</td> <td> <button title="Edit" class="btn btn-primary" (click)="editUser(user.Id)">Edit</button> <button title="Delete" class="btn btn-danger" (click)="deleteUser(user.Id)">Delete</button> </td> </tr> </tbody> </table> <div> </div> </div> <div *ngIf="msg" role="alert" class="alert alert-info alert-dismissible"> <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button> <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span> <span class="sr-only">Error:</span> {{msg}} </div> </div> </div> <modal #modal> <form novalidate (ngSubmit)="onSubmit(userFrm)" [formGroup]="userFrm"> <modal-header [show-close]="true"> <h4 class="modal-title">{{modalTitle}}</h4> </modal-header> <modal-body> <div class="form-group"> <div> <span>Full name*</span> <input type="text" class="form-control" placeholder="First Name" formControlName="FirstName"> </div> <div> <span>Full name</span> <input type="text" class="form-control" placeholder="Last Name" formControlName="LastName"> </div> <div> <span>Gender*</span> <select formControlName="Gender" class="form-control"> <option>Male</option> <option>Female</option> </select> </div> </div> </modal-body> <modal-footer> <div> <a class="btn btn-default" (click)="modal.dismiss()">Cancel</a> <button type="submit" [disabled]="userFrm.invalid" class="btn btn-primary">{{modalBtnTitle}}</button> </div> </modal-footer> </form> </modal></span>
-
如果你看Add按钮,我们
AddUser
通过使用(click)
函数来调用这个函数,这个函数是event
前面步骤讨论过的绑定的例子。 -
接下来,我们使用
*ngIf
,structural directives
显示基于indLoading
布尔变量的加载消息。 -
接下来,我们使用
*ngFor
结构指令来循环遍历users
数组并显示用户信息。 -
下一个代码是用于模态弹出,您可以看到
#modal
占位符,我们正在使用它来访问它在TypeScript侧通过@ViewChild
访问打开和关闭功能。 -
接下来我们创建表单,
(ngSumbit)
事件将表单数据发送到TypeScriptonSumit
函数。 -
通过
[formgorup]
属性绑定,我们分配userform
我们在TypeScript端创建的。我们通过formControlName
属性告诉我们的模板相应的表单控件。 -
添加和编辑按钮将被禁用,直到表单有效。这是通过
[disabled]
属性绑定处理,直到userform.invalid
属性启用。 -
就这样
UserComponent
,现在让我们添加UserComponent的路由并添加它AppModule
。 -
双击
app.routing.ts
在app
文件夹中进行编辑:
-
UserComponent
通过以下代码 导入:
<span id="ArticleContent">import { UserComponent } from './components/user.component';</span>
-
添加
UserComponent
路线如下:
<span id="ArticleContent">{ path: 'user', component: UserComponent }</span>
-
决赛
app.routing.ts
应该如下所示:
-
app.component.ts
双击编辑:
-
在应用模块中添加用户组件:
<span id="ArticleContent">import { UserComponent } from './components/user.component';</span>
-
添加
UserComponent
在声明部分中,最终AppModule
应该如下所示:
-
为用户管理添加菜单项,双击
app.component.ts
并添加以下行:
<span id="ArticleContent"><li><a [routerLink]="['user']">Users Management</a></li></span>
-
决赛
app.component.ts
应该如下:
-
编译并运行应用程序。