.net的retrofit--WebApiClient库
库简介
WebApiClient是开源在github上的一个httpClient客户端库,内部基于HttpClient开发,是一个只需要定义c#接口(interface),并打上相关特性,即可异步调用http-api的框架 ,支持.net framework4.5+、netcoreapp2.0和netstandard2.0。本文将详细地讲解如何使用WebApiClient进行http接口的调用,给.net开发者提供一种有别于传统的http接口调用编程方式。
1. 设计一个Get请求接口
1.1 最简单的Get请求
public interface MyWebApi : IDisposable
{
// GET http://www.mywebapi.com/webapi/user?account=laojiu
[HttpGet("http://www.mywebapi.com/webapi/user")]
ITask<string> GetUserByAccountAsync(string account);
}
var myWebApi = HttpApiClient.Create<MyWebApi>();
var userStr = await myWebApi.GetUserByAccountAsync("laojiu");
myWebApi.Dispose();
1.2 使用[HttpHost]特性
如果你有多个接口,而且都指向对一服务器,可以将请求的域名抽出来放到HttpHost特性,接口的代码如下:
[HttpHost("http://www.mywebapi.com")]
public interface MyWebApi : IDisposable
{
// GET /webapi/user?account=laojiu
[HttpGet("/webapi/user")]
ITask<string> GetUserByAccountAsync(string account);
}
1.3 使用强类型返回值处理xml或json
如果接口的返回内容是xml或json,你希望将它自动映射为强类型的模型,需要给接口打上对应的[XmlReturn]或[JsonResult]。实际上有一个[AutoReturn],它会根据回复头标识,自动选择不同的转换器转换为TResult类型的结果,默认的,每个接口都使用了[AutoReturn],除非给接口显性地给方法配置了[XmlReturn]或[JsonResult]。如果以上返回的userStr是UserInfo类型的xml或json文本,那么强类型的代码声明如下:
[HttpHost("http://www.mywebapi.com")]
public interface MyWebApi : IDisposable
{
// GET /webapi/user?account=laojiu
[HttpGet("/webapi/user")]
ITask<UserInfo> GetUserByAccountAsync(string account);
}
[HttpHost("http://www.mywebapi.com")]
[JsonReturn] // 指明使用Json处理返回值为UserInfo类型
public interface MyWebApi : IDisposable
{
// GET /webapi/user?account=laojiu
[HttpGet("/webapi/user")]
ITask<UserInfo> GetUserByAccountAsync(string account);
}
2.请求URL的多个参数
2.1 参数平铺
你可以将多个参数一一设计为接口的参数,类似于:
// GET /webapi/user?account=laojiu&password=123456
[HttpGet("/webapi/user")]
ITask<UserInfo> GetUserAsync(string account, string password);
2.2 参数合并到模型
也可以将所有参数合到一个简单的多属性模型对象:
public class MyParameters
{
public string Account { get; set; }
public string Password { get; set; }
}
// GET /webapi/user?account=laojiu&password=123456
[HttpGet("/webapi/user")]
ITask<UserInfo> GetUserAsync(MyParameters parameters);
2.3 模型+简单参数混合
在一些场景中,除了提交多属性模型对象之外,可能还需要一个简单类型的额外参数,你可以如下编写接口:
// GET /webapi/user?account=laojiu&password=123456&birthDay=2010-01-01 01:01:01
[HttpGet("/webapi/user")]
ITask<UserInfo> GetUserAsync(MyParameters parameters,DateTime birthDay);
上面这里,你可能会遇到一个问题,birthDay会简单的ToString()值做为参数值,如果你希望只需要日期而不包含时间,你可以给birthDay指定格式:
// GET /webapi/user?account=laojiu&password=123456&birthDay=2010-01-01
[HttpGet("/webapi/user")]
ITask<UserInfo> GetUserAsync(
MyParameters parameters,
[PathQuery("yyyy-MM-dd")] DateTime birthDay);
实际上,对于没有任何特性修饰的每个参数,都默认被[PathQuery]修饰,表示做为请求路径或请求参数处理,[PathQuery]的构造器重载方法可以指定日期时间格式。
3.设计一个Post请求接口
3.1使用x-www-form-urlencoded提交请求
// POST webapi/user
// Body Account=laojiu&Password=123456
[HttpPost("/webapi/user")]
ITask<UserInfo> UpdateUserWithFormAsync([FormContent] UserInfo user);
设计风格和Get请求是差不多的,你应该发现,接口参数被[FormContent]修饰了,[FormContent]的作用是将模型参数user以key1=value1&key2=value2的方式写入到请求内容中。如果你还需要提供一个额外的简单类型参数,需要使用[FormField]修饰这个参数,可以这样设计接口:
// POST webapi/user
// Body Account=laojiu&Password=123456&fieldX=xxx
[HttpPost("/webapi/user")]
ITask<UserInfo> UpdateUserWithFormAsync(
[FormContent] UserInfo user,
[FormField] string fieldX);
3.2使用multipart/form-data提交请求
// POST webapi/user
[HttpPost("/webapi/user")]
ITask<UserInfo> UpdateUserWithMulitpartAsync([MulitpartContent] UserInfo user);
// POST webapi/user
[HttpPost("/webapi/user")]
ITask<UserInfo> UpdateUserWithMulitpartAsync(
[MulitpartContent] UserInfo user,
[MulitpartText] string nickName,
MulitpartFile file);
需要了解的是,[MulitpartText]表示是一个文本项,而MulitpartFile表示一个文件项,MulitpartFile实现了IApiParameterable接口,它不需要任何特性的修饰,它能提供自我解释和处理。
3.3提交Json或Xml文本
对于json和xml,只能一次性提交一个参数,不支持额外参数之说
// POST webapi/user
// Body user的json文本
[HttpPost("/webapi/user")]
ITask<UserInfo> UpdateUserWithJsonAsync([JsonContent] UserInfo user);
// POST webapi/user
// Body user的xml文本
[HttpPost("/webapi/user")]
ITask<UserInfo> UpdateUserWithXmlAsync([XmlContent] UserInfo user);
如果你的UserInfo有DateTime类型的属性,你可以使用[JsonContent("时间格式")]来修饰接口参数,否则时间格式使用HttpApiConfig的DateTimeFormate。
3.4 提交原始的HttpContent
// POST webapi/user
// Body Account=laojiu&Password=123456
[HttpPost("/webapi/user")]
ITask<UserInfo> UpdateUserWithFormAsync(FormUrlEncodedContent user);
// POST webapi/user
// Body Account=laojiu&Password=123456&age=18
[HttpPost("/webapi/user")]
ITask<UserInfo> UpdateUserWithFormAsync(
[HttpContent] FormUrlEncodedContent user,
[FormField] int age);
默认的,所有System.Net.Http.HttpContent类型的参数,都会被[HttpContent]特性修饰,而且可以与表单字段特性等混合使用。值得说明的话,传统的System.Net.Http.HttpContent类型参数必须放到其它表单字段参数的前面。
4. 动态指定请求的域名或Url
4.1 域名动态而相对路径固定
以上的例子,请求的根路径都是硬编码,而在不少场景中是放在配置文件中的,可以在创建接口实例时创建配置项:
var config = new HttpApiConfig
{
// 请求的域名,会覆盖[HttpHost]特性
HttpHost = new Uri("http://www.webapiclient.com"),
};
var myWebApi = HttpApiClient.Create<MyWebApi>(config);
var userStr = await myWebApi.GetUserByAccountAsync("laojiu");
myWebApi.Dispose();
4.2 每个请求接口的URL路径都是动态的
有时,多个接口方法的全部URL都是运行时才确定的,这时,需要给每个接口做如下的调整,注意[Url]特性表示参数是请求的URL,要求必须放在第一个参数。:
public interface MyWebApi : IDisposable
{
// GET {URL}?account=laojiu
[HttpGet]
ITask<string> GetUserByAccountAsync([Url] string url, string account);
}
4.3 相对路径某个分段动态
有时,有些接口会将某个参数做路径的一个分段,比如GET http://www.webapiclient.com/{account},这里的{account}是动态的,获取哪个账号的资料就填写哪个账号,可以如下设计接口
public interface MyWebApi : IDisposable
{
// GET http://www.webapiclient.com/laojiu
[HttpGet("http://www.webapiclient.com/{account}"]
ITask<string> GetUserByAccountAsync(string account);
}
5.参数别名或属性别名
5.1 参数别名
有些服务端接口要求的键名与你的编程风格不一致,或者使用了特殊的键名为.net语言不允许的参数名,你可以使用[AliasAs("name")]来给参数或模型的属性别名。
public interface MyWebApi : IDisposable
{
// GET http://www.mywebapi.com/webapi/user?_name=laojiu
[HttpGet("http://www.mywebapi.com/webapi/user")]
ITask<string> GetUserByAccountAsync(
[AliasAs("_name")] string account);
}
5.2 模型的属性别名
public class UserInfo
{
[AliasAs("loginAccount")]
public string Account { get; set; }
public string Password { get; set; }
}
6.特性的范围和优先级
6.1 特性的范围
有些特性比如[Header],可以修饰于接口、方法和参数,使用不同的构造器和修饰于不同的地方产生的含义和结果是有点差别的:
- 修饰接口时,表示接口下的所有方法在请求前都会添加这个请求头;
- 修饰方法时,表示此方法在语法前添加这个请求头;
- 修饰参数时,表示参数的值将做为请求头的值,由调用者动态传入;
6.2 特性的优先级
有些特性比如[AutoReturn]和[JsonReturn],可以修饰于接口和方法,但特性的AllowMultiple为false,如果在接口级生明方法级[AutoReturn],在方法级上声明[JsonReturn],此方法实际生效的是[JsonReturn];再比如[Timeout]特性,如果在接口级声明[Timeout(5000)]在方法级声明[Timeout(10000)],实际生效的是[Timeout(10000)],总结如下:
- AllowMultiple为false的同一个特性,方法级比接口级优先级高
- AllowMultiple为false的不同类型的[ReturnAttribute],方法级比接口级优先级高
.net的retrofit--WebApiClient库的更多相关文章
- Rxjava, RxAndroid, Retrofit 等库的使用
RxJava的基本用法: 关于 unSubscribe() 的调用问题: There is no need to unsubscribe in onCompleted. Take a look at ...
- WebApiClient库支持AOT
1 库简介 WebApiClient是开源在github上的一个http客户端库,内部基于HttpClient开发,只需要定义c#接口(interface),并打上相关特性,即可异步调用http-ap ...
- 一种优雅的条件引用第三方.net库的方法
1.遇到的问题 今年我一直在开发一个WebApiClient库,旨在.net下能像java的retrofit一样,方便地请求服务端的http接口.在这restful api盛行的年代,json的身影无 ...
- WebApiClient的JsonPatch局部更新
1. 文章目的 随着WebApiClient的不断完善,越来越多开发者选择WebApiClient替换原生的HttpClient,本文将介绍使用WebApiClient来完成JsonPatch提交的新 ...
- WebApiClient的接口输入验证
1. 文章目的 随着WebApiClient的不断完善,越来越多开发者选择WebApiClient替换原生的HttpClient,本文将介绍WebApiClient的接口参数输入有效性验证的新特性. ...
- WebApiClient百度地图服务接口实践
1. 文章目的 随着WebApiClient的不断完善,越来越多开发者选择WebApiClient替换原生的HttpClient,然而在应用到实际项目中多多少少会遇到一些项目结合上的疑问和困难,本文将 ...
- RxJava+Retrofit+OkHttp,一步一步封装网络框架;
使用RxJava+Retrofit+OkHttp,首先在build.gradle添加: compile 'com.squareup.okhttp3:okhttp:3.8.1' compile 'com ...
- Android RxJava/RxAndroid结合Retrofit使用
概述 RxJava是一个在 Java VM 上使用可观測的序列来组成异步的.基于事件的程序的库.更重要的是:使用RxJava在代码逻辑上会非常简洁明了,尤其是在复杂的逻辑上.告别迷之缩进. RxAnd ...
- .net的retrofit--WebApiClient底层篇
前言 本篇文章的内容是WebApiClient底层说明,也是WebApiClient系列接近尾声的一篇文章,如果你没有阅读过之前的的相关文章,可能会觉得本文章的内容断层,WebApiClient系列文 ...
- 请给你的短信验证码接口加上SSL双向验证
序言 去年年底闲来几天,有位同事专门在网上找一些注册型的app和网站,研究其短信接口是否安全,半天下来找到30来家,一些短信接口由于分析难度原因,没有继续深入,但差不多挖掘到20来个,可以肆意被调用, ...
随机推荐
- 八、 Spring Boot 过滤器、监听器
直接使用@WebFilter和@WebListener的方式,完成一个Filter 和一个 Listener.过滤器(Filter)文件MyFilter.Javapackage org.springb ...
- tomcat启动失败的一种可能性
今天搭建一个新的项目,采用spring+hibernate框架,项目框架搭建完成以后,启动tomcat,报错,如下图. 第一反应是tomcat的问题,于是clean了tomcat,没用,再把tomca ...
- 后台程序处理 (一)python asyncio 协程使用
由于脚本需要在完成事件处理后N秒检查事件处理结果,当执行失败时再执行另一个事件处理. 想要最小化完成这个功能.同时在第一时间就将执行完毕的结果反馈给接口. 因此想到使用协程. 使用之前先翻阅了一下现有 ...
- 为eclipse离线安装hibernate tools插件
工具/原料 eclipse luna jboss hibernate tools 方法/步骤 下载hibernate tools插件 在eclipse根目录下创建myplugins和l ...
- 理解cocoa和cocoa touch的响应者链
该文章翻译自:Understanding cocoa and cocoa touch responder chain. 转载注明出处:http://www.cnblogs.com/zhanggui/p ...
- IntelliJ IDEA如何设置头注释,自定义author和date
下面这张图,保证你一看就会: 下面这个模板,你拿去改一改就行了. /** * @Author: Gosin * @Date: ${DATE} ${TIME} */ 如果觉得上面名字下面的波浪线碍眼,可 ...
- BZOJ 4553 Tjoi2016&Heoi2016 序列
Tjoi2016&Heoi2016序列 Description 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他.玩具上有一个数列,数列中某些项的值 可能会变化,但同一个时刻最 ...
- bzoj 3626: [LNOI2014]LCA
Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q ...
- <tangmuchw>之新手vue项目小记--新建.vue文件,运行项目,出现error:This dependency was not found...
错误码: This dependency was not found: * !!vue-style-loader!css-loader?{"minimize":false,&quo ...
- Golang 网络爬虫框架gocolly/colly 一
Golang 网络爬虫框架gocolly/colly 一 gocolly是用go实现的网络爬虫框架,目前在github上具有3400+星,名列go版爬虫程序榜首.gocolly快速优雅,在单核上每秒可 ...