我正在使用清洁架构解决方案建立一个新的API:https://github.com/jasontaylordev/CleanArchitecture
如果我们将重点放在API的返回类型上。
1- 200 -此API规范是生成精细的(基于在控制器中的动作的返回类型)
例如对于get/TodoItems
"/api/TodoItems": {
"get": {
"tags": [
"TodoItems"
],
"operationId": "TodoItems_GetTodoItemsWithPagination",
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PaginatedListOfTodoItemBriefDto"
}
}
}
}
},
]
},然后我们在ApiExceptionFilterAttribute文件夹WebUI/Filters/中处理了几个异常
_exceptionHandlers = new Dictionary<Type, Action<ExceptionContext>>
{
{ typeof(ValidationException), HandleValidationException },
{ typeof(NotFoundException), HandleNotFoundException },
{ typeof(UnauthorizedAccessException), HandleUnauthorizedAccessException },
{ typeof(ForbiddenAccessException), HandleForbiddenAccessException },
};typeof(ValidationException)用于Http状态代码400
typeof(NotFoundException)用于Http状态代码404
typeof(UnauthorizedAccessException)用于Http状态代码401
typeof(ForbiddenAccessException)用于Http状态代码403
现在,要将这些填充到swagger.json文件中,我们需要用以下方法来修饰每个控制器操作。
[ProducesResponseType(typeof(ValidationException), 400)]
[ProducesResponseType(typeof(UnauthorizedAccessException), 401)]
[ProducesResponseType(typeof(NotFoundException), 404)]
[ProducesResponseType(typeof(ForbiddenAccessException), 403)]为了避免这种情况,我考虑使用来自NSwag的NSwag接口。但是,我在为返回的类型生成架构时遇到了问题。
public class CustomResponseTypesOperationProcessor : IOperationProcessor
{
public bool Process(OperationProcessorContext context)
{
var schema = context.SchemaGenerator.Generate(typeof(ValidationException));
context.OperationDescription.Operation.Responses.Add("400", new OpenApiResponse { Description = "An error occurs or a business rule fails.", Schema = schema });
return true;
}
}在ConfigureServices中
services.AddOpenApiDocument(configure =>
{
...
configure.OperationProcessors.Add(new CustomResponseTypesOperationProcessor());
});但是,当我构建项目时(它应该在构建时生成swagger.json和TS客户端,我得到以下错误)
System.InvalidOperationException: Could not resolve the path '#/paths//api/TodoItems/get/responses/400/content/application/json/schema/definitions/Exception'.
1> at NJsonSchema.JsonReferenceResolver.ResolveDocumentReference(Object rootObject, String jsonPath, Type targetType, IContractResolver contractResolver)
1> at NJsonSchema.JsonReferenceResolver.ResolveReferenceAsync(Object rootObject, String jsonPath, Type targetType, IContractResolver contractResolver, Boolean append, CancellationToken cancellationToken)
1> at NJsonSchema.JsonReferenceResolver.ResolveReferenceAsync(Object rootObject, String jsonPath, Type targetType, IContractResolver contractResolver, CancellationToken cancellationToken)
1> at NJsonSchema.JsonSchemaReferenceUtilities.JsonReferenceUpdater.VisitJsonReferenceAsync(IJsonReference reference, String path, String typeNameHint, CancellationToken cancellationToken)
1> at NJsonSchema.Visitors.AsyncJsonReferenceVisitorBase.VisitAsync(Object obj, String path, String typeNameHint, ISet`1 checkedObjects, Action`1 replacer, CancellationToken cancellationToken)
1> at NJsonSchema.Visitors.AsyncJsonReferenceVisitorBase.VisitAsync(Object obj, String path, String typeNameHint, ISet`1 checkedObjects, Action`1 replacer, CancellationToken cancellationToken)
1> at NJsonSchema.Visitors.AsyncJsonReferenceVisitorBase.VisitAsync(Object obj, String path, String typeNameHint, ISet`1 checkedObjects, Action`1 replacer, CancellationToken cancellationToken)
1> at NJsonSchema.Visitors.AsyncJsonReferenceVisitorBase.VisitAsync(Object obj, String path, String typeNameHint, ISet`1 checkedObjects, Action`1 replacer, CancellationToken cancellationToken)
1> at NJsonSchema.Visitors.AsyncJsonReferenceVisitorBase.VisitAsync(Object obj, String path, String typeNameHint, ISet`1 checkedObjects, Action`1 replacer, CancellationToken cancellationToken)
1> at NJsonSchema.Visitors.AsyncJsonReferenceVisitorBase.VisitAsync(Object obj, String path, String typeNameHint, ISet`1 checkedObjects, Action`1 replacer, CancellationToken cancellationToken)
1> at NJsonSchema.Visitors.AsyncJsonReferenceVisitorBase.VisitAsync(Object obj, String path, String typeNameHint, ISet`1 checkedObjects, Action`1 replacer, CancellationToken cancellationToken)
1> at NJsonSchema.Visitors.AsyncJsonReferenceVisitorBase.VisitAsync(Object obj, String path, String typeNameHint, ISet`1 checkedObjects, Action`1 replacer, CancellationToken cancellationToken)
1> at NJsonSchema.Visitors.AsyncJsonReferenceVisitorBase.VisitAsync(Object obj, String path, String typeNameHint, ISet`1 checkedObjects, Action`1 replacer, CancellationToken cancellationToken)
1> at NJsonSchema.Visitors.AsyncJsonReferenceVisitorBase.VisitAsync(Object obj, String path, String typeNameHint, ISet`1 checkedObjects, Action`1 replacer, CancellationToken cancellationToken)
1> at NJsonSchema.Visitors.AsyncJsonReferenceVisitorBase.VisitAsync(Object obj, CancellationToken cancellationToken)
1> at NJsonSchema.JsonSchemaReferenceUtilities.JsonReferenceUpdater.VisitAsync(Object obj, CancellationToken cancellationToken)
1> at NJsonSchema.JsonSchemaReferenceUtilities.UpdateSchemaReferencesAsync(Object rootObject, JsonReferenceResolver referenceResolver, IContractResolver contractResolver, CancellationToken cancellationToken)
1> at NJsonSchema.Infrastructure.JsonSchemaSerialization.FromJsonWithLoaderAsync[T](Func`1 loader, SchemaType schemaType, String documentPath, Func`2 referenceResolverFactory, IContractResolver contractResolver, CancellationToken cancellationToken)
1> at NSwag.OpenApiDocument.FromJsonAsync(String data, String documentPath, SchemaType expectedSchemaType, Func`2 referenceResolverFactory, CancellationToken cancellationToken) in /_/src/NSwag.Core/OpenApiDocument.cs:line 203
1> at NSwag.Commands.Generation.AspNetCore.AspNetCoreToSwaggerCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in /_/src/NSwag.Commands/Commands/Generation/AspNetCore/AspNetCoreToOpenApiCommand.cs:line 239
1> at NSwag.Commands.NSwagDocumentBase.GenerateSwaggerDocumentAsync() in /_/src/NSwag.Commands/NSwagDocumentBase.cs:line 275
1> at NSwag.Commands.NSwagDocument.ExecuteAsync() in /_/src/NSwag.Commands/NSwagDocument.cs:line 81
1> at NSwag.Commands.Document.ExecuteDocumentCommand.ExecuteDocumentAsync(IConsoleHost host, String filePath) in /_/src/NSwag.Commands/Commands/Document/ExecuteDocumentCommand.cs:line 85
1> at NSwag.Commands.Document.ExecuteDocumentCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in /_/src/NSwag.Commands/Commands/Document/ExecuteDocumentCommand.cs:line 32
1> at NConsole.CommandLineProcessor.ProcessSingleAsync(String[] args, Object input)
1> at NConsole.CommandLineProcessor.ProcessAsync(String[] args, Object input)
1> at NSwag.Commands.NSwagCommandProcessor.ProcessAsync(String[] args) in /_/src/NSwag.Commands/NSwagCommandProcessor.cs:line 61然而,如果我移除Schema位,构建就可以了--但是显然Schema是空的。
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PaginatedListOfTodoItemBriefDto"
}
}
}
},
"400": {
"description": "An error occurs or a business rule fails."
}
},我不知道我错过了什么,也许这就是我想要建立计划的方式。
发布于 2022-07-17 22:10:21
我也面临着同样的问题,但不像您,因为我有两个泛型控制器,其中响应类型根据泛型参数不同。解决方案是不动态地生成模式,并将其明确分配给结果。相反,获取或生成模式并将其设置为引用。
例如:
var dtoType = typeof(FooDto);
var okResponse = new OpenApiResponse
{
Schema = new JsonSchema()
{
Reference = GetSchemaForType(context, dtoType)
}
};
context.OperationDescription.Operation.Responses.Add(StatusCodes.Status200OK.ToString(), okResponse);在使用此方法获取或生成架构时:
private static JsonSchema GetSchemaForType(OperationProcessorContext context, Type type)
{
JsonSchema schema;
if (!context.SchemaResolver.HasSchema(type, false))
{
schema = context.SchemaGenerator.Generate(type);
context.SchemaResolver.AddSchema(type, false, schema);
}
else
{
schema = context.SchemaResolver.GetSchema(type, false);
}
return schema;
}免责声明:只有当您的模型还不是“傲慢定义”的一部分时,才需要使用GetSchemaForType。这段代码只是确保它不是依赖于这样的断言。
如果查看上面发布的json,您会发现模式并不包括响应模式本身,而是包含对它的引用。OperationDescription是最终被序列化的对象,因此您可以查看一个有效的swagger.json,以获得有关如何在代码中正确修改它的参考。
顺便说一句:同样也适用于数组类型。我也有问题,为他们找到一个合适的解决方案,所以也许这可以帮助你,以防你需要它。
var dtoType = typeof(FooDto);
var dtoSchema = GetSchemaForType(context, dtoType);
var okResponse = new OpenApiResponse
{
Schema = new JsonSchema()
{
Type = JsonObjectType.Array,
Item = new JsonSchema()
{
Reference = dtoSchema
}
}
};
operation.Responses.Add(StatusCodes.Status200OK.ToString(), okResponse);https://stackoverflow.com/questions/72774030
复制相似问题