web APIS

WEB API系列:

 

           不少人都很迷惑,既然有了WCF为何还要有WEB API?WEB API会不会取代WCF?html

       就个人见解,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的替代产品。web

       OK,如今咱们来开发第一组WEB API接口!使用VS2012之后的版本都有现成的WEB API建立模板,你们跟着建立就行了,建立出来后,项目中会有MVC、WEB API的项目,WEB API对MVC有依赖,不能单首创建!而WEB API和MVC都是利用相似的路由机制,因此在默认路由中,WEB API 使用json

/api/{controller}/{id}

 

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

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

       在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序列化。async

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

 

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

收到响应:响应码为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

        }

}
相关文章
相关标签/搜索