2

为控制器生成OpenAPI注释 - 波多尔斯基

 11 months ago
source link: https://www.cnblogs.com/podolski/p/17525675.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

非常喜欢. NET 的 /// 注释,写代码的时候就顺道完成写文档的过程,简直不要太爽了。 ASP. NET CORE 也是一样的,通过 Swagger 工具,可以自动生成 API 的接口文档(OpenAPI规范),提供给前端使用,也可以用过 APIPOST/APIFOX 之类的工具提供给前端同学直接调用。

生成 OpenAPI 注释

只需要安装 swashbuckle.aspnetcore 包,在项目上设置生成 XML 格式的注释,并且如下配置即可自动生成 OpenAPI 的文档,对我这个例子,可以通过 swagger/v{version}/swagger.json 访问。

            services.AddSwaggerGen(options =>
            {
                // options.CustomSchemaIds(type => type.AssemblyQualifiedName);
                var fileName = Assembly.GetExecutingAssembly().GetName().Name + ".xml";
                var filePath = Path.Combine(AppContext.BaseDirectory, fileName);

                // integrate xml comments
                options.IncludeXmlComments(filePath);
            });


                app.UseSwagger();
                app.UseSwaggerUI(
                    options =>
                    {
                        foreach (var description in app.DescribeApiVersions())
                        {
                            var url = $"/swagger/{description.GroupName}/swagger.json";
                            var name = description.GroupName.ToUpperInvariant();
                            options.SwaggerEndpoint(url, name);
                        }
                    });

注释如下:

    /// <summary>
    /// 这个接口
    /// </summary>
    public class CoverageDataController : ODataController
	{
        /// <summary>
        /// 获取盖度数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        [HttpGet]
        [ProducesResponseType(typeof(CoverageDataDto), Status200OK)]
        public async Task<IActionResult> Get(string key, ODataQueryOptions<CoverageDataDto> options)
        {
        }
    }

生成 Tags 注释

在使用 APIFOX 导入 swagger.json 导入时,我发现,对每一个 path 的注释能够正常显示,但是对的控制器的注释不能正常被识别。

image

查看生成的 swagger.json,这个 CoverageData 被解释成了 OpenAPI 的 Tags,那对应控制器的相关注释,是需要使用另外的标注实现的,而不能直接使用///的注释实现。

paths": {
        "/api/v{version}/CoverageData({key})": {
            "get": {
                "tags": [
                    "CoverageData"
                ],
                "summary": "获取盖度数据",

安装的新的包 swashbuckle.aspnetcore.annotations,然后增加启用语句,如下:

            services.AddSwaggerGen(options =>
            {
                // options.CustomSchemaIds(type => type.AssemblyQualifiedName);
                var fileName = Assembly.GetExecutingAssembly().GetName().Name + ".xml";
                var filePath = Path.Combine(AppContext.BaseDirectory, fileName);

                // integrate xml comments
                options.IncludeXmlComments(filePath);
                options.EnableAnnotations();
            });

在控制器的声明上面,添加 [SwaggerTag("接受盖度数据")] 注解:

    /// <summary>
    /// 这个接口
    /// </summary>
    [SwaggerTag("接受盖度数据")]
    public class CoverageDataController : ODataController
	{
    }

最后生成的 swagger.json 文件在末尾多了几行:

    "tags": [
        {
            "name": "CoverageData",
            "description": "接受盖度数据"
        }
    ]

Swagger 里面就可以看到注释了:

image

但是导入到 APIFOX 中,显示的组别名称依然是 CoverageData ,没有达到我想要的效果,我想将其替换成可以显示友好的名称。实质上是为 CoverageData 取一个别名。

注:这种方法不能与 swagger 配置的 TagActionsBy 方法的一起使用。

Tags 注解

在 ASP. NET CORE 中,可以在控制器上使用 [Tags("盖度接口")],对控制器的组别进行标注。这样生成的 tag 名称直接就换成了的中文名称。

"paths": {
        "/api/v{version}/CoverageData({key})": {
            "get": {
                "tags": [
                    "盖度接口"
                ],
                "summary": "获取盖度数据",

....

    "tags": [
        {
            "name": "CoverageData",
            "description": "接受盖度数据"
        }
    ]

但是 swagger 变得非常奇怪:

image

出现了两个不同的 tag,其中 CoverageData 名称的下面没有从属的 api。

如果没有对 Tag 写 description 的要求,那么使用这个方案是最简单的:设置[Tags],不要设置[SwaggerTag]。

DisplayName 注解

这么看应该是通过 swagger 生成的 tag 与通过 [Tags] 注解生成的 tag 对象不能匹配,导致 swagger 生成的没用被引用。

查了很久资料,说这个是一个现在的 Bug,有人通过重写 DisplayName,在帖子中给了临时的解决方案

  1. 先增加一个新的类型。
/// <summary>
/// Uses the [DisplayName] attribute as the Controller name in OpenAPI spec and Swagger/ReDoc UI if available else the default Controller name.
/// </summary>
public class ControllerDocumentationConvention : IControllerModelConvention
{
    void IControllerModelConvention.Apply(ControllerModel controller)
    {
        if (controller == null)
        {
            return;
        }
        
        foreach (var attribute in controller.Attributes)
        {
            if (attribute is DisplayNameAttribute displayNameAttribute && !string.IsNullOrWhiteSpace(displayNameAttribute.DisplayName))
            {
                controller.ControllerName = displayNameAttribute.DisplayName;
            }
        }
    }
}
  1. 给 Controller 配置这个命名转换。
services.AddControllers(o =>
{
   o.Conventions.Add(new ControllerDocumentationConvention());
});
  1. 在需要调整名称的控制器上添加 [DisplayName("targetNames")] 即可。可以看到名称与注释都得到的保留,最终效果如下:

image

导入 APIFOX 也可以正常识别了。

image

本文作者:波多尔斯基

本文链接:https://www.cnblogs.com/podolski/p/17525675.html

版权声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK