您好,欢迎访问一九零五行业门户网

ASP.NET 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的使用。
    博文中如有不正确的地方欢迎大家指正。
以上就是asp.net web api的适用场景第一个实例 的详细内容。
其它类似信息

推荐信息