宣告式RESTful客戶端在asp.net core中的應用
1 宣告式RESTful客戶端
宣告式服務呼叫的客戶端,常見有安卓的Retrofit、SpringCloud的Feign等,.net有Refit和WebApiClient,這些客戶端都是以java或.net某個語言來宣告介面,描述如何請求RESTful api。
1.1 WebApiClient
WebApiClient由c#開發,但適用於任意.net語言,包括c#、vb.net、f#
等專案,其提供兩個nuget包:WebApiClient.JIT和WebApiClient.AOT,均支援.net framework4.5
、.NET Standard 1.3
。
WebApiClient.JIT
在執行時使用Emit建立Http請求介面的代理類,HttpApiClient.Create
- 可以在專案中直接引用WebApiClient.JIT.dll就能使用;
- 不適用於不支援JIT技術的平臺(IOS、UWP);
- 介面要求為public;
WebApiClient.AOT
在編譯過程中使用Mono.Cecil修改編譯得到的程式集,向其插入Http請求介面的代理類IL指令,這一步是在AOT編譯階段之前完成。代理型別所在的程式集、模組、名稱空間與介面型別的一樣,其名稱為$字首的介面型別名稱,使用反編譯工具檢視專案編譯後的程式集可以看到這些代理類。
- 專案必須使用nuget安裝WebApiClient.AOT才能正常使用;
- 沒有JIT,支援的平臺廣泛;
- 介面不要求為public,可以巢狀在類裡面;
1.2 Refit
Refit是一個開發很早的專案,在github有很高的人氣,由c#開發,目前僅支援c#語言專案,支援.NET Standard 1.4
,.net framework需要4.6.1得以支援。
Refit的內部實現與WebApiClient.AOT有相似之處,都是在編譯階段向宣告介面專案插入介面實現類的程式碼或IL指令,我們可以稱之為靜態代理的編譯時織入。Refit使用Microsoft.CodeAnalysis.CSharp來分析介面語法,編譯前補充生成介面的代理類程式碼用來與專案程式碼一起編譯。
2 WebApiClient的宣告式介面
WebApiClient支援GET/HEAD、PUT/POST/DELETE、PATCH請求方法,請求內容體支援json、xml、multipart/form-data、application/x-www-form-urlencoded和自定義無結構內容等,其宣告式介面風格與
asp.net core
的介面宣告非常相似。
2.1 介面宣告
遠端服務
asp.net core
介面示例
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
// GET api/users
[HttpGet]
public UserInfo[] Get()
{
return new UserInfo[]
{
new UserInfo { Account="laojiu" },
new UserInfo { Account="webapicleint" }
};
}
// GET api/users/id001
[HttpGet("{id}")]
public UserInfo Get(string id)
{
return new UserInfo { Id = id, Account = "laojiu" };
}
// POST api/users
[HttpPost]
public bool Post([FromBody] UserInfo value)
{
return true;
}
// PUT api/users
[HttpPut]
public bool Put([FromBody] UserInfo value)
{
return true;
}
// PATCH api/users/id001
[HttpPatch("{id}")]
public bool Patch(string id, [FromBody] JsonPatchDocument<UserInfo> value)
{
var user = new UserInfo { Account = "laojiu" };
value.ApplyTo(user);
return true;
}
// DELETE api/users/id001
[HttpDelete("{id}")]
public bool Delete(string id)
{
return true;
}
}
WebApiClient宣告式呼叫介面
[TraceFilter]
public interface IUsersApi : IHttpApi
{
[HttpGet("api/users")]
ITask<UserInfo[]> GetAsync();
[HttpGet("api/users/{id}")]
ITask<UserInfo> GetAsync(string id);
[HttpPost("api/users")]
ITask<bool> PostAsync([JsonContent] UserInfo value);
[HttpPut("api/users")]
ITask<bool> PutAsync([JsonContent] UserInfo value);
[HttpPatch("api/users/{id}")]
ITask<bool> PatchAsync(string id, JsonPatchDocument<UserInfo> value);
[HttpDelete("api/users/{id}")]
ITask<bool> DeleteAsync(string id);
}
3 WebApiClient與DI結合
在
asp.net core
環境中,我們可以使用WebApiClient.Extensions專案簡單WebApiClient的DI的配置,目前有DependencyInjection和HttpClientFactory的擴充套件等。
3.1 WebApiClient.Extensions.DependencyInjection
引入nuget包
PM> install-package WebApiClient.Extensions.DependencyInjection
Startup相關配置
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpApi<IUsersApi>().ConfigureHttpApiConfig((c,p) =>
{
c.HttpHost = new Uri("https://localhost:5001/");
c.FormatOptions.DateTimeFormat = "yyyy-MM-dd HH:mm:ss.fff";
c.LoggerFactory = p.GetRequiredService<ILoggerFactory>();
});
...
}
Controller
public class HomeController : Controller
{
public async Task<string> Index([FromServices]IUsersApi usersApi)
{
var u = new UserInfo { Id = "id001", Account = "webapiclient", Password = "123456" };
var doc = new JsonPatchDocument<UserInfo>();
doc.Replace(item => item.Password, "888888");
var users = await usersApi.GetAsync();
var user = await usersApi.GetAsync("id001");
var postState = await usersApi.PostAsync(u);
var putState = await usersApi.PutAsync(u);
var patchState = await usersApi.PatchAsync("id001", doc);
var deleteState = await usersApi.DeleteAsync("id001");
return "ok";
}
}
3.2 WebApiClient.Extensions.HttpClientFactory
引入nuget包
PM> install-package WebApiClient.Extensions.HttpClientFactory
Startup相關配置
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpApiTypedClient<IUsersApi>((c, p) =>
{
c.HttpHost = new Uri("https://localhost:5001/");
c.FormatOptions.DateTimeFormat = "yyyy-MM-dd HH:mm:ss.fff";
c.LoggerFactory = p.GetRequiredService<ILoggerFactory>();
});
...
}
4 總結
本文講解了宣告式客戶端的概念、列表幾個宣告式客戶端專案,同時講解宣告式客戶端WebApiClient在asp.net core
專案中的簡單使用,有關更多高階的應用,可以到WebApiClient的github上檢視相關wiki。