通过Knockout.js + ASP.NET Web API构建一个简单的CRUD应用

简介:

较之面向最终消费者的网站,企业级Web应用对用户体验的要求要低一些。不过客户对“用户体验”的要求是“与日俱增”的,很多被“惯坏了”的用户已经不能忍受Postback带来的页面刷新,所以Ajax在企业级Web应用中得到了广泛的应用。企业级Web应用的一个特点是以“数据处理”为主,所以“面向绑定”的Knockout.js 是一个不错的选择。ASP.NET Web API,作为.NET平台最好的REST服务开发平台(主要与WCF相比),则可以以服务的形式提供对数据的后台处理。

一、一个简单的基于CRUD的Web应用

在《通过ASP.NET Web API + JQuery创建一个简单的Web应用》中,我采用jQuery + ASP.NET Web API构建了一个单纯的对单一数据进行CRUD操作的应用,对于数据在界面上的呈现,我是通过jQuery 动态生成HTML的方式实现的。现在我们通过Knockout.js来进行数据绑定,你会发现我们代码会变得很优雅。

这个简单的Demo应用用于模拟“联系人管理”。当页面加载的时候,所有的联系人列表被列出来。在同一个页面中,我们可以添加一个新的联系人,也可以修改和删除现有联系人信息。整个应用唯一的页面在浏览器中的呈现效果如下图所示。

image

二、通过ASP.NET Web API提供服务

先来看看ApiController的定义。如下面的代码片断所示,我们定义了一个名为ContactsController的ApiController用于完成针对联系人的CRUD操作,我们采用HTTP Method(Get、Post、Put和Delete)对Action方法进行命名,因为在进行Action匹配的时候会默认以Http Method作为前缀进行匹配。

   1: public class ContactsController : ApiController
   2: {
   3:     private static List<Contact> contacts = new List<Contact>
   4:     {
   5:         new Contact{ Id = "001", FirstName = "San", LastName="Zhang", PhoneNo="123", EmailAddress="zhangsan@gmail.com"},
   6:         new Contact{ Id = "002", FirstName = "Si", LastName="Li", PhoneNo="456", EmailAddress="lisi@gmail.com"}
   7:     };
   8:  
   9:     public IEnumerable<Contact> Get()
  10:     {
  11:         return contacts;
  12:     }
  13:  
  14:     public Contact Get(string id)
  15:     {
  16:         return contacts.FirstOrDefault(c => c.Id == id);
  17:     }
  18:  
  19:     public void Put(Contact contact)
  20:     {
  21:         contact.Id = Guid.NewGuid().ToString();
  22:         contacts.Add(contact);
  23:     }
  24:  
  25:     public void Post(Contact contact)
  26:     {
  27:         Delete(contact.Id);
  28:         contacts.Add(contact);
  29:     }
  30:  
  31:     public void Delete(string id)
  32:     {
  33:         Contact contact = contacts.FirstOrDefault(c => c.Id == id);
  34:         contacts.Remove(contact);
  35:     }
  36: }
  37:  
  38: public class Contact
  39: {
  40:     public string Id { get; set; }
  41:     public string FirstName { get; set; }
  42:     public string LastName { get; set; }
  43:     public string PhoneNo { get; set; }
  44:     public string EmailAddress { get; set; }
  45: }

和ASP.NET MVC Web应用一样,我们同样采用URL路由机制来实现请求地址与目标Controller和Action的映射,而针对API默认注册的路有如下所示(这里调用的方法是MapHttpRoute而不是MapRoute)。

   1: public class RouteConfig
   2: {
   3:     public static void RegisterRoutes(RouteCollection routes)
   4:     {
   5:         routes.MapHttpRoute(
   6:             name: "DefaultApi",
   7:             routeTemplate: "api/{controller}/{id}",
   8:             defaults: new { id = RouteParameter.Optional }
   9:         );
  10:     }
  11: }

按照注册的路由规则和Action方法名称与HTTP方法的默认影射机制,我们可以直接在浏览器中分别访问地址“/api/contacts”和“/api/contacts/001”得到所有联系人列表和ID为“001”的联系人信息。得到的结果如下图所示。

image

三、通过jQuery进行Ajax调用,利用Knockout.js进行数据绑定

