NSWAG-常见操作响应操作处理器
我正在使用此处使用干净的体系结构解决方案设置新的API: https://github.com/jasontaylordev/jasontoylordev/cleanarchitecture
如果我们专注于API的返回类型。
1-200-为此生成此API规范(基于控制器中的返回类型),
例如get/dodoItems
"/api/TodoItems": {
"get": {
"tags": [
"TodoItems"
],
"operationId": "TodoItems_GetTodoItemsWithPagination",
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PaginatedListOfTodoItemBriefDto"
}
}
}
}
},
]
},
,我们在apiexceptionfiltertribute < /code>在文件夹
webui/filters/
_exceptionHandlers = new Dictionary<Type, Action<ExceptionContext>>
{
{ typeof(ValidationException), HandleValidationException },
{ typeof(NotFoundException), HandleNotFoundException },
{ typeof(UnauthorizedAccessException), HandleUnauthorizedAccessException },
{ typeof(ForbiddenAccessException), HandleForbiddenAccessException },
};
typeof(valivationException)
用于http status code 400
type> type> typef(notfoundException)代码>用于HTTP状态代码404
typeof(unauterizedAccessexception)
for HTTP状态代码401
typef(forbiddenAccessexception)现在是HTTP状态代码
403
现在,要使这些填充在Swagger.json文件中,我们将需要使用以下内容来装饰每个控制器操作。
[ProducesResponseType(typeof(ValidationException), 400)]
[ProducesResponseType(typeof(UnauthorizedAccessException), 401)]
[ProducesResponseType(typeof(NotFoundException), 404)]
[ProducesResponseType(typeof(ForbiddenAccessException), 403)]
为了避免这种情况,我想到了使用ioperationProcessor
从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;
}
}
在配置
services.AddOpenApiDocument(configure =>
{
...
configure.OperationProcessors.Add(new CustomResponseTypesOperationProcessor());
});
中
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
显然,模式是空的。
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PaginatedListOfTodoItemBriefDto"
}
}
}
},
"400": {
"description": "An error occurs or a business rule fails."
}
},
我不确定我缺少什么,也许是我试图生成该计划的方式。
I'm setting up a new API using Clean Architecture solution from here: https://github.com/jasontaylordev/CleanArchitecture
If we focus on the return types for the API.
1 - 200 - This API specification for this is generated fine (based on return type of the Action in Controller)
e.g. for get/TodoItems
"/api/TodoItems": {
"get": {
"tags": [
"TodoItems"
],
"operationId": "TodoItems_GetTodoItemsWithPagination",
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PaginatedListOfTodoItemBriefDto"
}
}
}
}
},
]
},
Then we have a couple of exceptions being handled in ApiExceptionFilterAttribute
in the folder WebUI/Filters/
_exceptionHandlers = new Dictionary<Type, Action<ExceptionContext>>
{
{ typeof(ValidationException), HandleValidationException },
{ typeof(NotFoundException), HandleNotFoundException },
{ typeof(UnauthorizedAccessException), HandleUnauthorizedAccessException },
{ typeof(ForbiddenAccessException), HandleForbiddenAccessException },
};
typeof(ValidationException)
is for Http status code 400
typeof(NotFoundException)
is for Http status code 404
typeof(UnauthorizedAccessException)
is for Http status code 401
typeof(ForbiddenAccessException)
is for Http status code 403
Now, to make these populate in the swagger.json file we will need to decorate every single controller action with the following.
[ProducesResponseType(typeof(ValidationException), 400)]
[ProducesResponseType(typeof(UnauthorizedAccessException), 401)]
[ProducesResponseType(typeof(NotFoundException), 404)]
[ProducesResponseType(typeof(ForbiddenAccessException), 403)]
To avoid this, I thought of using the IOperationProcessor
interface from NSwag
. but I am having trouble generating the Schema for the returned type.
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;
}
}
In ConfigureServices
services.AddOpenApiDocument(configure =>
{
...
configure.OperationProcessors.Add(new CustomResponseTypesOperationProcessor());
});
But when I build the project (it should generated the swagger.json and TS API client on build, I get the following error)
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
Whereas if I remove the Schema bit, the build is fine - but obviously the Schema is empty.
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PaginatedListOfTodoItemBriefDto"
}
}
}
},
"400": {
"description": "An error occurs or a business rule fails."
}
},
I am not sure what I'm missing, maybe it's they way I am trying to generate the Scheme.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我面临同一问题,但是与您不同,因为我有几个通用控制器,其中响应类型基于通用参数而有所不同。解决方案是不要即时生成架构,并将其明确分配给结果。而是获取或生成架构并将其设置为参考。
例如:
在使用此方法获取或生成模式的同时:
如果您查看上面发布的JSON,则发现该模式不包括响应架构本身,而是对其进行引用。操作描述是最终被序列化的对象,因此您可以查看有效的Swagger.json,以获取有关如何在代码中正确修改它的参考。
顺便说一句:同样适用于数组类型。我也有问题为他们找到适当的解决方案,因此,如果您需要它,这也许可以帮助您。
I was facing the same issue, but unlike you because I am having a couple of generic controllers where the response type differs based on generic parameters. The solution is to not generate a schema on the fly and plainly assigning it to the result. Rather, get or generate the schema and set it as a reference.
As an example:
while using this method to get or generate the schema:
If you look at the json you posted above you see that the schema does not include the response schema itself but a reference to it. The OperationDescription is the object that ends up being serialized so you can look at a valid swagger.json to get a reference on how to properly modify it in code.
Btw: same applies to array types. I had issues finding a proper solution for them as well so maybe this helps you out in case you need it.
我遇到了同样的问题,但是公认的解决方案对我不起作用。
经过很多调试后,我发现了这个问题(至少在我的情况下)。
用
schemageNerator.generate(...)
用generateWithReference(...)
或 generateWithReenceAndNullability(...) benate(...)。我最终得到了类似的东西:
I had the same issue but the accepted solution didn't work for me.
After a lot of debugging I figured out the issue (at least in my case).
Replacing the use of
SchemaGenerator.Generate(...)
with eitherGenerateWithReference(...)
orGenerateWithReferenceAndNullability(...)
.I ended up with something similar to this: