导入 OpenAPI 2.0 Postman 集合,所有 POST 请求主体显示为 x-www-form-urlencoded,而不是原始 JSON

Import OpenAPI 2.0 Postman collection and all POST request bodies are displayed as x-www-form-urlencoded, instead of raw JSON

我在用什么?

.NET Framework 4.8
Postman 版本 7.19.1
Swashbuckle 5.6.0,金块包


有问题吗?

我有一个很大的 API 使用 Swagger (Swashbuckle),我想将 Open API 模式作为一个集合导入 Postman。
在继续 {myUrl}/swagger/docs/v1 并将模式粘贴到 Postman 之后,我注意到我所有的 Post 请求都是 'broken'。当转到 Body 时,它显示为 "application/x-www-form-urlencoded",而不是原始的 JSON 正文。

相反,它看起来像这样:

我的架构:

{
    "swagger": "2.0",
    "info": {
        "version": "v1",
        "title": "My API"
    },
    "host": "localhost:51209",
    "schemes": [
        "http"
    ],
    "paths": { },
    "definitions": { }
}

pathsdefinitions 不是空的,它们包含很多 API 调用,这就是为什么我只从中选择一个 POST 方法,因为它们都是有同样的问题。

这是 paths 对象和其中的 属性 "consumes" 的一个示例:

"/api/MyController/MyMethod": {
        "consumes": [
            "application/json",
            "text/json",
            "application/xml",
            "text/xml",
            "application/x-www-form-urlencoded"
        ]
}

问题似乎出在 consumes 对象 属性 中,该对象具有一个字符串数组作为值,其中之一是 "application/x-www-form-urlencoded"

我在 .NET Web API 中的操作或控制器之上没有 'special' 属性。

[HttpPost]
[Route("MyMethod")]
public IHttpActionResult MyMethod(List<JobHeaderInputModel> jobHeaderList)

我知道 ASP Net Core 有一个 Consumes 属性,但我使用的是 .NET Framework。

解决方案:

我看到了这个惊人的 article 并在那里实施了解决方案:

创建了自定义属性:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class SwaggerConsumesAttribute : Attribute
{
    public SwaggerConsumesAttribute(params string[] contentTypes)
    {
        this.ContentTypes = contentTypes;
    }

    public IEnumerable<string> ContentTypes { get; }
}

之后为 Swagger 创建一个 OperationFilter class:

public class ConsumesOperationFilter : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        var attribute = apiDescription.GetControllerAndActionAttributes<SwaggerConsumesAttribute>().SingleOrDefault();
        if (attribute == null)
        {
            return;
        }

        operation.consumes.Clear();
        operation.consumes = attribute.ContentTypes.ToList();
    }
}

最后,只需在SwaggerConfig.cs中注册OperationFilter,如下所示:

c.OperationFilter<ConsumesOperationFilter>();