Asp.net-Web-Api

我如何告訴 Swashbuckle 需要正文內容?

  • February 27, 2020

我有一個 WebAPI 控制器,它接受二進制包並將它們儲存在某個地方。由於這些包可能變得非常大,我不想通過添加字節數組參數將它們載入到記憶體中,而是通過流傳遞。

在這個答案中找到了一種方法:

[HttpPost]
[Route("Store/{projectId}")]
public async Task Store(string projectId)
{
   using (var stream = await this.Request.Content.ReadAsStreamAsync())
   {
       await this.packageManager.StorePackageAsync(projectId, stream);
   }
}

這行得通,我可以使用 Postman 將文件發送到控制器。但是,我現在想用 Swashbuckle 生成 swagger 文件,當然,這裡沒有提到所需的正文內容。

有沒有辦法獲取請求內容的流,以便 Swashbuckle 知道它?或者是否有一個屬性可以用來告訴它所需的內容?

要實現這一點,您必須做幾件事。

首先,您必須告訴 Swagger 在正文中有一個包含二進制數據的參數。接下來,您必須告訴 Swagger 端點使用二進制數據(例如 application/octet-stream)。

Swashbuckle 不支持此功能。但是您可以創建自定義過濾器來擴展 Swashbuckle 的功能。我通常做的是創建一個自定義屬性來裝飾一個方法,然後創建一個自定義過濾器來對該屬性進行操作。

在您的情況下,這可以解決問題:

自定義屬性

public class BinaryPayloadAttribute : Attribute
{
   public BinaryPayloadAttribute()
   {
       ParameterName = "payload";
       Required = true;
       MediaType = "application/octet-stream";
       Format = "binary";
   }

   public string Format { get; set; }

   public string MediaType { get; set; }

   public bool Required { get; set; }

   public string ParameterName { get; set; }
}

自定義過濾器

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

       operation.consumes.Clear();
       operation.consumes.Add(attribute.MediaType);

       operation.parameters.Add(new Parameter
       {
           name = attribute.ParameterName,
           @in = "body", 
           required = attribute.Required,
           type = "string", 
           format = attribute.Format
       });
   }
}

將過濾器添加到 Swashbuckle 配置

GlobalConfiguration.Configuration 
   .EnableSwagger(c => 
       {
           // other configuration setting removed for brevity
           c.OperationFilter<BinaryPayloadFilter>();
       });

將屬性應用於您的方法

[HttpPost]
[BinaryPayload]
[Route("Store/{projectId}")]
public async Task Store(string projectId)
{
   ...
}

在 Swagger UI 中,您將獲得:

招搖使用者界面

又一個更新。這是我最終使用ASP.NET Core 3.1and的解決方案Swashbuckle.AspNetCore.Swagger 5.0.0

public class BinaryContentAttribute : Attribute
{
}
public class BinaryContentFilter : IOperationFilter
{
   /// <summary>
   /// Configures operations decorated with the <see cref="BinaryContentAttribute" />.
   /// </summary>
   /// <param name="operation">The operation.</param>
   /// <param name="context">The context.</param>
   public void Apply(OpenApiOperation operation, OperationFilterContext context)
   {
       var attribute = context.MethodInfo.GetCustomAttributes(typeof(BinaryContentAttribute), false).FirstOrDefault();
       if (attribute == null)
       {
           return;
       }

       operation.RequestBody = new OpenApiRequestBody() { Required = true };
       operation.RequestBody.Content.Add("application/octet-stream", new OpenApiMediaType()
       {
           Schema = new OpenApiSchema()
           {
               Type = "string",
               Format = "binary",
           },
       });
   }
}

ConfigureServicesStartup.cs

services.AddSwaggerGen(o =>
{
   o.OperationFilter<BinaryContentFilter>();
});

引用自:https://stackoverflow.com/questions/41141137