什么是 Web API

http://www.cnblogs.com/developersupport/p/aspnet-webapi.html

Web API 强势入门指南

Web API是一个比较宽泛的概念。这里我们提到Web API特指ASP.NET Web API。

这篇文章中我们主要介绍Web API的主要功能以及与其他同类型框架的对比,最后通过一些相对复杂的实例展示如何通过Web API构建http服务,同时也展示了Visual Studio构建.net项目的各种强大。

目录

什么是 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主要负责的是构建实时服务,例如股票,聊天室,在线游戏等实时性要求比较高的服务。

为什么要用 Web API

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

当你遇到以下这些情况的时候,就可以考虑使用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很类似,他们有哪些不同之处呢?先上图,这就是他们最大的不同之处。

详细点说他们的区别,

  • 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的功能。

涉及技术

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

服务URI Pattern

Action Http verb URI
Get contact list GET /api/contacts
Get filtered contacts GET /api/contacts?$top=2
Get contact by ID GET /api/contacts/id
Create new contact POST /api/contacts
Update a contact PUT /api/contacts/id
Delete a contact DELETE /api/contacts/id

准备工作

1. 下载并安装Mongo DB,步骤看这里

2. Mongo DB C# driver下载可以在nuget搜索mongocsharpdriver。

3. 如果想本地察看数据库中内容,下载MongoVUE

4. Knockoutjs下载可以在nuget搜索knockoutjs。

代码实现

1. 创建项目

创建MVC4 Web Application

在Project Template中选择Web API

然后项目就创建成了,Controllers里面有一个ValuesController,是自动生成的一个最简单的Web API Controller。

正如我们前面所说,里面引用的是System.Web.Http命名空间。

2. 创建model

在model里面添加Contact类

代码如下,其中BsonId需要mongocsharpdriver。


1

2

3

4

5

6

7

8

9

public class Contact

    {

        [BsonId]

        public string Id { get; set; }

        public string Name { get; set; }

        public string Phone { get; set; }

        public string Email { get; set; }

        public DateTime LastModified { get; set; }

    }

我们需要添加mongosharpdriver。

另外我们需要在Model中添加Repository,Controller通过该类来访问Mongo DB。


1

2

3

4

5

6

7

public interface IContactRepository {

        IEnumerable GetAllContacts();

        Contact GetContact(string id);

        Contact AddContact(Contact item);

        bool RemoveContact(string id);

        bool UpdateContact(string id, Contact item);  

    }

ContactRepository的完整实现如下,


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

public class ContactRepository : IContactRepository

    {

        MongoServer _server = null;

        MongoDatabase _database = null;

        MongoCollection _contacts = null;

        public ContactRepository(string connection)

        {

            if (string.IsNullOrWhiteSpace(connection))

            {

                connection = "mongodb://localhost:27017";

            }

            _server = new MongoClient(connection).GetServer();

            _database = _server.GetDatabase("Contacts");

            _contacts = _database.GetCollection("contacts");

            // Reset database and add some default entries

            _contacts.RemoveAll();

            for (int index = 1; index < 5; index++)

            {

                Contact contact1 = new Contact

                {

                    Email = string.Format("test{0}@example.com", index),

                    Name = string.Format("test{0}", index),

                    Phone = string.Format("{0}{0}{0} {0}{0}{0} {0}{0}{0}{0}", index)

                };

                AddContact(contact1);

            }

        }

        public IEnumerable GetAllContacts()

        {

            return _contacts.FindAll();

        }

        public Contact GetContact(string id)

        {

            IMongoQuery query = Query.EQ("_id", id);

            return _contacts.Find(query).FirstOrDefault();

        }

        public Contact AddContact(Contact item)

        {

            item.Id = ObjectId.GenerateNewId().ToString();

            item.LastModified = DateTime.UtcNow;

            _contacts.Insert(item);

            return item;

        }

        public bool RemoveContact(string id)

        {

            IMongoQuery query = Query.EQ("_id", id);

            WriteConcernResult result = _contacts.Remove(query);

            return result.DocumentsAffected == 1;

        }

        public bool UpdateContact(string id, Contact item)

        {

            IMongoQuery query = Query.EQ("_id", id);

            item.LastModified = DateTime.UtcNow;

            IMongoUpdate update = Update

                .Set("Email", item.Email)

                .Set("LastModified", DateTime.UtcNow)

                .Set("Name", item.Name)

                .Set("Phone", item.Phone);

            WriteConcernResult result = _contacts.Update(query, update);

            return result.UpdatedExisting;

        }

    }

3. 添加Controller

右键Controllers目录选择添加Controller

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

添加如下代码,可以看到Controller中的API方法名就是以http verb命名的。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

