使用 ASP.NET MVC、$http & $window 服务、EF 和 CRUD 实现的第一个 AngularJs 应用程序






4.73/5 (15投票s)
在本文中,我们将使用流行的 AngularJs 库、ASP.NET MVC、$http & $window 服务和 Entity Framework 以及 Linq 来实现 CRUD 操作。
引言
在本文中,我们将使用最受欢迎的客户端库之一“AngularJs”来实现 CRUD 操作,并使用 Entity Framework & DB first 方法的 ASP.NET MVC 应用业务逻辑。
进度
我们将从创建一个全新的 ASP.NET MVC 项目开始,然后按以下步骤进行:
- 将 AngularJs 库添加到我们的项目,进行打包并启用优化
- 将 Bundle 引用添加到布局页面,并检查 Angular 是否正常工作
- 添加联系人列表客户端功能
- 使用数据库优先方法添加 EF (edmx) 并生成 POCO 类
- 创建带有 Linq 语句的 Repository 类以执行所有 CRUD 操作
- 创建一个自定义 Angular Service “Repo”来访问服务器端控制器,并
- 最后,创建我们的自定义 Angular Directive 并附带模板
创建全新的 ASP.NET MVC 项目
首先创建一个新的 ASP.NET MVC 项目。在此演示中,我使用了 VS 2013,包含了 MVC 核心,并且不包含 Web API 和 Web Forms。
由于本文的重点是 AngularJs,并且为了消除不必要的代码,请单击“更改身份验证”按钮,将身份验证设置为“无身份验证”。这将删除所有与身份验证相关的代码,无论是使用 Windows/Forms 还是 OWIN。
我们的项目最初看起来像这样,在“Views”文件夹中包含“Home”控制器及其相关视图。
现在,我们将向 Controllers 文件夹添加一个新的 MVC 5 空控制器“Ng
”。
注意:创建控制器将自动在“Views”文件夹中添加新文件夹,用于存放其所有对应的视图。如果未添加,请在“Views”文件夹中创建一个与控制器同名的文件夹。
现在,我们将向新控制器添加第一个操作方法“NgFirst
”。
[HttpGet]
public ActionResult NgFirst()
{
return View();
}
转到并创建我们的“NgFirst
”视图,右键单击 View()
;然后选择“添加视图…”。使用我们现有的布局页面作为其主布局。
添加控制器“Ng
”和视图“NgFirst
”后,我们的解决方案看起来是这样的。
将 Angularjs 库添加到我们的项目,进行打包并启用优化
现在,是时候使用“NuGet 包管理器”将 AngularJS 库添加到我们的项目了。右键单击项目引用,然后单击“管理 NuGet 程序包…”
搜索“AngularJs”,NuGet 将列出所有与 AngularJs 相关的项。在此演示中,我们只需要名为 AngularJS Core 的“核心”功能。
安装 AngularJs Core 后,将把以下 JavaScript 文件添加到Scripts文件夹。
打开位于“App_Start”文件夹中的“BundleConfig.cs”文件,创建一个指向所有 Angular js 文件的虚拟路径“ng
”。
bundles.Add(new ScriptBundle("~/bundles/ng")
.Include(
"~/Scripts/angular.js",
"~/Scripts/angular-mocks.js"));
BundleTable.EnableOptimizations = false;
将 Bundle 引用添加到布局页面,并检查 AngularJs 是否正常工作
打开“_Layout.cshtml”文件,添加新创建的 bundle 虚拟路径名“ng
”。
注意:在 @RenderSection
标签之前,在 bootstrap 之后。
@Scripts.Render("~/bundles/ng")
另外,在布局页面的顶部导航菜单栏上添加一个新的 Action 链接“{{ng-First}}
”。
<li>@Html.ActionLink("{{NgFirst}}", "NgFirst", "Ng")</li>
检查与 AngularJs 和 bundle 相关的所有内容是否设置正确,将以下标记添加到我们的“NgFirst
”视图。生成并运行项目。
<div ng-app>
<p>{{ "Hello" + " World" }}</p>
<p>{{ 2 + 4 }}</p>
</div>
生成并运行应用程序以查看我们的“NgFirst
”视图。使用 Firebug 进行检查时,应如下所示:
这意味着我们的 AngularJs 库已成功加载并成功评估了语句。
注意:如果 AngularJs 未正确加载,我们的视图将如下所示:
添加“联系人列表”客户端功能
在我们的第一个应用程序中,我们将创建一个联系人列表表单,从中获取用户输入的三个字段(名字、姓氏和电子邮件),并使用 Angular 控制器将其保存到列表中。
注意:此时我们不使用任何服务器端 MVC 或 API 控制器。我们所做的只是将数据持久化到客户端的数组对象中。
将以下 HTML 标记添加到页面
<div ng-app="ContactList" ng-controller="ContactCtrl">
<h2>Contact Details</h2>
<form>
<div class="col-sm-12">
<div><input type="hidden" ng-model="c.Id" /></div>
<div class="col-sm-3"><input type="text"
placeholder="First Name" class="form-control"
ng-model="c.FirstName" id="firstName" /></div>
<div class="col-sm-3"><input type="text"
placeholder="Last Name" class="form-control"
ng-model="c.LastName" /></div>
<div class="col-sm-3"><input type="email"
placeholder="email@somedomain.com"
class="form-control" ng-model="c.Email" /></div>
<div class="col-sm-3">
<input type="submit" value="Save"
class="btn btn-primary" ng-click="addContact(c);"
ng-hide="IsInEditMode" />
<input type="submit" value="Edit"
class="btn btn-primary" ng-click="editContact(c);"
ng-show="IsInEditMode" /><input type="button" value="Cancel"
class="btn btn-default" ng-click="clearFields();" />
</div>
</div>
</form><br />
<div ng-show="haveContacts();">
<h2>Contact List</h2>
<hr />
<table class="table table-striped">
<thead>
<tr>
<td>Id</td>
<td>Name</td>
<td>Email</td>
<td></td>
</tr>
</thead>
<tbody>
<tr ng-repeat="contact in contacts">
<td>{{contact.Id}}</td>
<td>{{contact.FirstName + " " + contact.LastName}}</td>
<td><span ng-bind="contact.Email"></span></td>
<td>
<button type="button" class="btn btn-primary btn-xs"
ng-click="doEdit(contact);">
<span class="glyphicon glyphicon-edit"
aria-hidden="true"></span> Edit
</button>
<button type="button" class="btn btn-danger btn-xs"
ng-click="deleteContact(contact.Id);">
<span class="glyphicon glyphicon-remove"
aria-hidden="true">
</span> Delete
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
还将以下脚本添加到视图的底部
在向视图添加 JavaScript 之前,让我们先在布局页面上的 bundle 脚本语句之后添加一个scripts 部分。这允许我们将位于子/容器视图的脚本部分中的所有 JavaScript 渲染到布局脚本之后。
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@Scripts.Render("~/bundles/ng")
@RenderSection("scripts", required: false)
“required: false
”表示视图中的 JavaScript 部分不是必需的。否则,它将引发错误。
警告:视图中使用的所有脚本都必须放在script 部分内。否则,您的脚本可能无法按预期工作。
@section scripts{
<script>
var myContact = angular.module("ContactList", []);
myContact.controller("ContactCtrl",
["$scope", "$window", function ($scope, $window) {
$scope.contacts = [{ Id: 1, FirstName: "Sree",
LastName: "M", Email: "abc@bbc.com" }];
$scope.c = { Id: 1, FirstName: "Sree",
LastName: "M", Email: "abc@bbc.com" };
// Flag variable to check if the form is in edit mode - initially set to false
$scope.IsInEditMode = false;
clearFields = function () {
$scope.c.Id = "";
$scope.c.FirstName = "";
$scope.c.LastName = "";
$scope.c.Email = "";
$scope.IsInEditMode = false;
};
$scope.clearFields = clearFields;
addContact = function (contact) {
if ((contact.FirstName === "") ||
(contact.LastName === "") || (contact.Email === "")) {
$window.alert("Input fields cannot be empty!");
$("#firstName").focus();
}
else {
var localContact = angular.copy(contact);
if ($scope.contacts.length === 0)
localContact.Id = 1;
else
localContact.Id = $scope.contacts[$scope.contacts.length - 1].Id + 1;
$scope.contacts.push(localContact);
clearFields();
}
};
$scope.addContact = addContact;
doEdit = function (contact) {
var localCopy = angular.copy(contact);
$scope.c.Id = localCopy.Id;
$scope.c.FirstName = localCopy.FirstName;
$scope.c.LastName = localCopy.LastName;
$scope.c.Email = localCopy.Email;
$scope.IsInEditMode = true;
}
$scope.doEdit = doEdit;
editContact = function (xContact) {
var localCopy = angular.copy(xContact);
for (var i = 0; i < $scope.contacts.length; i++) {
if (xContact.Id === $scope.contacts[i].Id) {
$scope.contacts[i].Id = localCopy.Id;
$scope.contacts[i].FirstName = localCopy.FirstName;
$scope.contacts[i].LastName = localCopy.LastName;
$scope.contacts[i].Email = localCopy.Email;
clearFields();
return;
}
}
$scope.contacts.push(localCopy);
clearFields();
}
$scope.editContact = editContact;
deleteContact = function (Id) {
if ($window.confirm("Are you sure you want to delete the contact?")) {
for (var i = 0; i < $scope.contacts.length; i++) {
if (Id === $scope.contacts[i].Id) {
$scope.contacts.splice(i, 1);
break;
}
}
}
}
$scope.deleteContact = deleteContact;
haveContacts = function () {
return $scope.contacts.length > 0 ? true : false;
}
$scope.haveContacts = haveContacts;
//clearFields();
}]);
</script>
}
以下是我们视图中使用的 Ng 指令:
ng-app
:这表示我们在页面上声明了一个 Angular 容器,并且ng-app
装饰元素内的所有内容都已准备好在运行时由浏览器解析 Angular 指令和求值{{ }}
语法。ng-controller
:唯一负责控制 UI 的控制器。它应该只包含单个视图所需的业务逻辑。ng-model
:ng-model
指令将输入、选择、文本区域(或自定义表单控件)绑定到作用域上的属性。它充当双向绑定指令。ng-model
将尝试通过在当前作用域上求值表达式来绑定到指定的属性。如果当前作用域上尚不存在该属性,它将被隐式创建并添加到作用域。ng-click
:此指令允许我们将作用域级别的对象/函数分配给元素的客户端点击事件。ng-hide/ng-show
:ng-hide
/ng-show
指令根据提供给ng-hide
/ng-show
属性的表达式来显示或隐藏给定的 HTML 元素。ng-repeat
:允许我们循环遍历项目集合并为每个项目应用模板。ng-bind
:该属性指示 Angular 用给定表达式或作用域级别变量的值替换元素的内容,并在表达式发生更改时更新内容。
以下是我们视图中使用的 Ng 服务:
$scope
:此服务通过一种机制来监视模型变化,从而实现模型和视图之间的分离。它们还提供事件发射/广播和订阅功能。$window
:指向浏览器窗口。此服务类似于 JavaScript 中的 window 对象。
以下是我们视图中使用的 Ng 方法:
Angular.copy
:创建源的深层副本,源应为对象或数组。这使我们不必将对象及其 Angular 双向绑定一起复制。- 代码说明:在此示例中,我们创建了一个
$scope
级别的对象“c
”,它将保存 Id、名字、姓氏和电子邮件的当前值。一个数组对象“contacts
”用于保存添加的联系人列表,以及一个标志变量“IsInEditMode
”用于保存表单的可编辑模式。我们还创建了容器方法来在客户端执行添加、编辑和删除操作。
JavaScript 代码本身解释了很多。它在客户端执行基本的 CRUD 操作。
使用数据库优先方法添加 EF (edmx) 并生成 POCO 类
现在,我们将使用 ASP.NET MVC 添加服务器端行为(CRUD)。我们将使用现有的“NgController
”来处理所有 CRUD 操作,同时创建一个新的实体模型(.edmx),该模型将指向 SQL Server 数据库。
首先,让我们创建一个新数据库“FirstAngularJs
”。使用以下脚本创建表“[User]
”。
USE [FirstAngularJs]
GO
/****** Object: Table [dbo].[User] Script Date: 05/04/2015 4:06:26 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[User](
[Id] [int] IDENTITY(1,1) NOT NULL,
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[Email] [nvarchar](100) NULL,
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] 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
现在,我们将向Model文件夹添加一个名为“Model.edmx”的“ADO.NET 实体数据模型”。从向导中选择“从数据库生成的 EF 设计器”。
单击“下一步”,并为本次演示选择 Entity Framework 6.x 版本。
注意:在此应用程序中,我使用了 EF 版本 6。但是,我们也可以选择其他版本。
连接到您的数据库,选择“User
”表。同时指定web.config文件中出现的连接字符串名称。
注意:此处给出的连接字符串名称将与我们的实体模型上下文相同。
再次单击“下一步”,并选择我们之前在 SQL Server Management Studio 中创建的表。取消选中“复数化/…”并为我们的模型设置命名空间。单击“完成”以生成 POCO(纯旧 CLR 对象)类。
注意:代码生成工具 T4(文本模板转换工具包)在实际创建我们的 POCO 类之前会产生一些警告消息。单击“确定”继续。
一切完成后,我们的实体模型看起来将是这样的:
创建带有 Linq 语句的 Repository 类以执行所有 CRUD 操作
接下来,我们将向项目根目录添加“Repository”文件夹,该文件夹通常包含与数据库交互的类。我们将添加一个名为“UserRepository.cs”的类,并使用 Linq 实现 CRUD 操作。
public class UserRepository
{
private ngFirstEntitiesConStr _context;
public UserRepository()
{
_context = new ngFirstEntitiesConStr();
}
public bool CreateUser(User model)
{
_context.User.Add(model);
return (_context.SaveChanges() > 0);
}
public List<User> GetAllUsers()
{
return _context.User.ToList();
}
public User GetUserById(int Id)
{
return _context.User.Where(u => u.Id == Id).SingleOrDefault();
}
public bool UpdateUser(User usr)
{
User userToUpdate = _context.User.Where(u => u.Id == usr.Id).SingleOrDefault();
userToUpdate.FirstName = usr.FirstName;
userToUpdate.LastName = usr.LastName;
userToUpdate.Email = usr.Email;
_context.Entry(userToUpdate).State = System.Data.Entity.EntityState.Modified;
return (_context.SaveChanges() > 0);
}
public bool DeleteUser(int Id)
{
try
{
User ItemToDelete = _context.User.Where(u => u.Id == Id).SingleOrDefault();
_context.Entry(ItemToDelete).State = System.Data.Entity.EntityState.Deleted;
return (_context.SaveChanges() > 0);
}
catch (Exception)
{
return false;
}
}
}
现在,使用新的操作方法更新我们的“NgController
”,以便从存储库创建、更新、删除和获取用户联系人,如下所示:
UserRepository repo = new UserRepository();
[HttpPost]
public JsonResult CreateUser(User user)
{
return Json(repo.CreateUser(user));
}
[HttpGet]
public JsonResult GetUsers()
{
return Json(repo.GetAllUsers(), JsonRequestBehavior.AllowGet);
}
[HttpGet]
public JsonResult GetUser(int id)
{
return Json(repo.GetUserById(id), JsonRequestBehavior.AllowGet);
}
[HttpPost]
public JsonResult UpdateUser(User user)
{
return Json(repo.UpdateUser(user));
}
[HttpPost]
public JsonResult DeleteUser(int Id)
{
return Json(repo.DeleteUser(Id), JsonRequestBehavior.AllowGet);
}
与传统地使用 jQuery Ajax 调用访问我们的控制器操作方法不同,现在我们依赖 Angular 服务($http)。这一点至关重要,因为我们将创建带有 $http
依赖项的自定义 Angular 服务。
注意:我们需要让 Angular 控制器独立于访问远程服务器方法相关的逻辑,我们必须使用自定义 Angular 服务来处理繁重的工作。
$http:此服务是核心 Angular 服务,它通过浏览器的 XMLHttpRequest
对象或 JSONP 促进与远程 HTTP 服务器的通信。
在创建 Angular 模块后立即将自定义 Angular 服务添加到我们的脚本中
// Angular service to handle all remote server interactions
myApp.service("Repo", ["$http", function ($http) {
// Add new Contact
this.addUser = function (usr) {
var userObj = { "Id": usr.Id, "FirstName":
usr.FirstName, "LastName": usr.LastName, "Email": usr.Email }
var config = { method: "POST",
url: "@Url.Action("CreateUser", "Ng")", data: userObj };
return $http(config);
};
// Get All Contacts
this.GetUsers = function () {
return $http.get("@Url.Action("GetUsers", "Ng")");
};
// Get Single Contact
this.GetUser = function (id) {
var config = { method: "GET",
url: "@Url.Action("GetUser", "Ng")", data: Id };
$http(config)
.success(function (data, status, header, config) {
alert(data);
}).error(function (data, status, header, config) {
alert("Error: Something went wrong");
});
};
// Edit Contact
this.editUser = function (usr) {
var userObj = { "Id": usr.Id, "FirstName":
usr.FirstName, "LastName": usr.LastName, "Email": usr.Email };
var config = { method: "POST",
url: "@Url.Action("UpdateUser", "Ng")", data: userObj };
return $http(config);
};
// Delete Contact
this.deleteUser = function (id) {
var userObj = { "Id": id };
var config = { method: "POST",
url: "@Url.Action("DeleteUser", "Ng")", data: userObj };
return $http(config);
};
}]);
如果我们查看我们的“Repo
”服务,我们将 $http
服务注入到我们的处理程序中。此外,我们有几个方法可以与服务器端操作方法进行交互。我们所做的只是配置请求方法并调用 $http
服务。
基本上,配置 $http
服务需要设置操作URL、方法类型(GET/POST)以及可选的要发布到服务器的数据。这是一个以 POST
方法类型将联系人详细信息作为“userObj
”调用“Ng
”控制器中的“CreateUser
”操作方法的示例。
var userObj = { "Id": usr.Id, "FirstName":
usr.FirstName, "LastName": usr.LastName, "Email": usr.Email }
var config = { method: "POST",
url: "@Url.Action("CreateUser", "Ng")", data: userObj };
return $http(config);
注意:$http(config)
将返回一个 Promise。使用 Promise,我们可以访问成功和/或错误回调方法。
现在,我们需要更新我们的“ContactCtrl
”控制器,使其能够使用我们自定义的 Angular 服务“Repo
”。我们通过将我们的自定义服务“Repo
”注入到我们的控制器对象中来做到这一点。
// Controller is update with the custom Repo and window service dependancy
myContact.controller("ContactCtrl",
["$scope", "$window", function ($scope, $window) {
$scope.contacts = [];
$scope.c = { Id:"" ,
FirstName: "", LastName: "", Email: "" };
// Flag variable to check if the form is in edit mode - initially set to false
$scope.IsInEditMode = false;
clearFields = function () {
$scope.c.Id = "";
$scope.c.FirstName = "";
$scope.c.LastName = "";
$scope.c.Email = "";
$scope.IsInEditMode = false;
};
$scope.clearFields = clearFields;
addContact = function (contact) {
Repo.addUser(usr)
.success(function (data, status, header, config) {
getUsers();
clearFields();
$scope.isEditMode = false;
$("#firstName").focus();
})
.error(function (data, status, header, config) {
alert("Error: Something went wrong");
});
//if ((contact.FirstName === "") ||
(contact.LastName === "") || (contact.Email === "")) {
// $window.alert("Input fields cannot be empty!");
// $("#firstName").focus();
//}
//else {
// var localContact = angular.copy(contact);
// if ($scope.contacts.length === 0)
// localContact.Id = 1;
// else
// localContact.Id = $scope.contacts[$scope.contacts.length - 1].Id + 1;
// $scope.contacts.push(localContact);
// clearFields();
//}
};
$scope.addContact = addContact;
doEdit = function (contact) {
var localCopy = angular.copy(contact);
$scope.c.Id = localCopy.Id;
$scope.c.FirstName = localCopy.FirstName;
$scope.c.LastName = localCopy.LastName;
$scope.c.Email = localCopy.Email;
$scope.IsInEditMode = true;
}
$scope.doEdit = doEdit;
getUsers = function () {
Repo.GetUsers()
.success(function (data, status, header, config) {
$scope.users = data;
})
.error(function (data, status, header, config) {
alert("Error: Something went wrong");
})
};
editContact = function (xContact) {
Repo.editUser(usr).success(function (data, status, header, config) {
getUsers();
clearFields();
$scope.isEditMode = false;
})
.error(function (data, status, header, config) {
alert("Error: Something went wrong");
});
//var localCopy = angular.copy(xContact);
//for (var i = 0; i < $scope.contacts.length; i++) {
// if (xContact.Id === $scope.contacts[i].Id) {
// $scope.contacts[i].Id = localCopy.Id;
// $scope.contacts[i].FirstName = localCopy.FirstName;
// $scope.contacts[i].LastName = localCopy.LastName;
// $scope.contacts[i].Email = localCopy.Email;
// clearFields();
// return;
// }
//}
//$scope.contacts.push(localCopy);
//clearFields();
}
$scope.editContact = editContact;
deleteContact = function (Id) {
if ($window.confirm("Are you sure you want to delete the user
'" + usr.FirstName + " " + usr.LastName + "'?")) {
Repo.deleteUser(usr.Id).success(function (data, status, header, config) {
getUsers();
clearFields();
$scope.isEditMode = false;
}).error(function (data, status, header, config) {
alert("Error: Something went wrong");
});
}
//if ($window.confirm("Are you sure you want to delete the contact?")) {
// for (var i = 0; i < $scope.contacts.length; i++) {
// if (Id === $scope.contacts[i].Id) {
// $scope.contacts.splice(i, 1);
// break;
// }
// }
//}
}
$scope.deleteContact = deleteContact;
haveContacts = function () {
return $scope.contacts.length > 0 ? true : false;
}
$scope.haveContacts = haveContacts;
clearFields();
getUsers();
}]);
生成并运行应用程序以查看更改。执行一些创建、读取、更新和删除操作,并检查您的后端数据库。
创建我们的自定义 Angular 指令并附带模板
第一步是在脚本部分的底部创建我们的自定义 Angular Directive“contactdir”;就在我们的控制器结束的地方。
myContact.directive("contactdir", function () {
return {
restrict: 'EA',
replace: true,
templateUrl: "@Url.Content("/templates/contactrow.html")"
};
});
指令构造函数将返回一个具有以下属性的对象:
restrict
:这允许我们将自定义指令限制为用作元素或属性。虽然,我们可以将指令用作 CSS 类名或注释;在我们的例子中,我们将其限制为元素和属性。replace
:将此值设置为“true
”将替换内联元素或属性;“false
”值将把模板内容附加到下面的属性或元素。template
:内联string
,带有用作指令模板的作用域变量。templateUrl
:指向包含模板内容的外部文件的路径。我们的“templateUrl
”指向位于“Templates”文件夹内的外部 HTML 文件。
转到并在项目根目录创建一个新文件夹“Templates”。将 tbody
元素内的表格模板行提取到一个新的 HTML 文件(ContactRow.html)中。
注意:确保从 tr
标签中删除 ng-Repeat
。让其他一切保持原样。
<tr>
<td>{{contact.Id}}</td>
<td>{{contact.FirstName + " " + contact.LastName}}</td>
<td><span ng-bind="contact.Email"></span></td>
<td>
<button type="button" class="btn btn-primary btn-xs" ng-click="doEdit(contact);">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span> Edit
</button>
<button type="button" class="btn btn-danger btn-xs" ng-click="deleteContact (contact);">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete
</button>
</td>
</tr>
更新“NgFirst.cshtml”中的 tbody
元素,使其使用我们的指令,如下所示:
<tr ng-repeat="contact in contacts" contactdir></tr>
注意:我们正在通过 ng-repeat
指令将 Angular 作用域变量“contact
”传递给我们的自定义“contactdir
”指令。
运行应用程序,您会发现 UI 没有变化,而是通过指令对底层联系人列表进行了更改。
存储在我们 MS SQL Server 数据库中的记录。
最后,我们使用 ASP.NET MVC 和 Entity Framework 的第一个 Angular js 应用程序项目,包含 Controller(NgController
)、Model(Model.edmx)、Repository(UserReposiroty.cs)和 View(NgFirst.cshtml),看起来如下:
关注点
作为我们第一个 Angular js 应用程序与 ASP.NET MVC 和 Entity Framework 的一部分,我们使用了以下 Angular 特定的指令、服务或方法:
- ng-app
- ng-controller
- ng-directive
- ng-model
- ng-bind 或 {{ expression }}
- ng-click
- ng-hide
- ng-show
- ng-repeat
- $scope
- $http
- $window
- angular.module
- angular.copy
希望通过本文您学到了一些新东西,并能够使用 AngularJs 执行一些基本操作。欢迎评分、评论和提出建议。