找回密码
 立即注册
首页 业界区 业界 Web API 强势入门指南

Web API 强势入门指南

每捎京 2025-5-29 16:33:36
Web API是一个比较宽泛的概念。这里我们提到Web API特指ASP.NET Web API。
这篇文章中我们主要介绍Web API的主要功能以及与其他同类型框架的对比,最后通过一些相对复杂的实例展示如何通过Web API构建http服务,同时也展示了Visual Studio构建.net项目的各种强大。
目录


  • 什么是 Web API
  • 为什么要用 Web API
  • 功能简介
  • Web API vs MVC
  • Web API vs WCF
  • Web API 实战 (Web API + MongoDB + knockoutjs)

    • 涉及技术
    • 服务URI Pattern
    • 准备工作
    • 代码实现

什么是 Web API

官方定义如下,强调两个关键点,即可以对接各种客户端(浏览器,移动设备),构建http服务的框架。
ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mobile devices. ASP.NET Web API is an ideal platform for building RESTful applications on the .NET Framework.
Web API在ASP.NET完整框架中地位如下图,与SignalR一起同为构建Service的框架。Web API负责构建http常规服务,而SingalR主要负责的是构建实时服务,例如股票,聊天室,在线游戏等实时性要求比较高的服务。
1.png

 
为什么要用 Web API

Web API最重要的是可以构建面向各种客户端的服务。另外与WCF REST Service不同在于,Web API利用Http协议的各个方面来表达服务(例如 URI/request response header/caching/versioning/content format),因此就省掉很多配置。
2.png

 
当你遇到以下这些情况的时候,就可以考虑使用Web API了。

  • 需要Web Service但是不需要SOAP
  • 需要在已有的WCF服务基础上建立non-soap-based http服务
  • 只想发布一些简单的Http服务,不想使用相对复杂的WCF配置
  • 发布的服务可能会被带宽受限的设备访问
  • 希望使用开源框架,关键时候可以自己调试或者自定义一下框架
功能简介

Web API的主要功能
1. 支持基于Http verb (GET, POST, PUT, DELETE)的CRUD (create, retrieve, update, delete)操作
    通过不同的http动作表达不同的含义,这样就不需要暴露多个API来支持这些基本操作。
2. 请求的回复通过Http Status Code表达不同含义,并且客户端可以通过Accept header来与服务器协商格式,例如你希望服务器返回JSON格式还是XML格式。
3. 请求的回复格式支持 JSON,XML,并且可以扩展添加其他格式。
4. 原生支持OData。
5. 支持Self-host或者IIS host。
6. 支持大多数MVC功能,例如Routing/Controller/Action Result/Filter/Model Builder/IOC Container/Dependency Injection。
Web API vs MVC

你可能会觉得Web API 与MVC很类似,他们有哪些不同之处呢?先上图,这就是他们最大的不同之处。
3.png

详细点说他们的区别,

  • MVC主要用来构建网站,既关心数据也关心页面展示,而Web API只关注数据
  • Web API支持格式协商,客户端可以通过Accept header通知服务器期望的格式
  • Web API支持Self Host,MVC目前不支持
  • Web API通过不同的http verb表达不同的动作(CRUD),MVC则通过Action名字表达动作
  • Web API内建于ASP.NET System.Web.Http命名空间下,MVC位于System.Web.Mvc命名空间下,因此model binding/filter/routing等功能有所不同
  • 最后,Web API非常适合构建移动客户端服务
Web API vs WCF

发布服务在Web API和WCF之间该如何取舍呢?这里提供些简单地判断规则,

  • 如果服务需要支持One Way Messaging/Message Queue/Duplex Communication,选择WCF
  • 如果服务需要在TCP/Named Pipes/UDP (wcf 4.5),选择WCF
  • 如果服务需要在http协议上,并且希望利用http协议的各种功能,选择Web API
  • 如果服务需要被各种客户端(特别是移动客户端)调用,选择Web API
Web API 实战 (Web API + MongoDB + knockoutjs)

ASP.NET网站上有很多简单的Web API实例,看看贴图和实例代码你就明白怎么用了。这里我们通过一个稍微复杂一点的实例来展示下Web API的功能。
涉及技术

在我们的实例里面用到了:

  • Mongo DB数据库保存数据 (NoSQL, Document Store,跨平台,跨语言)
  • Web API提供数据服务
  • MVC作数据展示
  • Knockoutjs动态绑定客户端数据,这里有一个简单的介绍
服务URI Pattern

ActionHttp verbURI
Get contact listGET/api/contacts
Get filtered contactsGET/api/contacts?$top=2
Get contact by IDGET/api/contacts/id
Create new contactPOST/api/contacts
Update a contactPUT/api/contacts/id
Delete a contactDELETE/api/contacts/id
准备工作

