Swagger UI 不会在控制器的 GET 操作中呈现复杂类型参数的主体参数字段

问题描述 投票:0回答:3

我有一个 ASP.NET Web API 2 项目,我已向其中添加了 Swagger - Swashbuckle v5.6.0。一切正常。 Swagger UI 按预期呈现我的 API 的测试端点。

我在 API 中添加了一个新的控制器。有一个带有复杂类型参数的

GET
操作。对于复杂类型,Web API 尝试从消息正文中读取值。这是默认行为。

这是我的 GET 操作:

    [HttpGet]
    [Route("search")]
    [ResponseType(typeof(List<SearchModel>))]
    public IHttpActionResult Search(SearchModel searchOptions)
    {
        //....
        
        return Ok();
    }

她是我的复杂型:

public class SearchModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    [DataType(DataType.EmailAddress)]
    [EmailAddress]
    public string Email { get; set; }

    public string AddressLine1 { get; set; }

    public string City { get; set; }

    public string Telephone { get; set; }

    public string MobilePhone { get; set; }
}

问题:

但是 Swagger UI 不会在

GET
操作中为我的复杂类型渲染主体参数字段。对于
POST
PUT
操作,Swagger UI 按预期呈现主体参数字段,但不适用于我的
GET
操作中的复杂类型。

从屏幕截图中可以看出,Swagger UI 为我的复杂类型中的属性呈现查询参数字段,而不是像在

POST
PUT
的情况下那样为我的类型呈现主体参数字段。

当从 Postman 进行测试并在请求正文中填充 json 时,我的

GET

 操作工作正常。通过在 Visual Studio 内的操作中设置断点,我可以看到这些值绑定到操作参数中的对象。

我尝试用

[FromBody]

(这是复杂类型的默认值)来装饰我的操作中的参数,但结果相同。

这是 Swagger 中的一个错误吗?还是我错过了什么?

asp.net swagger asp.net-web-api2 swagger-ui swashbuckle
3个回答
4
投票
遗憾的是,您无法使用 Swagger 做您想做的事。您无法在 HTTP GET 方法中发送请求模型。但是,您可以将 swagger UI 更改为如下所示:

但是您将无法在控制器中接收模型。

这是 Swagger 开发人员中的一个已知问题,并于 2016 年进行了讨论,最终决定是 swagger 不支持 HTTP GET 方法中的请求正文。

这是已关闭问题的链接。

您有三个选择:

    保持该方法不变,并在 Postman 中测试它,但不在 Swagger 中测试。
  • 按照以下步骤即可实现上图,但请注意,这只会修复 UI 部分,当你大摇大摆地按
  • null
     时,控制器中始终会出现 
    SearchModel
     
    Try it out!
  • 使其成为
  • [HttpPost
     方法而不是 
    [HttpGet]

如何让 swagger UI 显示带有请求正文的 GET 方法:

首先,创建一个

Attribute

类:

public class ModelInBodyAttribute : Attribute { public ModelInBodyAttribute(string modelName, string description, bool isRequired) { this.ModelName = modelName; this.Description = description; this.IsRequired = IsRequired; } public string ModelName { get; set; } public bool IsRequired { get; set; } public string Description { get; set; } }
然后你可以在控制器中装饰你的方法:

[ModelInBody(modelName: nameof(SearchModel), description: "My model description", isRequired: true)] [HttpGet] [Route("search")] [ResponseType(typeof(List<SearchModel>))] public IHttpActionResult Search(SearchModel searchOptions) { //.... return Ok(new List<SearchModel>()); }
之后创建

IOperationFilter

类(
ModelInBodyOperationFilter
):

public class ModelInBodyOperationFilter : IOperationFilter { public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) { var attribute = apiDescription.GetControllerAndActionAttributes<ModelInBodyAttribute>().FirstOrDefault(); if (attribute == null) { return; } operation.parameters.Clear(); operation.parameters.Add(new Parameter { name = attribute.ModelName, description = attribute.Description, @in = "body", required = attribute.IsRequired, schema = new Schema { @ref = $"#/definitions/{attribute.ModelName}" } }); } }
最后,别忘了在

IOperationFilter

中注册
SwaggerConfig
:

c.OperationFilter<ModelInBodyOperationFilter>();


当您通过 swagger 发送请求时,您会注意到

Curl

 部分是绝对正确的,但是在您的控制器中仍然没有任何内容。


1
投票
关于 GET 请求中是否应该有 PAYLOAD“正文内容”的讨论无穷无尽。正如您提到的

它受 HTTP 支持,但您会在互联网上发现很多人建议不要这样做。我想 swagger 团队也希望你不要使用它。


0
投票
回复有点晚了,但是如果你能够用 [APIController] 装饰控制器,swagger 将为复杂类型显示不同的 ui。

APIController

© www.soinside.com 2019 - 2024. All rights reserved.