.NET9における異なるOpenAPI


.NET9の第4プレビュー版で、MicrosoftはOpenAPIを導入しました。これを使用するには`Microsoft.AspNetCore.OpenApi`を参照する必要があります。ローカルのAPI記述ファイルを生成したい場合は、`Microsoft.Extensions.ApiDescription.Server`を参照する必要があります。

以下はプロジェクトファイルです：

```xml
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0-preview.4.24267.6" />
    <PackageReference Include="Microsoft.Extensions.ApiDescription.Server" Version="9.0.0-preview.4.24267.6">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

  <PropertyGroup>
    <OpenApiDocumentsDirectory>$(MSBuildProjectDirectory)</OpenApiDocumentsDirectory>
    <OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>
  </PropertyGroup>

</Project>
```

OpenApiを使用するには、`Services.AddOpenApi()`と`app.MapOpenApi()`を使用するだけです。また、`AddOpenApi`の`Action`パラメーターを通じて、APIの設定情報を変更または完全にすることができます。以下のようなコードです：

```cs
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging.Configuration;
using Microsoft.OpenApi.Extensions;
using Microsoft.OpenApi.Interfaces;
using Microsoft.OpenApi.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOpenApi("myapi", opt =>
{
    opt.UseTransformer((oper, context, c) =>
    {
        oper.Info = new OpenApiInfo
        {
            Version = "v1",
            Title = "My API",
            Description = "My API Description",
            Contact = new OpenApiContact
            {
                Name = "My Name",
                Email = "aaa@aa.com"
            },
            License = new OpenApiLicense
            {
                Name = "MIT",
                Url = new Uri("https://opensource.org/licenses/MIT")
            },
            TermsOfService = new Uri("https://www.google.com"),
        };
        return Task.CompletedTask;
    });
    opt.ShouldInclude = (o) =>
    {
        Console.WriteLine("-----HttpMethod------" + o.HttpMethod);
        Console.WriteLine("-----GroupName------" + o.GroupName);
        Console.WriteLine("------RelativePath-----" + o.RelativePath);
        Console.WriteLine("------ActionDescriptor-----" + o.ActionDescriptor.DisplayName);
        return true;
    };
    opt.UseOperationTransformer((oper, context, c) =>
    {
        Console.WriteLine("======summary=======" + oper.Summary);
        oper.Summary = "gui su wei test summary";
        oper.Tags = new OpenApiTag[]
        {
            new OpenApiTag
            {
                Name = "tag1", Description = "tag1 description",
            },
            new OpenApiTag
            {
                Name = "tag2", Description = "tag2 description",
            }
        };
        return Task.CompletedTask;
    });
});

var app = builder.Build();
app.MapOpenApi("/openapi/{documentName}.json");
app.MapGet("/order", () =>
{
    return new Order()
    {
        OrderNo = "20210901",
        Amount = 100,
        OrderDate = DateTime.Now
    };
});
app.MapPost("/order", (Order order) =>
{
    return new OkResult();
});
app.Run();

/// <summary>
/// 注文
/// </summary>
public class Order
{
    /// <summary>
    /// 注文番号
    /// </summary>
    public string OrderNo { get; set; }
    /// <summary>
    /// 注文金額
    /// </summary>
    public decimal Amount { get; set; }
    /// <summary>
    /// 注文日
    /// </summary>
    public DateTime OrderDate { get; set; }
}
```

以下は実行結果です：

![画像](https://mmbiz.qpic.cn/sz_mmbiz_png/4CAA63nvHRDQwic8x5UIU5PiceqURicqYkn6dxSfX0wQmNDMfW7JoSbt9rFF36iaN5G24ibf7hEaHnvNaq29zDdMLLQ/640?wx_fmt=png&from=appmsg)

http://localhost:5287/openapi/myapi.jsonにアクセスして、APIのjson情報を見ることができます。また、APIファイルの生成が設定されているため、生成されたapi.jsonファイルも確認できます。結果は以下の通りです：

```json
{
  "openapi": "3.0.1",
  "info": {
    "title": "My API",
    "description": "My API Description",
    "termsOfService": "https://www.google.com",
    "contact": {
      "name": "My Name",
      "email": "aaa@aa.com"
    },
    "license": {
      "name": "MIT",
      "url": "https://opensource.org/licenses/MIT"
    },
    "version": "v1"
  },
  "paths": {
    "/order": {
      "get": {
        "tags": [
          "tag1",
          "tag2"
        ],
        "summary": "gui su wei test summary",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "orderNo": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "number",
                      "format": "double"
                    },
                    "orderDate": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          }
        },
        "x-aspnetcore-id": "e8ba784f-bc44-4d62-9132-2e0ec46472ea"
      },
      "post": {
        "tags": [
          "tag1",
          "tag2"
        ],
        "summary": "gui su wei test summary",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "orderNo": {
                    "type": "string"
                  },
                  "amount": {
                    "type": "number",
                    "format": "double"
                  },
                  "orderDate": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "statusCode": {
                      "type": "integer",
                      "format": "int32"
                    }
                  }
                }
              }
            }
          }
        },
        "x-aspnetcore-id": "ddb8949d-07dc-414a-99b0-a298aab0ecb8"
      }
    }
  },
  "tags": [
    {
      "name": "OpenAPIDemo"
    }
  ]
}
```

(Translated by GPT)

元のリンク：https://mp.weixin.qq.com/s?__biz=MzA3NDM1MzIyMQ==&mid=2247488158&idx=1&sn=c85638fcd7f78584eca4755c9d8ba20d&chksm=9f004db4a877c4a2fcac764ad98a5c6a01fe83220c53205e1adebcdde16a17fc6bd465300895&token=1053798272&lang=zh_CN#rd&wt.mc_id=MVP_325642