1. 下载并安装Mongo DB,步骤看这里。
2. Mongo DB C# driver下载可以在nuget搜索mongocsharpdriver。
3. 如果想本地察看数据库中内容,下载MongoVUE。
4. Knockoutjs下载可以在nuget搜索knockoutjs。
代码实现

1. 创建项目
创建MVC4 Web Application
4.png

在Project Template中选择Web API
5.png

然后项目就创建成了,Controllers里面有一个ValuesController,是自动生成的一个最简单的Web API Controller。
正如我们前面所说,里面引用的是System.Web.Http命名空间。
6.png

2. 创建model
在model里面添加Contact类
7.png

代码如下,其中BsonId需要mongocsharpdriver。
  1. public class Contact
  2.     {
  3.         [BsonId]
  4.         public string Id { get; set; }
  5.         public string Name { get; set; }
  6.         public string Phone { get; set; }
  7.         public string Email { get; set; }
  8.         public DateTime LastModified { get; set; }
  9.     }
复制代码
我们需要添加mongosharpdriver。
8.png

9.png

另外我们需要在Model中添加Repository,Controller通过该类来访问Mongo DB。
  1. public interface IContactRepository {
  2.         IEnumerable GetAllContacts();
  3.         Contact GetContact(string id);
  4.         Contact AddContact(Contact item);
  5.         bool RemoveContact(string id);
  6.         bool UpdateContact(string id, Contact item);   
  7.     }
复制代码
ContactRepository的完整实现如下,
  1. public class ContactRepository : IContactRepository
  2.     {
  3.         MongoServer _server = null;
  4.         MongoDatabase _database = null;
  5.         MongoCollection _contacts = null;
  6.         public ContactRepository(string connection)
  7.         {
  8.             if (string.IsNullOrWhiteSpace(connection))
  9.             {
  10.                 connection = "mongodb://localhost:27017";
  11.             }
  12.             _server = new MongoClient(connection).GetServer();
  13.             _database = _server.GetDatabase("Contacts");
  14.             _contacts = _database.GetCollection("contacts");
  15.             // Reset database and add some default entries
  16.             _contacts.RemoveAll();
  17.             for (int index = 1; index < 5; index++)
  18.             {
  19.                 Contact contact1 = new Contact
  20.                 {
  21.                     Email = string.Format("test{0}@example.com", index),
  22.                     Name = string.Format("test{0}", index),
  23.                     Phone = string.Format("{0}{0}{0} {0}{0}{0} {0}{0}{0}{0}", index)
  24.                 };
  25.                 AddContact(contact1);
  26.             }
  27.         }
  28.         public IEnumerable GetAllContacts()
  29.         {
  30.             return _contacts.FindAll();
  31.         }
  32.         public Contact GetContact(string id)
  33.         {
  34.             IMongoQuery query = Query.EQ("_id", id);
  35.             return _contacts.Find(query).FirstOrDefault();
  36.         }
  37.         public Contact AddContact(Contact item)
  38.         {
  39.             item.Id = ObjectId.GenerateNewId().ToString();
  40.             item.LastModified = DateTime.UtcNow;
  41.             _contacts.Insert(item);
  42.             return item;
  43.         }
  44.         public bool RemoveContact(string id)
  45.         {
  46.             IMongoQuery query = Query.EQ("_id", id);
  47.             WriteConcernResult result = _contacts.Remove(query);
  48.             return result.DocumentsAffected == 1;
  49.         }
  50.         public bool UpdateContact(string id, Contact item)
  51.         {
  52.             IMongoQuery query = Query.EQ("_id", id);
  53.             item.LastModified = DateTime.UtcNow;
  54.             IMongoUpdate update = Update
  55.                 .Set("Email", item.Email)
  56.                 .Set("LastModified", DateTime.UtcNow)
  57.                 .Set("Name", item.Name)
  58.                 .Set("Phone", item.Phone);
  59.             WriteConcernResult result = _contacts.Update(query, update);
  60.             return result.UpdatedExisting;
  61.         }
  62.     }
复制代码
3. 添加Controller
右键Controllers目录选择添加Controller
10.png

选择Empty API controller,将Controller命名为ContactsController
11.png