public class ContactsController : ApiController

    {

        private static readonly IContactRepository _contacts = new ContactRepository(string.Empty);

        public IQueryable Get()

        {

            return _contacts.GetAllContacts().AsQueryable();

        }

        public Contact Get(string id)

        {

            Contact contact = _contacts.GetContact(id);

            if (contact == null)

            {

                throw new HttpResponseException(HttpStatusCode.NotFound);

            }

            return contact;

        }

        public Contact Post(Contact value)

        {

            Contact contact = _contacts.AddContact(value);

            return contact;

        }

        public void Put(string id, Contact value)

        {

            if (!_contacts.UpdateContact(id, value))

            {

                throw new HttpResponseException(HttpStatusCode.NotFound);

            }

        }

        public void Delete(string id)

        {

            if (!_contacts.RemoveContact(id))

            {

                throw new HttpResponseException(HttpStatusCode.NotFound);

            }

        }

    }

4. 添加View

首先添加Knockoutjs库,

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

先打开HomeController,里面添加一个新的Action代码如下,因为我们要在MVC中对于ContactsController添加对应的View。


1

2

3

4

5

6

7

public ActionResult Admin()

        {

            string apiUri = Url.HttpRouteUrl("DefaultApi", new { controller = "contacts", });

            ViewBag.ApiUrl = new Uri(Request.Url, apiUri).AbsoluteUri.ToString();

            return View();

        }

然后右键Admin方法,选择添加View

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

添加View的完整代码,注意view中我们通过js去访问WebAPI,以及通过动态绑定将数据呈现在网页上。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

@model WebAPIDemo.Models.Contact

@{

    ViewBag.Title = "Admin";

}

@section Scripts {

  @Scripts.Render("~/bundles/jqueryval")

  <script type="text/javascript" src="@Url.Content("~/Scripts/knockout-2.3.0.js")"></script>

  <script type="text/javascript">

      function ProductsViewModel() {

          var self = this;

          self.products = ko.observableArray();

          var baseUri = ‘@ViewBag.ApiUrl‘;

          self.create = function (formElement) {

              // If valid, post the serialized form data to the web api

              $(formElement).validate();

              if ($(formElement).valid()) {

                  $.post(baseUri, $(formElement).serialize(), null, "json")

                      .done(function (o) { self.products.push(o); });

              }

          }

          self.update = function (product) {

              $.ajax({ type: "PUT", url: baseUri + ‘/‘ + product.Id, data: product });

          }

          self.remove = function (product) {

              // First remove from the server, then from the UI

              $.ajax({ type: "DELETE", url: baseUri + ‘/‘ + product.Id })

                  .done(function () { self.products.remove(product); });

          }

          $.getJSON(baseUri, self.products);

      }

      $(document).ready(function () {

          ko.applyBindings(new ProductsViewModel());

      })

  </script>

}

<h2>Admin</h2>

<div class="content">

    <div class="float-left">

    <ul id="update-products" data-bind="foreach: products">

        <li>

            <div>

                <div class="item">ID</div> <span data-bind="text: $data.Id"></span>

            </div>

            <div>

                <div class="item">Name</div>

                <input type="text" data-bind="value: $data.Name"/>

            </div>

            <div>

                <div class="item">Phone</div>

                <input type="text" data-bind="value: $data.Phone"/>

            </div>

            <div>

                <div class="item">Email</div>

                <input type="text" data-bind="value: $data.Email"/>

            </div>

            <div>

                <div class="item">Last Modified</div> <span data-bind="text: $data.LastModified"></span>

            </div>

            <div>

                <input type="button" value="Update" data-bind="click: $root.update"/>

                <input type="button" value="Delete Item" data-bind="click: $root.remove"/>

            </div>

        </li>

    </ul>

    </div>

    <div class="float-right">

    <h2>Add New Product</h2>

    <form id="addProduct" data-bind="submit: create">

        @Html.ValidationSummary(true)

        <fieldset>

            <legend>Contact</legend>

            @Html.EditorForModel()

            <p>

                <input type="submit" value="Save" />

            </p>

        </fieldset>

    </form>

    </div>

</div>

接下来在_layout.cshtml中添加一个admin页面的链接如下


1

2

3

4

5

6

<ul id="menu">

    <li>@Html.ActionLink("Home", "Index", "Home", new { area = "" }, null)</li>

    <li>@Html.ActionLink("API", "Index", "Help", new { area = "" }, null)</li>

    <li>@Html.ActionLink("Admin", "Admin", "Home")</li>

</ul>

5. 测试与调试

大功告成,直接运行下我们的作品,我们的admin链接也显示在右上角,

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

通过IE network capture来查看请求内容,

重新加载页面,可以看到回复的格式为JSON,

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

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

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

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

分类: 技术分享 - ASP.NET

标签: ASP.NET, web api, mvc, knockoutjs, mongodb

好文要顶
关注我
收藏该文

微软互联网开发支持
关注 - 0
粉丝 - 881

荣誉:推荐博客

+加关注

174

2

(请您对文章做出评价)

« 上一篇:IE Javascript 进阶调试
» 下一篇:Web API 入门指南 - 闲话安全

posted on 2013-09-07 08:42 微软互联网开发支持 阅读(26264) 评论(89) 编辑 收藏

时间: 2024-10-06 21:49:10

什么是 Web API的相关文章

Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案 (精髓)