我们通过ASP.NET MVC来构建Web应用,默认的HomeController定义如下,默认的Index操作仅仅是将默认的View呈现出来而已。

   1: public class HomeController : Controller
   2: {
   3:     public ActionResult Index()
   4:     {
   5:         return View();
   6:     }
   7: }

下面是整个View的定义。我们采用jQuery进行Ajax调用ApiController进行联系人的获取、添加、修改和删除,数据和命令(添加、修改和删除)的绑定是通过Knockout.js来完成的。

   1: <!DOCTYPE html>
   2: <html lang="en">
   3:     <head>
   4:         <title>@ViewBag.Title - My ASP.NET MVC Application</title>
   5:         @Styles.Render("~/Content/css" )
   6:         <script type="text/javascript" src="../../Scripts/jquery-1.6.2.min.js"></script>
   1:  
   2:         <script type="text/javascript" src="../../Scripts/knockout-2.0.0.js">
   1: </script>       
   2:     </head>
   3:     <body>
   4:     <div id="contacts">
   5:          <table>
   6:             <tr>
   7:                 <th>First Name</th>
   8:                 <th>Last Name</th>
   9:                 <th>Phone No.</th>
  10:                 <th>Email Address</th>
  11:                 <th></th>
  12:             </tr>
  13:             <tbody>
  14:                 <!-- ko foreach: contacts -->
  15:                 <tr>
  16:                     <td data-bind="text: FirstName" />
  17:                     <td data-bind="text: LastName" />
  18:                     <td data-bind="text: PhoneNo" />
  19:                     <td><input type="text" class="textbox long" data-bind="value: EmailAddress" /></td>
  20:                     <td>
  21:                         <a href="#" data-bind="click: $root.updateContact">Update</a><a href="#" data-bind="click: $root.deleteContact">Delete</a>
  22:                     </td>
  23:                 </tr>
  24:                 <!-- /ko -->
  25:                 <tr data-bind="with: addedContact">
  26:                     <td><input type="text" class="textbox" data-bind="value: FirstName"</td>
  27:                     <td><input type="text" class="textbox" data-bind="value: LastName"</td>
  28:                     <td><input type="text" class="textbox" data-bind="value: PhoneNo"</td>
  29:                     <td><input type="text" class="textbox long" data-bind="value: EmailAddress"</td>
  30:                     <td><a href="#" data-bind="click: $root.addContact">Add</a></td>
  31:                 </tr>
  32:             </tbody>
  33:         </table>
  34:     </div>
  35:     <script type="text/javascript" >
  36:         function contactManagerModel() {
  37:             self = this;
  38:             self.contacts = ko.observableArray();
  39:             self.addedContact = ko.observable();
  40:  
  41:             self.loadContacts = function () {
  42:                 $.get("/api/contacts", null, function (data) {
  43:                     self.contacts(data);
  44:                     var emptyContact = { Id: "-1", FirstName: "", LastName: "", PhoneNo: "", EmailAddress: "" };
  45:                     self.addedContact(emptyContact);
  46:                     $("table tr:odd").addClass("oddRow");
  47:                 });
  48:             };
  49:  
  50:             self.addContact = function (data) {
  51:                 if (!self.validate(data)) {
  52:                     return;
  53:                 }
  54:                 $.ajax({
  55:                     url: "api/contacts/",
  56:                     data: self.addedContact(),
  57:                     type: "PUT",
  58:                     success: self.loadContacts
  59:                 });
  60:             };
  61:  
  62:             self.updateContact = function (data) {
  63:                 $.ajax({
  64:                     url: "api/contacts/" + data.Id,
  65:                     data: data,
  66:                     type: "POST",
  67:                     success: self.loadContacts
  68:                 });                        
  69:             };
  70:  
  71:             self.deleteContact = function (data) {
  72:                 $.ajax({
  73:                     url: "api/contacts/" + data.Id,
  74:                     type: "DELETE",
  75:                     success: self.loadContacts
  76:                 });
  77:             };
  78:  
  79:             self.validate = function (data) {
  80:                 if (data.FirstName && data.LastName && data.PhoneNo && data.EmailAddress) {
  81:                     return true;
  82:                 }
  83:                 alert("Please provide complete contact information!");
  84:                 return false;
  85:             }
  86:             self.loadContacts();
  87:         }
  88:         ko.applyBindings(new contactManagerModel());
  89:     
