首页 > 解决方案 > 导入 OpenAPI 2.0 Postman 集合,所有 POST 请求正文都显示为 x-www-form-urlencoded,而不是原始 JSON

问题描述

我在用什么?

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


问题?

我有一个使用 Swagger (Swashbuckle) 的大型 API,我想将 Open API 模式作为一个集合导入 Postman。
在 Postman 中继续{myUrl}/swagger/docs/v1粘贴模式后,我注意到我所有的 Post 请求都被“破坏”了。去的时候Body它显示为"application/x-www-form-urlencoded",而不是原始的JSON身体。

在此处输入图像描述

相反,它看起来像这样:

在此处输入图像描述

我的架构:

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

paths并且definitions不是空的,它们包含很多 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 中的操作或控制器上方没有“特殊”属性。

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

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

标签: .netasp.net-web-apiswaggerpostmanswashbuckle

解决方案


解决方案:

我看到了这篇很棒的文章并在那里实现了解决方案:

创建了一个自定义属性:

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

    public IEnumerable<string> ContentTypes { get; }
}

之后OperationFilter为 Swagger 创建一个类:

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();
    }
}

最后,只需OperationFilterSwaggerConfig.cs如下方式注册:

c.OperationFilter<ConsumesOperationFilter>();

推荐阅读