添加如下代码,可以看到Controller中的API方法名就是以http verb命名的。
  1. public class ContactsController : ApiController
  2.     {
  3.         private static readonly IContactRepository _contacts = new ContactRepository(string.Empty);
  4.         public IQueryable Get()
  5.         {
  6.             return _contacts.GetAllContacts().AsQueryable();
  7.         }
  8.         public Contact Get(string id)
  9.         {
  10.             Contact contact = _contacts.GetContact(id);
  11.             if (contact == null)
  12.             {
  13.                 throw new HttpResponseException(HttpStatusCode.NotFound);
  14.             }
  15.             return contact;
  16.         }
  17.         public Contact Post(Contact value)
  18.         {
  19.             Contact contact = _contacts.AddContact(value);
  20.             return contact;
  21.         }
  22.         public void Put(string id, Contact value)
  23.         {
  24.             if (!_contacts.UpdateContact(id, value))
  25.             {
  26.                 throw new HttpResponseException(HttpStatusCode.NotFound);
  27.             }
  28.         }
  29.         public void Delete(string id)
  30.         {
  31.             if (!_contacts.RemoveContact(id))
  32.             {
  33.                 throw new HttpResponseException(HttpStatusCode.NotFound);
  34.             }
  35.         }
  36.     }
复制代码
4. 添加View
首先添加Knockoutjs库,
12.png

Knockoutjs通过MVVM模式来实现动态html绑定数据,如下图,其中View-Model是客户端的javascript object保存的model数据。
13.png

先打开HomeController,里面添加一个新的Action代码如下,因为我们要在MVC中对于ContactsController添加对应的View。
  1. public ActionResult Admin()
  2.         {
  3.             string apiUri = Url.HttpRouteUrl("DefaultApi", new { controller = "contacts", });
  4.             ViewBag.ApiUrl = new Uri(Request.Url, apiUri).AbsoluteUri.ToString();
  5.             return View();
  6.         }
复制代码
然后右键Admin方法,选择添加View
14.png

选择Create strongly-typed view,在model class中选择Contact类。
15.png

添加View的完整代码,注意view中我们通过js去访问WebAPI,以及通过动态绑定将数据呈现在网页上。
  1. @model WebAPIDemo.Models.Contact
  2. @{
  3.     ViewBag.Title = "Admin";
  4. }
  5. @section Scripts {
  6.   @Scripts.Render("~/bundles/jqueryval")
  7.    
  8.   
  9. }
  10. <h2>Admin</h2>
  11.    
  12.     <ul id="update-products" data-bind="foreach: products">
  13.         <li>
  14.             
  15.                 ID <span data-bind="text: $data.Id"></span>
  16.             
  17.             
  18.                 Name
  19.                 <input type="text" data-bind="value: $data.Name"/>
  20.             
  21.             
  22.                 Phone
  23.                 <input type="text" data-bind="value: $data.Phone"/>
  24.             
  25.             
  26.                 Email
  27.                 <input type="text" data-bind="value: $data.Email"/>
  28.             
  29.             
  30.                 Last Modified <span data-bind="text: $data.LastModified"></span>
  31.             
  32.             
  33.                 <input type="button" value="Update" data-bind="click: $root.update"/>
  34.                 <input type="button" value="Delete Item" data-bind="click: $root.remove"/>
  35.             
  36.         </li>
  37.     </ul>
  38.    
  39.    
  40.     <h2>Add New Product</h2>
  41.     <form id="addProduct" data-bind="submit: create">
  42.         @Html.ValidationSummary(true)
  43.         <fieldset>
  44.             <legend>Contact</legend>
  45.             @Html.EditorForModel()
  46.             <p>
  47.                 <input type="submit" value="Save" />
  48.             </p>
  49.         </fieldset>
  50.     </form>
  51.    
复制代码
接下来在_layout.cshtml中添加一个admin页面的链接如下
  1. <ul id="menu">
  2.     <li>@Html.ActionLink("Home", "Index", "Home", new { area = "" }, null)</li>
  3.     <li>@Html.ActionLink("API", "Index", "Help", new { area = "" }, null)</li>
  4.     <li>@Html.ActionLink("Admin", "Admin", "Home")</li>
  5. </ul>
复制代码
5. 测试与调试
大功告成,直接运行下我们的作品,我们的admin链接也显示在右上角,
16.png

Admin页面的样子,Contact list是动态加载进来的,可以通过这个页面做添加,修改,删除的操作。
17.png

通过IE network capture来查看请求内容,
重新加载页面,可以看到回复的格式为JSON,
18.png

JSON内容就是我们mock的一些数据。
19.png

接下来我们修改,删除,又添加了一条记录,可以看到使用了不同的http method。
20.png

通过前面安装的mongovue来查看下DB种的数据,先添加的user也在其中,令我感到欣慰。。。
21.png

其实还有两个有趣的实例,不过文章一写就长了,不好意思耽误大家时间,只好先放放,以后再写。
 

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册