我正在尝试调整自动生成的 Swagger 定义中使用的模型的“displayName”。
这只会影响 Swagger 名称,这意味着代码中的命名空间将保持不变,而从 Swagger UI 查看模型时,您会看到自定义名称。
目前,从代码返回的模型名称是一个命名空间,看起来像这样:
b.c.d.e.f
,我想向代码添加一个属性并“屏蔽”Swagger 文档的名称,以便当文档/ Swagger 定义生成,它将显示为 CustomSwaggerName
。
我有一些使用工具的 API (C#),包括
Swashbuckle
(首选)和 SwaggerGen
,但现在,如果可能的话,我只想让它在其中任何一个中工作。
我尝试使用看起来正确的属性:
[ResponseType(typeof(Company)),DisplayName("NewCompany")]
[SwaggerResponse(200,"NewCompany",typeof(object))]
没有运气。我还浏览了 SwashBuckle git 存储库,希望能找到一些东西。
我知道这可能看起来是一个奇怪的用例,但它是为我们的 AWS API Gateway 自动化编写的工具,它将使用 Swagger 定义进行一些比较。
(.net core 的帐户:)
我会将类的显示属性与自定义的 swagger 模式结合起来:
[DisplayName("NewCompany")]
public class Company
{
}
然后在启动中:
services.AddSwaggerGen(c =>
{
c.CustomSchemaIds(x => x.GetCustomAttributes<DisplayNameAttribute>().SingleOrDefault().DisplayName);
});
另请参阅这个答案
这是我的解决方案,基于@AGuyCalledGerald 提供的建议 - 谢谢!
它使用更明确的自定义属性而不是
DisplayName
,因此很清楚该属性的用途,如果该属性不存在,它将回退到默认命名策略。
助手/SwashbuckleHelpers.cs:
namespace MyProject.Helpers;
public static class SwashbuckleHelpers
{
/// <summary>
/// Direct copy of <see href="https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/SchemaGeneratorOptions.cs">Swashbuckle.AspNetCore.SwaggerGen.SchemaGeneratorOptions.DefaultSchemaIdSelector</see>.
/// </summary>
public static string DefaultSchemaIdSelector(Type modelType)
{
if (!modelType.IsConstructedGenericType) return modelType.Name.Replace("[]", "Array");
var prefix = modelType.GetGenericArguments()
.Select(genericArg => DefaultSchemaIdSelector(genericArg))
.Aggregate((previous, current) => previous + current);
return prefix + modelType.Name.Split('`').First();
}
}
属性/CustomSwaggerSchemaIdAttribute.cs
namespace MyProject.Attributes;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class CustomSwaggerSchemaIdAttribute : Attribute
{
public virtual string SchemaId { get; init; }
public CustomSwaggerSchemaIdAttribute(string schemaId)
{
SchemaId = schemaId;
}
}
程序.cs:
builder.Services.AddSwaggerGen(options =>
{
...
options.CustomSchemaIds(t => t.GetCustomAttributes<CustomSwaggerSchemaIdAttribute>().SingleOrDefault()?.SchemaId ?? SwashbuckleHelpers.DefaultSchemaIdSelector(t));
});
用法示例:
[CustomSwaggerSchemaId("Customer")]
public class CustomerDto
{
...
}
我已经使用了this解决方案并在评论中提出了建议。但 x.Name 在泛型类型的情况下返回过于冗长的名称。 Swashbuckle.Swagger 命名空间中有一个扩展方法,Swagger 默认使用该方法。我最终得到了下一个代码。
[DisplayName("NewCompany")]
public class Company
{
}
Startup.cs:
using Swashbuckle.Swagger;
services.AddSwaggerGen(c =>
{
c.SchemaId(x => x.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault()?.DisplayName ?? x.FriendlyId());
});
答案是:使用 IDocumentFilter:
private class ApplyDocumentFilter_ChangeCompany : IDocumentFilter
{
public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
{
if (swaggerDoc.definitions != null)
{
swaggerDoc.definitions.Add("Company123", swaggerDoc.definitions["Company"]);
}
if (swaggerDoc.paths != null)
{
swaggerDoc.paths["/api/Company"].get.responses["200"].schema.@ref = "#/definitions/Company123";
}
}
}
代码如下: https://github.com/heldersepu/SwashbuckleTest/commit/671ce648a7cc52290b4ad29ca540b476e65240e6
这是最终结果: http://swashbuckletest.azurewebsites.net/swagger/ui/index#!/Company/Company_Get
如果使用 NSwag,这就是我所做的:
// Program.cs
builder.Services.AddOpenApiDocument(settings =>
{
settings.SchemaSettings.SchemaNameGenerator = new PublicSchemaNameGenerator();
});
// PublicSchemaNameGenerator.cs
using System.ComponentModel;
using System.Reflection;
using NJsonSchema.Generation;
public class PublicSchemaNameGenerator : ISchemaNameGenerator
{
public string Generate(Type type)
{
var attribute = type.GetCustomAttributes<DisplayNameAttribute>().FirstOrDefault();
if (attribute is null)
{
return type.Name;
}
return attribute.DisplayName;
}
}
现在您可以在想要使用此名称的类型上添加属性
DisplayName("SomeName")
。
// SomeType.cs
using System.ComponentModel;
[DisplayName("Product")]
public class SomeType
{
}