【发布时间】:2021-03-24 10:50:41
【问题描述】:
我为我的公共 api 生成了一个 swagger.json 文件。使用以下代码效果非常好:
在启动中 - 配置服务
//Register Swagger Options as Dependency Injection
services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
services.AddSwaggerGen(options =>
{
// add a custom operation filter which sets default values
//options.OperationFilter<SwaggerDefaultValues>();
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath);
});
在启动中 - 配置
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.InjectStylesheet("../css/customize-swagger-ui.css");
c.InjectJavascript("../js/customize-swagger-ui.js");
// build a swagger endpoint for each discovered API version
foreach (var description in provider.ApiVersionDescriptions)
{
c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant());
}
});
我的问题是,我想在 API-Request 后面添加方法的名称。否则,用于客户端代码生成的 NSWAG 等工具会创建许多不同的方法,称为 APIRoute1、APIRoute2、APIRoute3...
这里是swagger生成文件的json-sn-p:
"paths": {
"/api/v1/Order": {
"post": {
"tags": [
"Order"
],
"summary": "Creates a new Order if no order currently exists",
"requestBody": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateOrderModel"
}
},
"text/json": {
"schema": {
"$ref": "#/components/schemas/CreateOrderModel"
}
},
"application/*+json": {
"schema": {
"$ref": "#/components/schemas/CreateOrderModel"
}
}
}
},
"responses": {
"200": {
"description": "Success"
}
}
}
},
"/api/v1/Order/{orderNumber}": {
"get": {
"tags": [
"Order"
],
"summary": "Reads a given Order if exists",
"parameters": [
{
"name": "orderNumber",
"in": "path",
"description": "Order Number",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OrderDTO"
}
}
}
},
"400": {
"description": "Bad Request",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
},
"404": {
"description": "Not Found",
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
APIRoute 只是一个占位符作为示例。 APIRouteX 后面的方法使用相同的路由实现,但 http 变量不同,例如(POST、DELETE、PUT)。所以真的很难阅读客户端代码生成的代码。
是否可以在swagger.json文件的路由后面加上“Method-Name”?
SWAGGER 配置选项
/// <summary>
/// Configures the Swagger Options like Titel, Contact Informations etc
/// </summary>
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
{
readonly IApiVersionDescriptionProvider provider;
/// <summary>
/// Constructor which adds ApiVersionDescription by Dependency Injection
/// </summary>
/// <param name="provider">API Version Description Provider</param>
public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) => this.provider = provider;
/// <summary>
/// Adds a seperate Swagger Document for each API Version
/// </summary>
/// <param name="options">Swagger Generic Options</param>
public void Configure(SwaggerGenOptions options)
{
foreach (var description in provider.ApiVersionDescriptions)
{
options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description.ApiVersion.ToString(), description.IsDeprecated));
}
}
/// <summary>
/// Creates Header Informations for API
/// </summary>
/// <param name="description">ApiVersionDescription</param>
/// <returns>Api Info</returns>
static OpenApiInfo CreateInfoForApiVersion(string version, bool isDeprecated)
{
var info = new OpenApiInfo()
{
Title = "Rüstkontrolle API",
Version = version,
Description = "Service Dokumentation für das AddOn Rüstkontrolle im SICK Werkerportal",
Contact = new OpenApiContact() { Name = "Lukas Adler", Email = "lukas.adler@sick.de" },
License = new OpenApiLicense() { Name = "",}
};
if (isDeprecated)
{
info.Description += "API version is deprecated.";
}
return info;
}
}
Swagger 默认值
/// <summary>
/// Swagger Operation Filter
/// </summary>
public class SwaggerDefaultValues : IOperationFilter
{
/// <summary>
/// Applies Operations and OperationsFilterContext on API Descriptions
/// </summary>
/// <param name="operation">Operation</param>
/// <param name="context">OperationFilterContext</param>
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var apiDescription = context.ApiDescription;
if (operation.Parameters == null)
{
return;
}
foreach (var parameter in operation.Parameters)
{
var description = apiDescription.ParameterDescriptions.First(p => p.Name == parameter.Name);
if (parameter.Description == null)
{
parameter.Description = description.ModelMetadata?.Description;
}
parameter.Required |= description.IsRequired;
}
}
}
NSWAG 配置
{
"runtime": "NetCore21",
"defaultVariables": null,
"documentGenerator": {
"fromDocument": "HERE IS NORMALLY MY API DESCRIPTION",
"url": "https://localhost:44314/swagger/v1/swagger.json",
"output": null,
"newLineBehavior": "Auto"
}
},
"codeGenerators": {
"openApiToCSharpClient": {
"clientBaseClass": null,
"configurationClass": null,
"generateClientClasses": true,
"generateClientInterfaces": false,
"clientBaseInterface": null,
"injectHttpClient": true,
"disposeHttpClient": true,
"protectedMethods": [],
"generateExceptionClasses": true,
"exceptionClass": "ApiException",
"wrapDtoExceptions": true,
"useHttpClientCreationMethod": false,
"httpClientType": "System.Net.Http.HttpClient",
"useHttpRequestMessageCreationMethod": false,
"useBaseUrl": true,
"generateBaseUrlProperty": true,
"generateSyncMethods": false,
"generatePrepareRequestAndProcessResponseAsAsyncMethods": false,
"exposeJsonSerializerSettings": false,
"clientClassAccessModifier": "public",
"typeAccessModifier": "public",
"generateContractsOutput": false,
"contractsNamespace": null,
"contractsOutputFilePath": null,
"parameterDateTimeFormat": "s",
"parameterDateFormat": "yyyy-MM-dd",
"generateUpdateJsonSerializerSettingsMethod": true,
"useRequestAndResponseSerializationSettings": false,
"serializeTypeInformation": false,
"queryNullValue": "",
"className": "{controller}Client",
"operationGenerationMode": "MultipleClientsFromOperationId",
"additionalNamespaceUsages": [],
"additionalContractNamespaceUsages": [],
"generateOptionalParameters": false,
"generateJsonMethods": false,
"enforceFlagEnums": false,
"parameterArrayType": "System.Collections.Generic.IEnumerable",
"parameterDictionaryType": "System.Collections.Generic.IDictionary",
"responseArrayType": "System.Collections.Generic.ICollection",
"responseDictionaryType": "System.Collections.Generic.IDictionary",
"wrapResponses": false,
"wrapResponseMethods": [],
"generateResponseClasses": true,
"responseClass": "SwaggerResponse",
"namespace": "MyNamespace",
"requiredPropertiesMustBeDefined": true,
"dateType": "System.DateTimeOffset",
"jsonConverters": null,
"anyType": "object",
"dateTimeType": "System.DateTimeOffset",
"timeType": "System.TimeSpan",
"timeSpanType": "System.TimeSpan",
"arrayType": "System.Collections.Generic.ICollection",
"arrayInstanceType": "System.Collections.ObjectModel.Collection",
"dictionaryType": "System.Collections.Generic.IDictionary",
"dictionaryInstanceType": "System.Collections.Generic.Dictionary",
"arrayBaseType": "System.Collections.ObjectModel.Collection",
"dictionaryBaseType": "System.Collections.Generic.Dictionary",
"classStyle": "Poco",
"jsonLibrary": "NewtonsoftJson",
"generateDefaultValues": true,
"generateDataAnnotations": true,
"excludedTypeNames": [],
"excludedParameterNames": [],
"handleReferences": false,
"generateImmutableArrayProperties": false,
"generateImmutableDictionaryProperties": false,
"jsonSerializerSettingsTransformationMethod": null,
"inlineNamedArrays": false,
"inlineNamedDictionaries": false,
"inlineNamedTuples": true,
"inlineNamedAny": false,
"generateDtoTypes": true,
"generateOptionalPropertiesAsNullable": false,
"generateNullableReferenceTypes": false,
"templateDirectory": null,
"typeNameGeneratorType": null,
"propertyNameGeneratorType": null,
"enumNameGeneratorType": null,
"serviceHost": null,
"serviceSchemes": null,
"output": null,
"newLineBehavior": "Auto"
}
}
}
【问题讨论】:
-
通常,NSwag 使用路由来生成方法的名称。在您的情况下,两种方法
Order具有不同的参数。你能分享你的 NSwag 配置吗? -
@vernou 我已经添加了所需的信息。在实现中,两种排序方法具有不同的名称,例如“createOrder”和“readOrder”
-
我不清楚。你能分享一下 NSwag(客户端代码生成)设置吗?
-
@vernou 请再看看:)