Swashbuckle 是不是支持将自定义操作标签表示为 UI 中的徽章的方法?

Posted

技术标签:

【中文标题】Swashbuckle 是不是支持将自定义操作标签表示为 UI 中的徽章的方法?【英文标题】:Does Swashbuckle support a way to represent custom operation tags as badges in the UI?Swashbuckle 是否支持将自定义操作标签表示为 UI 中的徽章的方法? 【发布时间】:2020-12-23 10:43:41 【问题描述】:

我正在开发一个 ASP.NET Core 应用程序,并且我想将一些端点标记为“开发人员工具”,这表明这些端点的存在纯粹是为了开发团队采取调查/纠正措施的利益,并且是不适合第三方消费。像这样的:

我检查了 Swashbuckle 存储库,找不到任何表明它受支持的信息,但我认为最好检查一下。

【问题讨论】:

作为建议,您可以使用分组标签对Developer Tools API 进行分组:idratherbewriting.com/learnapidoc/… @MehdiKhademloo 这是真的,但我想保留它现在拥有的分组(由控制器) - 换句话说,只是为了表明一个端点是由开发团队使用而不是影响关于它的任何其他内容。 【参考方案1】:

由于似乎没有内置的方法来做到这一点,我设法通过一种非常 hacky(但有效)的方法来实现这个结果,即使用操作过滤器以特定格式将文本附加到操作摘要然后注入自定义 CS/JSS,将摘要描述的这些部分转换为 DOM 中的自定义元素。

首先我定义一个自定义属性:

/// <summary>
/// Indicates that this operation is intended for use solely by the development team.
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class DeveloperToolAttribute : Attribute


然后我创建一个操作过滤器来处理这些:

public class DeveloperToolOperationFilter : IOperationFilter

    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    
        if (!context.ApiDescription.CustomAttributes().Any(x => x is DeveloperToolAttribute))
            return;

        operation.Summary = $"[Developer Tool] operation.Summary";
    

我在其他根据 XML 文档设置操作摘要的过滤器之后注册了这个过滤器:

services.AddSwaggerGen(options =>

    // ...

    void AddXmlDocumentation(Assembly assembly)
    
        var xmlFile = $"assembly.GetName().Name.xml";
        var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
        options.IncludeXmlComments(xmlPath, includeControllerXmlComments: true);
    

    // Set the comments path for the Swagger JSON and UI.
    AddXmlDocumentation(Assembly.GetExecutingAssembly());
    AddXmlDocumentation(typeof(StatementReadModel).Assembly);
    // ...
    options.OperationFilter<DeveloperToolOperationFilter>();
);

这样我就可以用 [DeveloperTool] 注释我的 API 方法,并将其作为操作摘要的一部分:

[HttpGet]
[DeveloperTool]
public async Task<CommissionAuthorisationsReadModel> GetAuthorisations()

    var result = await _mediator.Send(CommissionAuthorisationsQuery.Instance);

    return result;

接下来,我使用 TamperMonkey 构建了一个用户脚本,它允许我遍历包含这些操作摘要的所有 DOM 元素,并将大括号内的任何文本(例如 [Developer Tool])转换为标记。

这使我可以生成以下 javascript 文件,并将其保存为 wwwroot/ext/custom-swagger-javascript.js

var callback = function() 
    var elements = document.getElementsByClassName("opblock-summary-description");

    for (const summaryDescription of elements) 
        const match = summaryDescription.textContent.match(/\[(\w|\s)+\]\s/);
    
        if (!match) 
            continue;
        

        const trimmedTextContent = summaryDescription.textContent.replaceAll(match[0], "");
        summaryDescription.textContent = trimmedTextContent;

        const customTag = match[0].substring(1, match[0].length - 2);
        const summary = summaryDescription.parentElement;
        const customTagElement = document.createElement("div");

        customTagElement.innerText = customTag;
        customTagElement.className = "opblock-custom-tag";
        summary.appendChild(customTagElement);
    
;

// Repeat just in case page is slow to load.
for (let attempts = 1; attempts <= 5; attempts++) 
    setTimeout(callback, attempts * 200);

除此之外,我还创建了一个 CSS 样式表,保存为 wwwroot/ext/custom-swagger-stylesheet.css

.opblock-custom-tag 
    font-size: 10px;
    font-weight: 700;
    min-width: 80px;
    padding: 6px 15px;
    text-align: center;
    border-radius: 3px;
    background: #9d45d4;
    text-shadow: 0 1px 0 rgba(0,0,0,.1);
    font-family: sans-serif;
    color: #fff;

在 Startup 中,我确保将注入这些 Javascript 和 CSS 文件:

app.UseSwaggerUI(c =>

    // ...
    
    c.InjectStylesheet("/ext/custom-swagger-stylesheet.css");
    c.InjectJavascript("/ext/custom-swagger-javascript.js");
);

这还要求我确保 ASP.NET Core 可以提供静态文件:

app.UseHttpsRedirection();
app.UseStaticFiles(); // Added this
app.UseRouting();

最后这一切让我得到了我想要的结果:

【讨论】:

以上是关于Swashbuckle 是不是支持将自定义操作标签表示为 UI 中的徽章的方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Swashbuckle 的 SwaggerUI 显示静态 swagger.json 文件而不是 SwaggerGen 的动态创建的定义?

动作必须是普通对象。将自定义中间件用于测试库而不是应用程序上的异步操作

是否可以将自定义元数据标签添加到音乐文件?

将自定义标签添加到材料范围滑块

将自定义html添加到django中的choicefield标签

将自定义标签注入 Java 客户端的默认 jmx Prometheus 指标