首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSwag -公共操作响应OperationProcessor

NSwag -公共操作响应OperationProcessor
EN

Stack Overflow用户
提问于 2022-06-27 14:45:36
回答 1查看 313关注 0票数 1

我正在使用清洁架构解决方案建立一个新的API:https://github.com/jasontaylordev/CleanArchitecture

如果我们将重点放在API的返回类型上。

1- 200 -此API规范是生成精细的(基于在控制器中的动作的返回类型)

例如对于get/TodoItems

代码语言:javascript
复制
"/api/TodoItems": {
  "get": {
    "tags": [
      "TodoItems"
    ],
    "operationId": "TodoItems_GetTodoItemsWithPagination",
    "responses": {
      "200": {
        "description": "",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PaginatedListOfTodoItemBriefDto"
            }
          }
        }
      }
    },
    ]
  },

然后我们在ApiExceptionFilterAttribute文件夹WebUI/Filters/中处理了几个异常

代码语言:javascript
复制
_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文件中,我们需要用以下方法来修饰每个控制器操作。

代码语言:javascript
复制
[ProducesResponseType(typeof(ValidationException), 400)]
[ProducesResponseType(typeof(UnauthorizedAccessException), 401)]
[ProducesResponseType(typeof(NotFoundException), 404)]
[ProducesResponseType(typeof(ForbiddenAccessException), 403)]

为了避免这种情况,我考虑使用来自NSwagNSwag接口。但是,我在为返回的类型生成架构时遇到了问题。

代码语言:javascript
复制
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

代码语言:javascript
复制
    services.AddOpenApiDocument(configure =>
    {
        ...
        configure.OperationProcessors.Add(new CustomResponseTypesOperationProcessor());
    });

但是,当我构建项目时(它应该在构建时生成swagger.json和TS客户端,我得到以下错误)

代码语言:javascript
复制
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是空的。

代码语言:javascript
复制
    "responses": {
      "200": {
        "description": "",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PaginatedListOfTodoItemBriefDto"
            }
          }
        }
      },
      "400": {
        "description": "An error occurs or a business rule fails."
      }
    },

我不知道我错过了什么,也许这就是我想要建立计划的方式。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-17 22:10:21

我也面临着同样的问题,但不像您,因为我有两个泛型控制器,其中响应类型根据泛型参数不同。解决方案是不动态地生成模式,并将其明确分配给结果。相反,获取或生成模式并将其设置为引用。

例如:

代码语言:javascript
复制
var dtoType = typeof(FooDto);
var okResponse = new OpenApiResponse
{
    Schema = new JsonSchema()
    {
        Reference = GetSchemaForType(context, dtoType)
    }
};
context.OperationDescription.Operation.Responses.Add(StatusCodes.Status200OK.ToString(), okResponse);

在使用此方法获取或生成架构时:

代码语言:javascript
复制
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,以获得有关如何在代码中正确修改它的参考。

顺便说一句:同样也适用于数组类型。我也有问题,为他们找到一个合适的解决方案,所以也许这可以帮助你,以防你需要它。

代码语言:javascript
复制
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);
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72774030

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档