[英]Does Swashbuckle support a way to represent custom operation tags as badges in the UI?
I'm developing an ASP.NET Core application and there are some endpoints that I want to tag as "developer tool", indicating that these endpoints exist purely for the benefit of the development team to take investigative/corrective action and are not intended for third-party consumption.我正在开发一个 ASP.NET 核心应用程序,并且有一些端点我想标记为“开发人员工具”,这表明这些端点的存在纯粹是为了开发团队采取调查/纠正措施的利益,而不是用于第三方-聚会消费。 Something like this:
像这样的东西:
I've checked the Swashbuckle repo and can't find anything to suggest this is supported, but I thought it's best to check.我检查了 Swashbuckle 存储库,找不到任何表明支持此功能的信息,但我认为最好检查一下。
Since there doesn't seem to be built-in way to do this, I managed to achieve this result through a pretty hacky (but effective) approach of using an operation filter to append text to the operation summary in a particular format and then injecting custom CS/JSS that converts these parts of the summary description into custom elements in the DOM.由于似乎没有内置的方法来做到这一点,我设法通过一种非常hacky(但有效)的方法来实现这个结果,即使用操作过滤器将 append 文本以特定格式添加到操作摘要中,然后注入自定义 CS/JSS 将摘要描述的这些部分转换为 DOM 中的自定义元素。
First I define a custom attribute:首先我定义一个自定义属性:
/// <summary>
/// Indicates that this operation is intended for use solely by the development team.
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
public class DeveloperToolAttribute : Attribute
{
}
Then I create an operation filter to process these:然后我创建一个操作过滤器来处理这些:
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}";
}
}
I register this filter after the other filters that set the operation summary based on the XML documentation:我在其他根据 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>();
});
This would then make it so that I could annotate my API methods with [DeveloperTool]
and have that become part of the operation summary:这样我就可以使用
[DeveloperTool]
注释我的 API 方法,并将其作为操作摘要的一部分:
[HttpGet]
[DeveloperTool]
public async Task<CommissionAuthorisationsReadModel> GetAuthorisations()
{
var result = await _mediator.Send(CommissionAuthorisationsQuery.Instance);
return result;
}
Next up I used TamperMonkey to build a userscript that allowed me to iterate through all the DOM elements containing these operation summaries and transform any text within braces (such as [Developer Tool]
) into badges.接下来,我使用 TamperMonkey 构建了一个用户脚本,它允许我遍历包含这些操作摘要的所有 DOM 元素,并将大括号中的任何文本(例如
[Developer Tool]
)转换为徽章。
This allowed me to produce the following Javascript file which I saved as wwwroot/ext/custom-swagger-javascript.js
:这使我能够生成以下 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);
}
Alongside this I created a CSS stylesheet saved as wwwroot/ext/custom-swagger-stylesheet.css
:除此之外,我创建了一个 CSS 样式表,保存为
wwwroot/ext/custom-swagger-stylesheet.css
8CBA22E28EB17B5F5C6AE2A266AZ :
.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;
}
In Startup, I ensured that these Javascript and CSS files would be injected:在启动中,我确保将注入这些 Javascript 和 CSS 文件:
app.UseSwaggerUI(c =>
{
// ...
c.InjectStylesheet("/ext/custom-swagger-stylesheet.css");
c.InjectJavascript("/ext/custom-swagger-javascript.js");
});
This also required me to ensure that ASP.NET Core would serve static files:这还要求我确保 ASP.NET 内核可以为 static 文件提供服务:
app.UseHttpsRedirection();
app.UseStaticFiles(); // Added this
app.UseRouting();
Finally this all allowed me to get the result that I wanted:最后,这一切都让我得到了我想要的结果:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.