背景解释
原文来自于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 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 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 {
}
AngularJS CRUD Operations with MVC5 WebAPI
List of Products
Name
Category
Price
Actions
{{items.Id}}
{{items.Name}}
{{items.Category}}
{{items.Price | currency:'₹':2}}
Total :
Update Product
Add New Product
在Scripts 文件夹中创建一个新的JavaScript文件“Angular Demo.js”,以使用角度代码实现CRUD操作。
// Defining angularjs module
var app = angular.module('demoModule', []);
// Defining angularjs Controller and injecting ProductsService
app.controller('demoCtrl', function ($scope, $http, ProductsService) {
$scope.productsData = null;
// Fetching records from the factory created at the bottom of the script file
ProductsService.GetAllRecords().then(function (d) {
$scope.productsData = d.data; // Success
}, function () {
alert('Error Occured !!!'); // Failed
});
// Calculate Total of Price After Initialization
$scope.total = function () {
var total = 0;
angular.forEach($scope.productsData, function (item) {
total += item.Price;
})
return total;
}
$scope.Product = {
Id: '',
Name: '',
Price: '',
Category: ''
};
// Reset product details
$scope.clear = function () {
$scope.Product.Id = '';
$scope.Product.Name = '';
$scope.Product.Price = '';
$scope.Product.Category = '';
}
//Add New Item
$scope.save = function () {
if ($scope.Product.Name != "" &&
$scope.Product.Price != "" && $scope.Product.Category != "") {
// Call Http request using $.ajax
//$.ajax({
// type: 'POST',
// contentType: 'application/json; charset=utf-8',
// data: JSON.stringify($scope.Product),
// url: 'api/Product/PostProduct',
// success: function (data, status) {
// $scope.$apply(function () {
// $scope.productsData.push(data);
// alert("Product Added Successfully !!!");
// $scope.clear();
// });
// },
// error: function (status) { }
//});
// or you can call Http request using $http
$http({
method: 'POST',
url: 'api/Product/PostProduct/',
data: $scope.Product
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
$scope.productsData.push(response.data);
$scope.clear();
alert("Product Added Successfully !!!");
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
alert("Error : " + response.data.ExceptionMessage);
});
}
else {
alert('Please Enter All the Values !!');
}
};
// Edit product details
$scope.edit = function (data) {
$scope.Product = { Id: data.Id, Name: data.Name, Price: data.Price, Category: data.Category };
}
// Cancel product details
$scope.cancel = function () {
$scope.clear();
}
// Update product details
$scope.update = function () {
if ($scope.Product.Name != "" &&
$scope.Product.Price != "" && $scope.Product.Category != "") {
$http({
method: 'PUT',
url: 'api/Product/PutProduct/' + $scope.Product.Id,
data: $scope.Product
}).then(function successCallback(response) {
$scope.productsData = response.data;
$scope.clear();
alert("Product Updated Successfully !!!");
}, function errorCallback(response) {
alert("Error : " + response.data.ExceptionMessage);
});
}
else {
alert('Please Enter All the Values !!');
}
};
// Delete product details
$scope.delete = function (index) {
$http({
method: 'DELETE',
url: 'api/Product/DeleteProduct/' + $scope.productsData[index].Id,
}).then(function successCallback(response) {
$scope.productsData.splice(index, 1);
alert("Product Deleted Successfully !!!");
}, function errorCallback(response) {
alert("Error : " + response.data.ExceptionMessage);
});
};
});
// Here I have created a factory which is a popular way to create and configure services.
// You may also create the factories in another script file which is best practice.
app.factory('ProductsService', function ($http) {
var fac = {};
fac.GetAllRecords = function () {
return $http.get('api/Product/GetAllProducts');
}
return 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'。
@ViewBag.Title
@RenderSection("featured", required: false)
@RenderBody()
@RenderSection("scripts", required: false)
增加样式表'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指令的样式。
ngCloak指令用于防止在加载应用程序时浏览器以原始(未编译)形式简要显示Angular HTML模板。 使用此指令可避免HTML模板显示引起的不希望的闪烁效应。