WEB API系列(一):WEB API的适用场景、第一个实例

在我前一篇博客中已经给各位简单介绍了HTTP协议与RestFul API的关系,以及一些基本的HTTP协议知识,在这些知识的铺垫下,今天,我们一起来讨论一下WEB API的适用场景,然后写我们第一个WEB API接口,并演示如何对其进行简单调用。

很多人都很迷惑,既然有了WCF为什么还要有WEB API?WEB API会不会取代WCF?

就我的看法,WCF提供的是一种RPC实现的集合,WCF的设计更多地考虑了SOA的场景,以及各种RPC的问题。很多人也会说,RestFul API也是一种RPC啊,并且WCF中也有关于RestFul 的实现啊。很多资料中RPC和RestFul在风格概念上是有一些区别的,其实我觉得这两者的区别比较主观,过度纠结这些就学院派了;我主要关注了实际使用上的一些问题,在WCF中,支持的协议很多,WS-*系列协议,以及一些更简洁的协议,其中提供了一些专用通信协议的性能是非常高的,并且WCF还提供了服务发现等功能,我认为WCF更适合内部系统间的高性能调用,社区中也有其他一些RPC方案可以选择,例如gRPC,Avor,thrift都是和WCF定位相同的产品;而WEB API是关注于HTTP RestFul风格的产品,在此基础上,任何语言、任何终端都能非常容易地进行对接,并且能利用非常成熟的各种HTTP基础设施和解决方案来进行开发、调试、负载均衡、内容分发。所以,WEB API是一种针对HTTP的,偏重于快速开发RestFul风格开放式API的开发框架。目前看来,他并不能取代WCF,他们各有适合的场景,不能认为WEB API是WCF的替代产品。

OK,现在我们来开发第一组WEB API接口!使用VS2012以后的版本都有现成的WEB API创建模板,大家跟着创建就好了,创建出来后,项目中会有MVC、WEB API的项目,WEB API对MVC有依赖,不能单独创建!而WEB API和MVC都是利用类似的路由机制,所以在默认路由中,WEB API 使用

/api/{controller}/{id}

作为路由,添加了/api/节以区分MVC和web api。

接下来,我们添加一个WEB API的Controller,取名为PersonController,他继承于ApiController;在创建这个Controller的时候,我们就定义了一种资源:Person,在PersonController里的所有操作均围绕着Person这个资源来的。接下来我们开始定义一组增删改查操作。

在Web API中,默认路由采用了一种约定:根据谓词来进行路由,而方法名的前缀就是调用该方法对应使用的HTTP谓词。代码示例如下:

/// <summary>

    /// Person 为资源,对Person进行的一组操作

    /// </summary>

    public class PersonController : ApiController

    {

        private static List<Person> _personLst = new List<Person>();

        /// <summary>

        /// 获取一个Person

        /// </summary>

        /// <param name="id">Person的ID</param>

        /// <returns>Person</returns>

        public Person GetPerson(long id)

        {

            return _personLst.Find(x => x.Id == id);

        }

        /// <summary>

        /// 添加一个Person

        /// </summary>

        /// <param name="person">Person</param>

        public void PostAddPerson(Person person)

        {

            _personLst.Add(person);

        }

        /// <summary>

        /// 修改一个

        /// </summary>

        /// <param name="id">Person Id</param>

        /// <param name="person">新</param>

        public void PutModifyPerson(long id, Person person)

        {

            var p = _personLst.Find(x => x.Id == id);

            p.Age = person.Age;

            p.Name = person.Name;

            p.Sex = person.Sex;

        }

        /// <summary>

        /// 删除一个Person

        /// </summary>

        /// <param name="id">Person ID</param>

        public void DeletePerson(long id)

        {

            _personLst.RemoveAll(x => x.Id == id);

        }

}

一个简单的针对资源的CRUD操作的API就好了,不用解析输入,不用拼接输出,就是那么简单!让我们来遛一遛!

发送请求:谓词为POST,语义创建Person,Person描述在Body里,head中声明了Body通过Json序列化。

收到响应:响应码204,属于2XX类型执行成功,Body里没有数据

发送请求:谓词为GET,语义为查询Person资源,Id为1的,head中声明希望接收使用XML序列化的数据

收到响应:响应码为200,执行成功,Body中有数据,数据使用XML序列化

发送请求:谓词为PUT,语义为修改ID为1的Person资源,修改内容在Body中,Content-Type标明Body使用Json序列化,在Body中我们将Name修改为Test1Changed

收到响应,响应码为204,执行成功

发送请求:谓词为GET,语义为查询ID为1的Person资源,Accept标明希望接收到Json数据

收到响应:可以看到Body为使用Json序列化的内容,Name属性已经变更为Test1Changed

发送请求:谓词为DELETE,语义为删除ID为1的Person资源

收到响应:响应码204,执行成功

