使用Kiota工具生成WebApi的代理类,以及接口调用的简单体验

news/2024/11/16 2:51:10/文章来源:https://www.cnblogs.com/vipwan/p/18372027

前言

当前.NET环境下,生成WebApi代理类的工具已经有很多选择了,比如OpenApi Generator,NSwagRefitter等,不同的工具生成的代码风格以及实现方式略有不同,比如Refitter生成的客户端是Refit风格.

本人比较喜欢Refit风格的标注风格因此还是比较喜欢使用Refitter的,TA生成的代码风格如下:

[Headers("Accept: application/json")]
[Get("/pet/{petId}")]
Task<Pet> GetPetById(long petId);

不过呢今天介绍的主角是Kiota,这个MS于2023年正式发布的一款代理生成工具,体验还是挺棒的,毫不夸张的说,算是这一领域的新贵了!

Kiota有以下诸多特性:

  • 支持多种语言:C#、CLI、Go、Java、PHP、Python、Ruby、Swift 和 TypeScript
  • 使用 OpenAPI 描述的全部功能
  • 能够轻松实施新的语言支持
  • 通过在核心库上构建,仅生成必要的源代码
  • 最小化外部依赖性
  • 使用 JSON Schema 描述生成基于基元的模型序列化/反序列化代码
  • 仅允许为OpenAPI描述的指定子集生成代码
  • 生成使 IDE 能够自动完成以帮助发现 API 资源的代码
  • 启用对 HTTP 功能的完全访问

命令行工具安装

接下来我们简单使用一下该工具:

当前以我们使用最多的Windows操作系统为例,首先安装NET8SDK,然后打开命令行工具,安装Kiota,当前最新版已经更新到了 1.17.0:

dotnet tool install --global Microsoft.OpenApi.Kiota

image

命令行生成代理

接下来我们随意创建一个NET8的MinimalApi项目,然后我们以Petshop3的Api为例,为了加快速度我们将接口Scheme文件下载到项目文件夹下:
文档地址为: https://petstore3.swagger.io/api/v3/openapi.json
当然了你也可以使用自己的WebApi;Schema文件下载完成后 我们使用命令行工具定位到对应的文件夹,然后键入如下命令:

kiota generate -l CSharp -o output -d petstore.json -n PetShops.V3

这里解释一下参数:

  • -l是客户端目标语言,CSharp就是C#
  • -o表示生成的代理类文件保存的文件夹
  • -d表示对应的schema文件,
  • -n表示生成的代理类的命名空间
    当然还有一些其他的参数这里就不一一列举,比如按需生成(排除保留指定的Api),有兴趣可以查看官方文档

如果没有其他问题,将会成功创建代理文件:
image

image

生成了代理类那使用起来就相当简单了:

调用生成的代理

接下来我们引用Kiota必须的几个类库:

<PackageReference Include="Microsoft.Kiota.Abstractions" />
<PackageReference Include="Microsoft.Kiota.Http.HttpClientLibrary" />
<PackageReference Include="Microsoft.Kiota.Serialization.Form" />
<PackageReference Include="Microsoft.Kiota.Serialization.Json"/>
<PackageReference Include="Microsoft.Kiota.Serialization.Multipart" />
<PackageReference Include="Microsoft.Kiota.Serialization.Text"  />

这里假设PetShop的接口需要简单验证才能访问:
我们首先定义一个名为SimpleAuthenticationProvider的类,该类实现了IAuthenticationProvider接口,代码如下:


internal class SimpleAuthenticationProvider(string baseUrl, string? userName, string? password) : IAuthenticationProvider
{public async Task AuthenticateRequestAsync(RequestInformation request,Dictionary<string, object>? additionalAuthenticationContext = null,CancellationToken cancellationToken = default){using var httpClient = new HttpClient(){BaseAddress = new Uri(baseUrl)};httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));var authRequest = await httpClient.GetAsync($"v3/user/login?username={userName}&password={password}", cancellationToken);if (!authRequest.IsSuccessStatusCode){throw new Exception("Authentication failed");}var session = await authRequest.Content.ReadAsStringAsync(cancellationToken);Console.WriteLine($"session: {session}");await Task.CompletedTask;//todo:}
}

