翻译:ASP.NET MVC5使用WebAPI 2 和 Ang
背景解释
原文来自于https://www.codeproject.com/Tips/1074608/CRUD-in-ASP-NET-MVC-using-WebAPI-with-AngularJS
代码DEMO:https://www.codeproject.com/KB/scripting/1074608/AngularJS_Demo.zip
第一次翻译技术文章,感谢谷歌翻译~~
CRUD是指在做计算处理时的增加(Create)、查询(Retrieve)(重新得到数据)、更新(Update)和删除(Delete)几个单词的首字母简写。主要被用在描述软件系统中数据库或者持久层的基本操作功能。
这篇文章将帮助初学者在ASP.NET MVC 5中使用具有脚本语言的WebAPI 2 、AngularJS和MS SQL 2008R2数据库实现CRUD操作。
介绍
如您所知,AngularJS是单页应用程序开发中最流行的JavaScript框架之一。 您可以使用Angular进行插入,更新,删除和检索操作。 本文将演示如何使用Angular、MVC5和WebAPI2进行CRUD操作。 有经验的开发人员会发现这篇文章非常基本,是的,这篇文章是从初学者的角度写的,所以我尽量保持简洁易懂。
开始代码
让我们开始吧 !!!
如下图在MSSQL中创建“TblProductList”表。
在ASP.NET MVC 5中创建一个新项目,并根据需要命名并选择Empty项目模板。
在添加文件夹和核心引用,勾选MVC和Web API选项:
在这个项目中使用NuGet软件包管理器安装Entity Framework 6、Jquery和AngularJS。
您还可以从官方网站下载jquery.js和angular.js,并将其粘贴到项目的“Scripts”文件夹中。
右键单击“Model”文件夹,新建一个ADO.NET 实体数据模型 。 将其命名为“ProductDataContext.edmx”。
选择“从数据库生成”,并根据SQL服务器配置连接字符串。
生成模型后,您将获得TblProductList的实体。
在根目录下创建新文件夹 Interface ,然后再新增一个类 IProductRepository.cs ,代码如下:
interface IProductRepository
{
IEnumerable<TblProductList> GetAll();
TblProductList Get(int id);
TblProductList Add(TblProductList item);
bool Update(TblProductList item);
bool Delete(int id);
}
再次在根目录下新建文件夹 Repositories ,新建类ProductRepository.cs ,以此来实现使用 Entity Framework 进行数据库的创建,读取,更新,删除的操作方法。
public class ProductRepository : IProductRepository
{
ProductDBEntities ProductDB = new ProductDBEntities();
public IEnumerable<TblProductList> GetAll()
{
// TO DO : Code to get the list of all the records in database
return ProductDB.TblProductLists;
}
public TblProductList Get(int id)
{
// TO DO : Code to find a record in database
return ProductDB.TblProductLists.Find(id);
}
public TblProductList Add(TblProductList item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
// TO DO : Code to save record into database
ProductDB.TblProductLists.Add(item);
ProductDB.SaveChanges();
return item;
}
public bool Update(TblProductList item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
// TO DO : Code to update record into database
var products = ProductDB.TblProductLists.Single(a => a.Id == item.Id);
products.Name = item.Name;
products.Category = item.Category;
products.Price = item.Price;
ProductDB.SaveChanges();
return true;
}
public bool Delete(int id)
{
// TO DO : Code to remove the records from database
TblProductList products = ProductDB.TblProductLists.Find(id);
ProductDB.TblProductLists.Remove(products);
ProductDB.SaveChanges();
return true;
}
}
右键单击 Controllers 文件夹并添加新的Web API 2 控制器-空,取名为'ProductController.cs':
public class ProductController : ApiController
{
static readonly IProductRepository repository = new ProductRepository();
public IEnumerable GetAllProducts()
{
return repository.GetAll();
}
public TblProductList PostProduct(TblProductList item)
{
return repository.Add(item);
}
public IEnumerable PutProduct(int id, TblProductList product)
{
product.Id = id;
if (repository.Update(product))
{
return repository.GetAll();
}
else
{
return null;
}
}
public bool DeleteProduct(int id)
{
if (repository.Delete(id))
{
return true;
}
else
{
return false;
}
}
}
右键单击Controllers文件夹并添加新的控制器,取名为'HomeController.cs':
public class HomeController : Controller
{
public ActionResult Product()
{
return View();
}
}
右键单击ActionResult Product(),点击添加视图'Product.cshtml'。
@{
ViewBag.Title = "Products List";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@section scripts {
<link href="~/Content/CustomStyle.css" rel="stylesheet" />
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/AngularDemo.js"></script>
}
<div ng-app="demoModule" id="body">
<div ng-controller="demoCtrl">
<h2>AngularJS CRUD Operations with MVC5 WebAPI</h2>
<h3>List of Products</h3>
<table ng-cloak>
<thead>
<tr>
<th style="display: none;">ID</th>
<th>Name</th>
<th>Category</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="items in productsData">
<td hidden="hidden">{{items.Id}}</td>
<td>{{items.Name}}</td>
<td>{{items.Category}}</td>
<td>{{items.Price | currency:'₹':2}}</td>
<td>
<button ng-model="$scope.Product"
ng-click="edit(productsData[$index])">Edit</button>
<button ng-click="delete($index)">Delete</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="6">
<hr />
</td>
</tr>
<tr>
<td>Total :</td>
<td></td>
<td><label ng-bind="total() |
currency:'₹':2"></label></td>
<td></td>
</tr>
</tfoot>
</table>
<br />
<div style="border-top: solid 2px #282828; width: 430px; height: 10px"> </div>
<div ng-show="Product.Id != '' ">
<div>
<h2>Update Product</h2>
</div>
<div hidden="hidden">
<label for="id">Id</label>
<input type="text" data-ng-model="Product.Id" />
</div>
<div>
<label for="name">Name</label>
<input type="text" data-ng-model="Product.Name" />
</div>
<div>
<label for="category">Category</label>
<input type="text" data-ng-model="Product.Category" />
</div>
<div>
<label for="price">Price</label>
<input type="text" data-ng-model="Product.Price" />
</div>
<br />
<div>
<button data-ng-click="update()">Update</button>
<button data-ng-click="cancel()">Cancel</button>
</div>
</div>
<div ng-hide="Product.Id != '' ">
<div>
<h2>Add New Product</h2>
</div>
<div>
<label for="name">Name</label>
<input type="text" data-ng-model="Product.Name" />
</div>
<div>
<label for="category">Category</label>
<input type="text" data-ng-model="Product.Category" />
</div>
<div>
<label for="price">Price</label>
<input type="text" data-ng-model="Product.Price" />
</div>
<br />
<div>
<button data-ng-click="save()">Save</button>
<button data-ng-click="clear()">Clear</button>
</div>
</div>
</div>
</div>
在Scripts 文件夹中创建一个新的JavaScript文件“Angular Demo.js”,以使用角度代码实现CRUD操作。
<span class="code-comment">//</span><span class="code-comment"> Defining angularjs module</span>
<span class="code-keyword">var</span> app = angular.module(<span class="code-string">'</span><span class="code-string">demoModule'</span>, []);
<span class="code-comment">//</span><span class="code-comment"> Defining angularjs Controller and injecting ProductsService</span>
app.controller(<span class="code-string">'</span><span class="code-string">demoCtrl'</span>, <span class="code-keyword">function</span> ($scope, $http, ProductsService) {
$scope.productsData = <span class="code-keyword">null</span>;
<span class="code-comment">//</span><span class="code-comment"> Fetching records from the factory created at the bottom of the script file</span>
ProductsService.GetAllRecords().then(<span class="code-keyword">function</span> (d) {
$scope.productsData = d.data; <span class="code-comment">//</span><span class="code-comment"> Success</span>
}, <span class="code-keyword">function</span> () {
alert(<span class="code-string">'</span><span class="code-string">Error Occured !!!'</span>); <span class="code-comment">//</span><span class="code-comment"> Failed</span>
});
<span class="code-comment">//</span><span class="code-comment"> Calculate Total of Price After Initialization</span>
$scope.total = <span class="code-keyword">function</span> () {
<span class="code-keyword">var</span> total = <span class="code-digit">0</span>;
angular.forEach($scope.productsData, <span class="code-keyword">function</span> (item) {
total += item.Price;
})
<span class="code-keyword">return</span> total;
}
$scope.Product = {
Id: <span class="code-string">'</span><span class="code-string">'</span>,
Name: <span class="code-string">'</span><span class="code-string">'</span>,
Price: <span class="code-string">'</span><span class="code-string">'</span>,
Category: <span class="code-string">'</span><span class="code-string">'</span>
};
<span class="code-comment">//</span><span class="code-comment"> Reset product details</span>
$scope.clear = <span class="code-keyword">function</span> () {
$scope.Product.Id = <span class="code-string">'</span><span class="code-string">'</span>;
$scope.Product.Name = <span class="code-string">'</span><span class="code-string">'</span>;
$scope.Product.Price = <span class="code-string">'</span><span class="code-string">'</span>;
$scope.Product.Category = <span class="code-string">'</span><span class="code-string">'</span>;
}
<span class="code-comment">//</span><span class="code-comment">Add New Item</span>
$scope.save = <span class="code-keyword">function</span> () {
<span class="code-keyword">if</span> ($scope.Product.Name != <span class="code-string">"</span><span class="code-string">"</span> &&
$scope.Product.Price != <span class="code-string">"</span><span class="code-string">"</span> && $scope.Product.Category != <span class="code-string">"</span><span class="code-string">"</span>) {
<span class="code-comment">//</span><span class="code-comment"> Call Http request using $.ajax</span>
<span class="code-comment">//</span><span class="code-comment">$.ajax({</span>
<span class="code-comment">//</span><span class="code-comment"> type: 'POST',</span>
<span class="code-comment">//</span><span class="code-comment"> contentType: 'application/json; charset=utf-8',</span>
<span class="code-comment">//</span><span class="code-comment"> data: JSON.stringify($scope.Product),</span>
<span class="code-comment">//</span><span class="code-comment"> url: 'api/Product/PostProduct',</span>
<span class="code-comment">//</span><span class="code-comment"> success: function (data, status) {</span>
<span class="code-comment">//</span><span class="code-comment"> $scope.$apply(function () {</span>
<span class="code-comment">//</span><span class="code-comment"> $scope.productsData.push(data);</span>
<span class="code-comment">//</span><span class="code-comment"> alert("Product Added Successfully !!!");</span>
<span class="code-comment">//</span><span class="code-comment"> $scope.clear();</span>
<span class="code-comment">//</span><span class="code-comment"> });</span>
<span class="code-comment">//</span><span class="code-comment"> },</span>
<span class="code-comment">//</span><span class="code-comment"> error: function (status) { }</span>
<span class="code-comment">//</span><span class="code-comment">});</span>
<span class="code-comment">//</span><span class="code-comment"> or you can call Http request using $http</span>
$http({
method: <span class="code-string">'</span><span class="code-string">POST'</span>,
url: <span class="code-string">'</span><span class="code-string">api/Product/PostProduct/'</span>,
data: $scope.Product
}).then(<span class="code-keyword">function</span> successCallback(response) {
<span class="code-comment">//</span><span class="code-comment"> this callback will be called asynchronously</span>
<span class="code-comment">//</span><span class="code-comment"> when the response is available</span>
$scope.productsData.push(response.data);
$scope.clear();
alert(<span class="code-string">"</span><span class="code-string">Product Added Successfully !!!"</span>);
}, <span class="code-keyword">function</span> errorCallback(response) {
<span class="code-comment">//</span><span class="code-comment"> called asynchronously if an error occurs</span>
<span class="code-comment">//</span><span class="code-comment"> or server returns response with an error status.</span>
alert(<span class="code-string">"</span><span class="code-string">Error : "</span> + response.data.ExceptionMessage);
});
}
<span class="code-keyword">else</span> {
alert(<span class="code-string">'</span><span class="code-string">Please Enter All the Values !!'</span>);
}
};
<span class="code-comment">//</span><span class="code-comment"> Edit product details</span>
$scope.edit = <span class="code-keyword">function</span> (data) {
$scope.Product = { Id: data.Id, Name: data.Name, Price: data.Price, Category: data.Category };
}
<span class="code-comment">//</span><span class="code-comment"> Cancel product details</span>
$scope.cancel = <span class="code-keyword">function</span> () {
$scope.clear();
}
<span class="code-comment">//</span><span class="code-comment"> Update product details</span>
$scope.update = <span class="code-keyword">function</span> () {
<span class="code-keyword">if</span> ($scope.Product.Name != <span class="code-string">"</span><span class="code-string">"</span> &&
$scope.Product.Price != <span class="code-string">"</span><span class="code-string">"</span> && $scope.Product.Category != <span class="code-string">"</span><span class="code-string">"</span>) {
$http({
method: <span class="code-string">'</span><span class="code-string">PUT'</span>,
url: <span class="code-string">'</span><span class="code-string">api/Product/PutProduct/'</span> + $scope.Product.Id,
data: $scope.Product
}).then(<span class="code-keyword">function</span> successCallback(response) {
$scope.productsData = response.data;
$scope.clear();
alert(<span class="code-string">"</span><span class="code-string">Product Updated Successfully !!!"</span>);
}, <span class="code-keyword">function</span> errorCallback(response) {
alert(<span class="code-string">"</span><span class="code-string">Error : "</span> + response.data.ExceptionMessage);
});
}
<span class="code-keyword">else</span> {
alert(<span class="code-string">'</span><span class="code-string">Please Enter All the Values !!'</span>);
}
};
<span class="code-comment">//</span><span class="code-comment"> Delete product details</span>
$scope.<span class="code-keyword">delete</span> = <span class="code-keyword">function</span> (index) {
$http({
method: <span class="code-string">'</span><span class="code-string">DELETE'</span>,
url: <span class="code-string">'</span><span class="code-string">api/Product/DeleteProduct/'</span> + $scope.productsData[index].Id,
}).then(<span class="code-keyword">function</span> successCallback(response) {
$scope.productsData.splice(index, <span class="code-digit">1</span>);
alert(<span class="code-string">"</span><span class="code-string">Product Deleted Successfully !!!"</span>);
}, <span class="code-keyword">function</span> errorCallback(response) {
alert(<span class="code-string">"</span><span class="code-string">Error : "</span> + response.data.ExceptionMessage);
});
};
});
<span class="code-comment">//</span><span class="code-comment"> Here I have created a factory which is a popular way to create and configure services.</span>
<span class="code-comment">//</span><span class="code-comment"> You may also create the factories in another script file which is best practice.</span>
app.factory(<span class="code-string">'</span><span class="code-string">ProductsService'</span>, <span class="code-keyword">function</span> ($http) {
<span class="code-keyword">var</span> fac = {};
fac.GetAllRecords = <span class="code-keyword">function</span> () {
<span class="code-keyword">return</span> $http.get(<span class="code-string">'</span><span class="code-string">api/Product/GetAllProducts'</span>);
}
<span class="code-keyword">return</span> fac;
});
注意
您可以使用jQuery中的$.ajax
或来自angular.js的$http
来进行HTTP请求。
但是最好就是使用angular.js的$http
,因为使用$.ajax
会迫使我们使用$scope.apply
,如果您使用$ http不需要。
您也可以使用 $resource ,这被认为是在RESTful Web API中进行CRUD操作的最佳做法。 本教程适用于初学者,所以我试图通过使用$http
来保持简单。
基于架构的关系,而不是控制器,您可以在我们的自定义工厂中调用$http
请求POST,PUT,DELETE,就像我已经为$http.get()
所做的那样,以便我们的控制器看起来很干净,并展现出适当的关注点分离。
译者注:(关注点分离(Separation of concerns,SOC)是对只与“特定概念、目标”(关注点)相关联的软件组成部分进行“标识、封装和操纵”的能力,即标识、封装和操纵关注点的能力。是处理复杂性的一个原则。由于关注点混杂在一起会导致复杂性大大增加,所以能够把不同的关注点分离开来,分别处理就是处理复杂性的一个原则,一种方法。)
现在,添加一个布局视图: '_Layout.cshtml'。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>@ViewBag.Title</title>
<meta name="viewport" content="width=device-width" />
</head>
<body>
<div id="body">
@RenderSection("featured", required: false)
<section class="content-wrapper main-content clear-fix">
@RenderBody()
</section>
</div>
@RenderSection("scripts", required: false)
</body>
</html>
增加样式表'CustomStyle.css'以改善页面的外观和美感。
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
display: none !important;
}
body {
margin: 20px;
font-family: "Arial", "Helventica", sans-serif;
}
label {
width: 80px;
display: inline-block;
}
button {
display: inline-block;
outline: none;
cursor: pointer;
text-align: center;
text-decoration: none;
padding: .4em 1.1em .4em;
color: #fef4e9;
border: solid 1px #006fb9;
background: #1276bb;
}
button:hover {
text-decoration: none;
background: #282828;
border: solid 1px #000;
}
table {
padding-top: 1em;
}
thead, tfoot {
font-weight: 600;
}
th, td {
padding: .1em .5em;
text-align: left;
}
td li, td ul {
margin: 0;
padding: 0;
}
td li {
display: inline;
}
td li::after {
content: ',';
}
td li:last-child::after {
content: '';
}
注意
在这里,我已经根据 AngularJS文档 定义了在我们的“Product.cshtml”中使用的ng-cloak指令的样式。<br class="Apple-interchange-newline"><div id="inner-editor"></div>
ngCloak指令用于防止在加载应用程序时浏览器以原始(未编译)形式简要显示Angular HTML模板。 使用此指令可避免HTML模板显示引起的不希望的闪烁效应。