前言 刚开始创建MVC与Web API的混合项目时,碰到好多问题,今天拿出来跟大家一起分享下.有朋友私信我问项目的分层及文件夹结构在我的第一篇博客中没说清楚,那么接下来我就准备从这些文件怎么分文件夹说起.问题大概有以下几点: 1.项目层的文件夹结构 2.解决MVC的Controller和Web API的Controller类名不能相同的问题 3.给MVC不同命名空间的Area的注册不同的路由 4.让Web API路由配置也支持命名空间参数 5.MVC及Web API添加身份验证及错误处理的过滤器

C#开发微信门户及应用(47) - 整合Web API、微信后台管理及前端微信小程序的应用方案

在微信开发中,我一直强调需要建立一个比较统一的Web API接口体系,以便实现数据的集中化,这样我们在常规的Web业务系统,Winform业务系统.微信应用.微信小程序.APP等方面,都可以直接调用基于JSON数据格式的Web API接口,在我之前的几篇随笔中,对这方面都有一定的介绍,本篇继续这个主题,细致深入的阐述如何在接口和源码的基础上整合Web API.微信后台管理及前端微信小程序的应用方案. 1.基于Web API的微信开发框架 首先我们各个业务模块,都应该围绕着Web API进行展开,

微信小程序的Web API接口设计及常见接口实现

微信小程序给我们提供了一个很好的开发平台,可以用于展现各种数据和实现丰富的功能,通过小程序的请求Web API 平台获取JSON数据后,可以在小程序界面上进行数据的动态展示.在数据的关键 一环中,我们设计和编写Web API平台是非常重要的,通过这个我们可以实现数据的集中控制和管理,本篇随笔介绍基于Asp.NET MVC的Web API接口层的设计和常见接口代码的展示,以便展示我们常规Web API接口层的接口代码设计.参数的处理等内容. 1.Web API整体性的架构设计 我们整体性的架构设计

Entity Framework 6 Recipes 2nd Edition(9-3)译-&gt;找出Web API中发生了什么变化

9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Frist实现数据访问管理. 本例,我们模拟一个N层场景,用单独的客户端(控制台应用)来调用单独的基于REST服务的Web网站(WEB API应用) . 注意:每层使用单独的Visual Studio 解决方案, 这样更方便配置.调试和模拟一个N层应用. 假设有一个如Figure 9-3所示的旅行社和预订

ASP.NET Web API 2基于令牌的身份验证

基于令牌的认证 我们知道WEB网站的身份验证一般通过session或者cookie完成的,登录成功后客户端发送的任何请求都带上cookie,服务端根据客户端发送来的cookie来识别用户. WEB API使用这样的方法不是很适合,于是就有了基于令牌的认证,使用令牌认证有几个好处:可扩展性.松散耦合.移动终端调用比较简单等等,别人都用上了,你还有理由不用吗? 下面我们花个20分钟的时间来实现一个简单的WEB API token认证: Step 1: 新建一个空的WEB API项目,项目名称就设置为

2种方式解决nginx负载下的Web API站点里swagger无法使用

Web API接口站点,引入了swagger来实时生成在线的api文档,也便于api接口的在线测试.swagger:The World's Most Popular Framework for APIs. 本地测试没有问题. 发布到生产,问题出现了.——线上部署的站点是用nginx做的3个节点的负载.nginx配置了公开的域名,并且与3个节点iis上的站点做了映射.3个单节点的端口不是默认的80,由此问题产生了:当访问swagger时,swagger自动获取的文档的url包含了这个端口,因为站点

asp.net core 2.0 web api基于JWT自定义策略授权

JWT(json web token)是一种基于json的身份验证机制,流程如下: 通过登录,来获取Token,再在之后每次请求的Header中追加Authorization为Token的凭据,服务端验证通过即可能获取想要访问的资源.关于JWT的技术,可参考网络上文章,这里不作详细说明, 这篇博文,主要说明在asp.net core 2.0中,基于jwt的web api的权限设置,即在asp.net core中怎么用JWT,再次就是不同用户或角色因为权限问题,即使援用Token,也不能访问不该访

Web Api和Asp.Net mvc post请求区别

这是mvc的,mvc的post请求可以这样写参数,但是web api的不行.而且content_type:"application/json" 必须要写 下面这是web api的:content_type:"application/json" 必须要写

在Web Api中实现Http方法(Get,Put,Post,Delete)

Post(新增),Put(修改),Delete(删除),Get(查询) GET:生到数据列表(默认),或者得到一条实体数据 POST:添加服务端添加一条记录,记录实体为Form对象 PUT:添加或修改服务端的一条记录,记录实体的Form对象,记录主键以GET方式进行传输 DELETE:删除 服务端的一条记录 上面公开的API接口都是在XMLHttpRequest情况下调用的,当然你可以使用jquery的ajax组件来完成这个请求调用 <fieldset> <legend>测试Web

Web API系列(三)统一异常处理

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 前面讲了webapi的安全验证和参数安全,不清楚的朋友,可以看看前面的文章,<Web API系列(二)接口安全和参数校验>,本文主要介绍Web API异常结果的处理.作为内部或者是对外提供的统一webapi 接口,统一的异常处理,把正确的信息