翼度科技»论坛 编程开发 .net 查看内容

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

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
前言

当前.NET环境下,生成WebApi代理类的工具已经有很多选择了,比如OpenApi Generator,NSwag和Refitter等,不同的工具生成的代码风格以及实现方式略有不同,比如Refitter生成的客户端是Refit风格.
本人比较喜欢Refit风格的标注风格因此还是比较喜欢使用Refitter的,TA生成的代码风格如下:
  1. [Headers("Accept: application/json")]
  2. [Get("/pet/{petId}")]
  3. 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:
  1. dotnet tool install --global Microsoft.OpenApi.Kiota
复制代码

命令行生成代理

接下来我们随意创建一个NET8的MinimalApi项目,然后我们以Petshop3的Api为例,为了加快速度我们将接口Scheme文件下载到项目文件夹下:
文档地址为: https://petstore3.swagger.io/api/v3/openapi.json
当然了你也可以使用自己的WebApi;Schema文件下载完成后 我们使用命令行工具定位到对应的文件夹,然后键入如下命令:
  1. kiota generate -l CSharp -o output -d petstore.json -n PetShops.V3
复制代码
这里解释一下参数:

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


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

接下来我们引用Kiota必须的几个类库:
  1. [/code]这里假设PetShop的接口需要简单验证才能访问:
  2. 我们首先定义一个名为SimpleAuthenticationProvider的类,该类实现了IAuthenticationProvider接口,代码如下:
  3. [code]internal class SimpleAuthenticationProvider(string baseUrl, string? userName, string? password) : IAuthenticationProvider
  4. {
  5.     public async Task AuthenticateRequestAsync(
  6.         RequestInformation request,
  7.         Dictionary<string, object>? additionalAuthenticationContext = null,
  8.         CancellationToken cancellationToken = default)
  9.     {
  10.         using var httpClient = new HttpClient()
  11.         {
  12.             BaseAddress = new Uri(baseUrl)
  13.         };
  14.         httpClient.DefaultRequestHeaders.Accept.Add(
  15.             new MediaTypeWithQualityHeaderValue("application/xml"));
  16.         var authRequest = await httpClient.GetAsync(
  17.             $"v3/user/login?username={userName}&password={password}", cancellationToken);
  18.         if (!authRequest.IsSuccessStatusCode)
  19.         {
  20.             throw new Exception("Authentication failed");
  21.         }
  22.         var session = await authRequest.Content.ReadAsStringAsync(cancellationToken);
  23.         Console.WriteLine($"session: {session}");
  24.         await Task.CompletedTask;
  25.         //todo:
  26.     }
  27. }
复制代码
上面的代码很简单就是模拟一个登录,然后后面的请求就存在了session即可进行后续的接口调用,如果有些认证是JWT之内的这里可以把得到的Token传入到后续的Header中,当然认证请求务必缓存起来,不用每个接口调用都请求一次!
MS默认帮我们实现了AnonymousAuthenticationProvider和BaseBearerTokenAuthenticationProvider两个认证Provider.
以下是简单的调用接口:
  1. //分别调用条件查询Pet,以及根据Id查询指定的Pet
  2. app.MapGet("/test", async () =>
  3. {
  4.     var baseUrl = "https://petstore3.swagger.io/api/v3";
  5.     var userName = "万雅虎";
  6.     var password = "12345";
  7.     var adaptor = new HttpClientRequestAdapter(
  8.         new SimpleAuthenticationProvider(baseUrl, userName, password))
  9.     {
  10.         BaseUrl = baseUrl
  11.     };
  12.     var api = new ApiClient(adaptor);
  13.     var pets = await api.Pet.FindByStatus.GetAsync(x =>
  14.     {
  15.         x.QueryParameters.StatusAsGetStatusQueryParameterType =
  16.         PetShops.V3.Pet.FindByStatus.GetStatusQueryParameterType.Sold;
  17.     });
  18.     var pet = await api.Pet[1].GetAsync();
  19.     return new { Pets = pets, Pet = pet };
  20. });
复制代码
不出意外请求成功了:

注入ApiClient