发送请求:谓词为GET,语义为查询ID为1的Person资源,Accept标明希望接收到Json数据

收到响应:响应码为200,执行成功,响应内容为null,资源已删除

这就是我用Fiddler来发送、调用的一组RestFul接口,大家可以看到,整个调用过程使用到了HTTP的语义,用到了谓词路由、内容协商。在增、删、改操作中,我都是使用void作为返回值,根据HTTP Code 判断,大家也可以自定义一些返回数据来做出更进一步的操作描述。

在写了这些API后,我们需要在程序中调用,我以C#为例写一组对这些接口调用的实现。在C#中,传统调用HTTP接口一般有两种办法: WebRequest/WebResponse组合的方法调用和WebClient类进行调用。第一种方法抽象程度较低,使用较为繁琐;而WebClient主要面向了WEB网页场景,在模拟Web操作时使用较为方便,但用在RestFul场景下却比较麻烦,在Web API发布的同时,.NET提供了两个程序集:System.Net.Http和System.Net.Http.Formatting。这两个程序集中最核心的类是HttpClient。在.NET4.5中带有这两个程序集,而.NET4需要到Nuget里下载Microsoft.Net.Http和Microsoft.AspNet.WebApi.Client这两个包才能使用这个类,更低的.NET版本就只能表示遗憾了只能用WebRequest/WebResponse或者WebClient来调用这些API了。

在使用中,System.Net.Http这个程序集提供了HttpClient类以及相关的HTTP调用,而System.Net.Http.Formatting提供了一些针对HttpClient的帮助扩展,更好地支持了内容协商、Content创建等功能。下面我就和大家一起写一下这个例子:

我们新建一个控制台程序:

代码如下:

public class Person

    {

        public long Id { get; set; }

        public string Name { get; set; }

        public int Age { get; set; }

        public string Sex { get; set; }

        public override string ToString()

        {

            return $"Id={Id} Name={Name} Age={Age} Sex={Sex}";

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            var client = new HttpClient();

            client.BaseAddress = new Uri("http://localhost:22658/"); //基本的API URL

            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); //默认希望响应使用Json序列化

            Run(client);

            Console.ReadLine();

        }

        static async void Run(HttpClient client)

        {

            var result = await AddPerson(client);

            Console.WriteLine($"添加结果:{result}"); //添加结果:true

            var person = await GetPerson(client);

            Console.WriteLine($"查询结果:{person}"); //查询结果:Id=1 Name=test Age=10 Sex=F

            result = await PutPerson(client);

            Console.WriteLine($"更新结果:{result}"); //更新结果:true

            result = await DeletePerson(client);

            Console.WriteLine($"删除结果:{result}"); //删除结果:true

        }

        static async Task<bool> AddPerson(HttpClient client)

        {

            return await client.PostAsJsonAsync("api/Person", new Person() { Age = 10, Id = 1, Name = "test", Sex = "F" }) //向Person发送POST请求,Body使用Json进行序列化

                                     .ContinueWith(x => x.Result.IsSuccessStatusCode);  //返回请求是否执行成功,即HTTP Code是否为2XX

        }

        static async Task<Person> GetPerson(HttpClient client)

        {

            return await await client.GetAsync("api/Person/1") //向Person发送GET请求

                .ContinueWith(x => x.Result.Content.ReadAsAsync<Person>(                              //获取返回Body,并根据返回的Content-Type自动匹配格式化器反序列化Body

                    new List<MediaTypeFormatter>() {new JsonMediaTypeFormatter()/*这是Json的格式化器*/

                                                    ,new XmlMediaTypeFormatter()/*这是XML的格式化器*/}));

        }

        static async Task<bool> PutPerson(HttpClient client)

        {

            return await client.PutAsJsonAsync("api/Person/1", new Person() { Age = 10, Id = 1, Name = "test1Change", Sex = "F" }) //向Person发送PUT请求,Body使用Json进行序列化

                                    .ContinueWith(x => x.Result.IsSuccessStatusCode);  //返回请求是否执行成功,即HTTP Code是否为2XX

        }

        static async Task<bool> DeletePerson(HttpClient client)

        {

            return await client.DeleteAsync("api/Person/1") //向Person发送DELETE请求

                .ContinueWith(x => x.Result.IsSuccessStatusCode); //返回请求是否执行成功,即HTTP Code是否为2XX

        }

}

这就完成了这组API的调用,是不是非常简单方便?HTTPClient使用全异步的方法,并且他有良好的扩展性,我会在之后的博客中再聊这个问题。

OK,到此为止一组简单的Restful API和C#的调用客户端就完成了,但这只是开始,Web API是一个很强大的框架,他的扩展点非常丰富,这些扩展能为我们的开发提供很多的帮助,下一篇博文我将为大家带来WEB API中Filter的使用。

博文中如有不正确的地方欢迎大家指正。

时间: 2024-11-08 19:53:30