上面的代码很简单就是模拟一个登录,然后后面的请求就存在了session即可进行后续的接口调用,如果有些认证是JWT之内的这里可以把得到的Token传入到后续的Header中,当然认证请求务必缓存起来,不用每个接口调用都请求一次!

MS默认帮我们实现了AnonymousAuthenticationProviderBaseBearerTokenAuthenticationProvider两个认证Provider.

以下是简单的调用接口:

//分别调用条件查询Pet,以及根据Id查询指定的Pet
app.MapGet("/test", async () =>
{var baseUrl = "https://petstore3.swagger.io/api/v3";var userName = "万雅虎";var password = "12345";var adaptor = new HttpClientRequestAdapter(new SimpleAuthenticationProvider(baseUrl, userName, password)){BaseUrl = baseUrl};var api = new ApiClient(adaptor);var pets = await api.Pet.FindByStatus.GetAsync(x =>{x.QueryParameters.StatusAsGetStatusQueryParameterType =PetShops.V3.Pet.FindByStatus.GetStatusQueryParameterType.Sold;});var pet = await api.Pet[1].GetAsync();return new { Pets = pets, Pet = pet };
});

不出意外请求成功了:
image

注入ApiClient

当然上面的调用代码显得有一些粗糙,实际上大多数开发代码会使用到DI,
我们使用MS提供的示例代码扩展一下IServiceCollection

using Microsoft.Kiota.Http.HttpClientLibrary;/// <summary>
/// Service collection extensions for Kiota handlers.
/// </summary>
public static class KiotaServiceCollectionExtensions
{/// <summary>/// Adds the Kiota handlers to the service collection./// </summary>/// <param name="services"><see cref="IServiceCollection"/> to add the services to</param>/// <returns><see cref="IServiceCollection"/> as per convention</returns>/// <remarks>The handlers are added to the http client by the <see cref="AttachKiotaHandlers(IHttpClientBuilder)"/> call, which requires them to be pre-registered in DI</remarks>public static IServiceCollection AddKiotaHandlers(this IServiceCollection services){// Dynamically load the Kiota handlers from the Client Factoryvar kiotaHandlers = KiotaClientFactory.GetDefaultHandlerTypes();// And register them in the DI containerforeach(var handler in kiotaHandlers){services.AddTransient(handler);}return services;}/// <summary>/// Adds the Kiota handlers to the http client builder./// </summary>/// <param name="builder"></param>/// <returns></returns>/// <remarks>/// Requires the handlers to be registered in DI by <see cref="AddKiotaHandlers(IServiceCollection)"/>./// The order in which the handlers are added is important, as it defines the order in which they will be executed./// </remarks>public static IHttpClientBuilder AttachKiotaHandlers(this IHttpClientBuilder builder){// Dynamically load the Kiota handlers from the Client Factoryvar kiotaHandlers = KiotaClientFactory.GetDefaultHandlerTypes();// And attach them to the http client builderforeach(var handler in kiotaHandlers){builder.AddHttpMessageHandler((sp) => (DelegatingHandler)sp.GetRequiredService(handler));}return builder;}
}

然后实现一个Api的ClientFactory:

//这里是伪代码,因为认证需要根据Api按需实现,比如这里是匿名请求
public class PetShopClientFactory
{private readonly IAuthenticationProvider _authenticationProvider;private readonly HttpClient _httpClient;public PetShopClientFactory(HttpClient httpClient){_authenticationProvider = new AnonymousAuthenticationProvider();_httpClient = httpClient;}public ApiClient GetClient() {return new ApiClient(new HttpClientRequestAdapter(_authenticationProvider, httpClient: _httpClient));}
}

然后在服务注册中添加如下代码:


// ----------- Add this part to register the generated client -----------
// Add Kiota handlers to the dependency injection container
builder.Services.AddKiotaHandlers();// Register the factory for the GitHub client
builder.Services.AddHttpClient<PetShopClientFactory>((sp, client) => {// Set the base address and accept header// or other settings on the http clientclient.BaseAddress = new Uri("https://petstore3.swagger.io/api/v3");client.DefaultRequestHeaders.Add("Accept", "application/json");
}).AttachKiotaHandlers(); // Attach the Kiota handlers to the http client, this is to enable all the Kiota features.// Register the GitHub client
builder.Services.AddTransient(sp => sp.GetRequiredService<PetShopClientFactory>().GetClient());
// ----------- Add this part to register the generated client end -------