当然上面的调用代码显得有一些粗糙,实际上大多数开发代码会使用到DI,
我们使用MS提供的示例代码扩展一下IServiceCollection和IHttpClientBuilder
  1. using Microsoft.Kiota.Http.HttpClientLibrary;
  2. /// <summary>
  3. /// Service collection extensions for Kiota handlers.
  4. /// </summary>
  5. public static class KiotaServiceCollectionExtensions
  6. {
  7.     /// <summary>
  8.     /// Adds the Kiota handlers to the service collection.
  9.     /// </summary>
  10.     /// <param name="services"><see cref="IServiceCollection"/> to add the services to</param>
  11.     /// <returns><see cref="IServiceCollection"/> as per convention</returns>
  12.     /// <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>
  13.     public static IServiceCollection AddKiotaHandlers(this IServiceCollection services)
  14.     {
  15.         // Dynamically load the Kiota handlers from the Client Factory
  16.         var kiotaHandlers = KiotaClientFactory.GetDefaultHandlerTypes();
  17.         // And register them in the DI container
  18.         foreach(var handler in kiotaHandlers)
  19.         {
  20.             services.AddTransient(handler);
  21.         }
  22.         return services;
  23.     }
  24.     /// <summary>
  25.     /// Adds the Kiota handlers to the http client builder.
  26.     /// </summary>
  27.     /// <param name="builder"></param>
  28.     /// <returns></returns>
  29.     /// <remarks>
  30.     /// Requires the handlers to be registered in DI by <see cref="AddKiotaHandlers(IServiceCollection)"/>.
  31.     /// The order in which the handlers are added is important, as it defines the order in which they will be executed.
  32.     /// </remarks>
  33.     public static IHttpClientBuilder AttachKiotaHandlers(this IHttpClientBuilder builder)
  34.     {
  35.         // Dynamically load the Kiota handlers from the Client Factory
  36.         var kiotaHandlers = KiotaClientFactory.GetDefaultHandlerTypes();
  37.         // And attach them to the http client builder
  38.         foreach(var handler in kiotaHandlers)
  39.         {
  40.             builder.AddHttpMessageHandler((sp) => (DelegatingHandler)sp.GetRequiredService(handler));
  41.         }
  42.         return builder;
  43.     }
  44. }
复制代码
然后实现一个Api的ClientFactory:
  1. //这里是伪代码,因为认证需要根据Api按需实现,比如这里是匿名请求
  2. public class PetShopClientFactory
  3. {
  4.     private readonly IAuthenticationProvider _authenticationProvider;
  5.     private readonly HttpClient _httpClient;
  6.     public PetShopClientFactory(HttpClient httpClient)
  7.     {
  8.         _authenticationProvider = new AnonymousAuthenticationProvider();
  9.         _httpClient = httpClient;
  10.     }
  11.     public ApiClient GetClient() {
  12.       return new ApiClient(new HttpClientRequestAdapter(_authenticationProvider, httpClient: _httpClient));
  13.     }
  14. }
复制代码
然后在服务注册中添加如下代码:
  1. // ----------- Add this part to register the generated client -----------
  2. // Add Kiota handlers to the dependency injection container
  3. builder.Services.AddKiotaHandlers();
  4. // Register the factory for the PetShop client
  5. builder.Services.AddHttpClient<PetShopClientFactory>((sp, client) => {
  6.     // Set the base address and accept header
  7.     // or other settings on the http client
  8.     client.BaseAddress = new Uri("https://petstore3.swagger.io/api/v3");
  9.     client.DefaultRequestHeaders.Add("Accept", "application/json");
  10. }).AttachKiotaHandlers(); // Attach the Kiota handlers to the http client, this is to enable all the Kiota features.
  11. // Register the PetShop client
  12. builder.Services.AddTransient(sp => sp.GetRequiredService<PetShopClientFactory>().GetClient());
  13. // ----------- Add this part to register the generated client end -------
复制代码
最后我们在使用的地方注入ApiClient即可!
总结

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

来源:https://www.cnblogs.com/vipwan/p/18372027
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具