WEB API系列(一):WEB API的适用场景、第一个实例的相关文章

Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问

本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这部分内容需要以下Jar包支持 mysql-connector:MySQL数据库连接驱动,架起服务端与数据库沟通的桥梁: MyBatis:一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架: log4j:Apache的开源项目,一个功能强大的日志组件,提供方便的日志记录: 修改后的pom.xm

web站点系列------选择web服务器

仅以此系列见证我的第一个web网站www.liuliancao.com的成长过程 web服务器的选择 纵观web服务器,我大致有三种选择,分别是Apache httpd,Nginx,Lighthttpd 首先,由于在学校,所以还可以用ali yun的云翼计划9.9元云服务器,配置如下 地区:青岛B区 CPU:1核 流量包:15G Linux存储:20G 那么毫无疑问,我需要一个内存消耗少,对动态处理要求不是非常高的,能处理小站的一个mini web服务器 对比了网上的大致分析,我得到以下信息,可

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

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

ASP.NET Web API系列教程(目录)(转)

注:微软随ASP.NET MVC 4一起还发布了一个框架,叫做ASP.NET Web API.这是一个用来在.NET平台上建立HTTP服务的Web API框架,是微软的又一项令人振奋的技术.目前,国内对此关注的人似乎还不多,有关ASP.NET Web API的文章也不多见.为此,本人打算对微软ASP.NET Web API官方网站上的一些教程进行翻译,以期让更多的国人了解.学习和使用这项ASP.NET Web API. ASP.NET Web API系列教程目录 Introduction:Wha

ASP.NET Web API系列教程目录

ASP.NET Web API系列教程目录 Introduction:What's This New Web API?引子:新的Web API是什么? Chapter 1: Getting Started with ASP.NET Web API第1章 ASP.NET Web API入门 Your First Web API (C#)第一个Web API(C#) Deep Dive into Web API深入探讨Web API(这是一个视频教程,本翻译系列略) Pro ASP.NET Web

Web Api系列教程第2季(OData篇)(二)&mdash;&mdash;使用Web Api创建只读的OData服务

前言 很久没更新了,之前有很多事情,所以拖了很久,非常抱歉.好了,废话不多说,下面开始正题.本篇仍然使用上一季的的项目背景(系列地址http://www.cnblogs.com/fzrain/p/3490137.html)来演示OData服务,因此我们可以直接使用之前建好的数据访问层.但是不是说一定要看到之前的所有内容,我们只是借用数据库访问层,对于数据库的模型构建移步(使用Entity Framework Code First构建数据库模型). 有了数据访问的基础,我们可以开始构建OData服

【Web API系列教程】2.1 — ASP.NET Web API中的路由机制

这篇文章描述了ASP.NET Web API如何将HTTP请求发送(路由)到控制器. 备注:如果你对ASP.NET MVC很熟悉,你会发现Web API路由和MVC路由非常相似.主要区别是Web API使用HTTP方法来选择动作(action),而不是URI路径.你也可以在Web API中使用MVC风格的路由.这篇文章不需要ASP.NET MVC的任何知识. 路由表 在ASP.NET Web API中,控制器是一个用于处理HTTP请求的类.控制器中的公共方法被称为动作方法或简单动作.当Web A

【Web API系列教程】1.1 — ASP.NET Web API入门

前言 HTTP不仅仅服务于web页面.同一时候也是构建暴露服务和数据的API的强大平台.HTTP有着简单.灵活和无处不在的特点.你能想到的差点儿全部平台都包括有一个HTTP库.所以HTTP服务能够遍及广泛的client,包括浏览器.移动设备和传统桌面应用程序. ASP.NET Web API是一个在.NET框架上构建web API的框架.在本教程中,你将使用ASP.NET Web API来创建一个返回产品列表的web API. 创建Web API项目 在本教程中,你将使用ASP.NET Web

ASP.NET MVC Web API 学习笔记---Web API概述及程序示例

1. Web API简单说明 近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过在浏览器中使用 JavaScript来创建更丰富的HTML体验.所以我相信Web API会越来越有它的用武之地. 说道Web API很多人都会想到Web服务,但是他们仍然有一定的区别:Web API服务是通过一般的 HTTP公开了,而不是通过更正式的服务合同 (如SOAP) 2. ASP.NET W

API优先的Web框架Synth,以及社区的不同声音

在近期Google的AngularJS会议上,Synth浮出水面,它是一套基于Node.js构建的API优先的Web应用框架. 自Synth被披露以来,在一个半月的时间里,其GitHub项目从1星增长到了超过500星.但Synth的创造者Jon Abrams表示,更广泛的开发者社区依旧对该框架感到迷茫. Jon Abrams表示,Synth项目不同于传统Node.js Web框架.它的设计目的,是简化后端资源的创建过程--这些资源可以在加载AngularJS视图的时候自动预加载. Synth的特