最后我们在使用的地方注入ApiClient即可!

总结

对于不同的代理类和工具选型这里不做推荐,能满足项目需求以及节省开发时间即可,不过如果你有兴趣倒是推荐体验一下KiotaRefitter,没准你会和我一样喜欢上TA!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/784905.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

039、Vue3+TypeScript基础,路由中使用redirect来重定向

01、index.ts代码如下://创建路由并暴露出去 import {createRouter, createWebHistory} from vue-router import Home from @/view/Home.vue import About from @/view/About.vue import News from @/view/News.vue import Detail from @/view/Detail.vueconst router = creat…

传习录

《传习录》 王阳明此心光明,亦复何言。 ◆ 徐爱录 2023/09/07发表想法 至善是心的本体,是内在的,只要我们把‘明明德’的工夫,做到“惟精、惟一”的程度就是至善。 大学之道,在明明德,在亲民,在止于至善。知止而后有定,定而后能静,静而后能安,安而后能虑,虑而后能得…

mysql and != 条件判断,某字段为空,是否会影响结果

1.在单表查询中,会影响2.在left join 查询中,会影响 加上或者is null去掉或者is null sepo.budget_status != 2 。null也是!= 2 的,但是查不出来下班记得打卡

收拾混乱账密,IT特权账号管理实践分享

随着网络设备、服务器、应用等被管对象越来越多,而要访问这些被管对象,基本入口都会要求登录账密。 而处于安全的考虑,IT部门都会制定相应的密码策略,包括密码复杂度要求,密码有效期、密码重复度等。 如果您习惯使用纸质、Word、Excel等来记录众多账密,那么当您的设备丢失…

【Linux】python版本控制和环境管理

@目录1.查看目前python的版本2.添加软件源并更新3.选择你想要下载的版本4.警示:没必要设置默认版本误区千万千万不要覆盖python3软链接解决办法5.pip软件包管理最省心稍微麻烦换源网上有很多教程都是教导小白去官方下载之后编译安装。但是,小白连cmake是什么都不知道,这种教…

【WPF】WPF项目.exe可执行文件在非开发环境打不开

如题,做一个小工具,开发完之后把bin/release文件夹打包发他,但在他电脑打不开。 打开可靠性监视器: 按下 Win + S,在搜索栏中输入“控制面板”,然后点击进入。 在控制面板中选择 “系统和安全”。 然后选择 “安全与维护”。 在“安全与维护”窗口中,展开“维护”部分,…

poi的excel导出

poi的excel导出这个导出依赖于模板文件,可便捷设置表头样式。 也可以不使用模板,直接创建。1.引入poi依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version> </dependency…

postman实操

一、postman参数化 1、{{变量名}} 花括号,时两个括号在环境变量中设置变量参数,作用于所有的接口设置变量:当前所有的接口都可以调用这个参数get中设置变量: http://cms.duoceshi.cn/manage/loginJump.do?userAccount={{u1}}&loginPwd={{p1}} 二、断言 test中的内容详…

Apache SeaTunnel数据处理引擎适配的演进和规划

作者 | Chao Tian (tyrantlucifer),Apache SeaTunnel PMC Member 摘要 Apache SeaTunnel作为一个高性能数据同步工具,以其高效的数据处理能力,为数据集成领域带来了创新。在引擎上,Apache SeaTunnel除了支持自身的Zeta引擎外,还支持Spark和Flink。在2024年的CommunityOver…

读《工程师文化》

1、来源工程师文化2、解读 Mens et manus,拉丁语,意思是 “心智与双手” 或 “智慧与实践”。这句话常常被用来表达理论与实践相结合的理念,强调通过思考(心智)和实际操作(双手)共同推动知识和技术的发展。这也是MIT的校训。一个合格的工程师,必须能够自己动手解决问题…

二极管常见电路符号说明

二极管常见电路符号说明 摘要 本文详细介绍了四种特殊的二极管:TVS二极管用于瞬态电压抑制,响应速度快;肖特基二极管适用于高速电路,导通电压低;隧道二极管利用量子穿隧效应,适用于高频切换;变容二极管则作为可变电容使用,电容量可随电压改变。 二极管简介 普通的二极管…