Swagger UI 不会在我的控制器的 GET 操作中为我的复杂类型参数呈现正文参数字段
Swagger UI doesn't render body parameter field for my complex type parameter in GET action of my Controller
我有一个 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
.
我的 GET
操作在从 Postman 测试并在请求正文中填充 json 时工作正常。通过在 Visual Studio 内的操作中设置断点,我可以看到值在操作参数中绑定到我的对象。
我尝试用 [FromBody]
(这是复杂类型的默认值)修饰我的操作中的参数,但结果相同。
这是 Swagger 中的错误吗?还是我遗漏了什么?
遗憾的是,您不能用 Swagger 做您想做的事。您不能在 HTTP GET 方法中发送请求模型。但是,您可以将 swagger UI 更改为如下所示:
但您将无法在控制器中接收模型。
这是 Swagger 开发人员内部的一个已知问题,在 2016 年进行了讨论,最终决定 swagger 将不支持 HTTP GET 方法中的请求正文。 Here is the link to the already closed issue.
这里有三个选项:
- 保持方法不变,在 Postman 中测试它,但不要在 Swagger 中测试。
- 按照以下步骤实现上图,但请注意,它只会修复 UI 部分,您将始终以
null
SearchModel
结束当你大摇大摆地按下 Try it out!
时的控制器。
- 将其设为
[HttpPost
方法而不是 [HttpGet]
。
如何使 swagger UI 显示带有请求正文的 GET 方法:
首先,创建一个Attribute
class:
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
class (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}" }
});
}
}
最后,不要忘记在SwaggerConfig
中注册IOperationFilter
:
c.OperationFilter<ModelInBodyOperationFilter>();
当您通过 swagger 发送请求时,您会注意到 Curl
部分是绝对正确的,但是在您的控制器中仍然没有任何内容。
关于是否应该在 GET 请求中包含 PAYLOAD“正文内容”的讨论无休止。正如您提到的 它受 HTTP 支持,但您会在互联网上发现许多人建议不要这样做。我猜那个swagger团队也希望你不要使用它。
我有一个 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
.
我的 GET
操作在从 Postman 测试并在请求正文中填充 json 时工作正常。通过在 Visual Studio 内的操作中设置断点,我可以看到值在操作参数中绑定到我的对象。
我尝试用 [FromBody]
(这是复杂类型的默认值)修饰我的操作中的参数,但结果相同。
这是 Swagger 中的错误吗?还是我遗漏了什么?
遗憾的是,您不能用 Swagger 做您想做的事。您不能在 HTTP GET 方法中发送请求模型。但是,您可以将 swagger UI 更改为如下所示:
但您将无法在控制器中接收模型。
这是 Swagger 开发人员内部的一个已知问题,在 2016 年进行了讨论,最终决定 swagger 将不支持 HTTP GET 方法中的请求正文。 Here is the link to the already closed issue.
这里有三个选项:
- 保持方法不变,在 Postman 中测试它,但不要在 Swagger 中测试。
- 按照以下步骤实现上图,但请注意,它只会修复 UI 部分,您将始终以
null
SearchModel
结束当你大摇大摆地按下Try it out!
时的控制器。 - 将其设为
[HttpPost
方法而不是[HttpGet]
。
如何使 swagger UI 显示带有请求正文的 GET 方法:
首先,创建一个Attribute
class:
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
class (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}" }
});
}
}
最后,不要忘记在SwaggerConfig
中注册IOperationFilter
:
c.OperationFilter<ModelInBodyOperationFilter>();
当您通过 swagger 发送请求时,您会注意到 Curl
部分是绝对正确的,但是在您的控制器中仍然没有任何内容。
关于是否应该在 GET 请求中包含 PAYLOAD“正文内容”的讨论无休止。正如您提到的 它受 HTTP 支持,但您会在互联网上发现许多人建议不要这样做。我猜那个swagger团队也希望你不要使用它。