翻译:ASP.NET MVC5使用WebAPI 2 和 AngularJS进行CRUD操作

背景解释

原文来自于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:'&#8377;':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:'&#8377;':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> &amp;&amp;
       $scope.Product.Price != <span class="code-string">"</span><span class="code-string">"</span> &amp;&amp; $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> &amp;&amp;
       $scope.Product.Price != <span class="code-string">"</span><span class="code-string">"</span> &amp;&amp; $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模板显示引起的不希望的闪烁效应。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容

  • 刚好在一个项目里面需要WebAPI 和VUE,于是我就将大抵的思路屡一下,做了一个TODO小例程出来。后端使用AS...
    凉风有兴阅读 2,956评论 3 17
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,566评论 18 139
  • 迪士尼差点炸了。 上周,有黑客宣称有《加勒比海盗5》完整片源,除非拿到巨额的比特币,否则将依次放出5分钟、20分钟...
    Sir电影阅读 1,212评论 3 21
  • 我去过多次越南。在外面出差也很多需要注意的地方,和大家分享一下。 1.不要想当然的认为所有人都是好人。 ...
    无非草木阅读 444评论 3 3
  • 虚拟机和Linux系统小白学习过程 1.虚拟机中安装linux系统 a)创建虚拟机的过程 第一步 第二步 第三步 ...
    简单生活101阅读 201评论 0 1