</script>
   7:     </body>
   8: </html>

作者:蒋金楠
微信公众账号:大内老A
微博: www.weibo.com/artech
如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
3天前
|
前端开发 搜索推荐 JavaScript
如何通过DIY.JS快速构建出一个DIY手机壳、T恤的应用?
DIY.JS 是一款基于原生 Canvas 的业务级图形库,专注于商品定制的图形交互功能,帮助开发者轻松实现个性化设计。适用于 T 恤、手机壳等多种商品场景。它自带丰富功能,无需从零构建,快速集成到项目中。通过创建舞台、添加模型、定义 DIY 区域和添加素材四个步骤即可完成基础用法。支持在线演示体验,文档详细,易上手。
|
14天前
|
前端开发 JavaScript NoSQL
使用 Node.js、Express 和 React 构建强大的 API
本文详细介绍如何使用 Node.js、Express 和 React 构建强大且动态的 API。从开发环境搭建到集成 React 前端,再到利用 APIPost 高效测试 API,适合各水平开发者。内容涵盖 Node.js 运行时、Express 框架与 React 库的基础知识及协同工作方式,还涉及数据库连接和前后端数据交互。通过实际代码示例,助你快速上手并优化应用性能。
|
5月前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js:从零开始构建后端服务
【10月更文挑战第42天】在数字时代的浪潮中,掌握一门后端技术对于开发者来说至关重要。Node.js,作为一种基于Chrome V8引擎的JavaScript运行环境,允许开发者使用JavaScript编写服务器端代码,极大地拓宽了前端开发者的技能边界。本文将从Node.js的基础概念讲起,逐步引导读者理解其事件驱动、非阻塞I/O模型的核心原理,并指导如何在实战中应用这些知识构建高效、可扩展的后端服务。通过深入浅出的方式,我们将一起探索Node.js的魅力和潜力,解锁更多可能。
|
1月前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
1月前
|
JavaScript 前端开发 Java
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
柯里化是一种强大的函数式编程技术,它通过将函数分解为单参数形式,实现了灵活性与可复用性的统一。无论是参数复用、延迟执行,还是函数组合,柯里化都为现代编程提供了极大的便利。 从 Redux 的选择器优化到复杂的数据流处理,再到深度嵌套的函数优化,柯里化在实际开发中展现出了非凡的价值。如果你希望编写更简洁、更优雅的代码,柯里化无疑是一个值得深入学习和实践的工具。从简单的实现到复杂的应用,希望这篇博客能为你揭开柯里化的奥秘,助力你的开发之旅! 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一
|
3月前
|
开发框架 数据可视化 .NET
.NET 中管理 Web API 文档的两种方式
.NET 中管理 Web API 文档的两种方式
73 14
|
3月前
|
中间件 API
Next.js 实战 (八):使用 Lodash 打包构建产生的“坑”?
这篇文章介绍了作者在使用Nextjs15进行项目开发时遇到的部署问题。在部署过程中,作者遇到了打包构建时的一系列报错,报错内容涉及动态代码评估在Edge运行时不被允许等问题。经过一天的尝试和调整,作者最终删除了lodash-es库,并将radash的部分源码复制到本地,解决了打包报错的问题。文章最后提供了项目的线上预览地址,并欢迎读者留言讨论更好的解决方案。
88 10
|
5月前
|
JavaScript
使用Node.js创建一个简单的Web服务器
使用Node.js创建一个简单的Web服务器
|
5月前
|
JSON 缓存 JavaScript
深入浅出:使用Node.js构建RESTful API
在这个数字时代,API已成为软件开发的基石之一。本文旨在引导初学者通过Node.js和Express框架快速搭建一个功能完备的RESTful API。我们将从零开始,逐步深入,不仅涉及代码编写,还包括设计原则、最佳实践及调试技巧。无论你是初探后端开发,还是希望扩展你的技术栈,这篇文章都将是你的理想指南。
|
5月前
|
开发框架 .NET 程序员
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结
Autofac 是一个轻量级的依赖注入框架,专门为 .NET 应用程序量身定做,它就像是你代码中的 "魔法师",用它来管理对象的生命周期,让你的代码更加模块化、易于测试和维护
157 4
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结

热门文章

最新文章

下一篇
oss创建bucket