[Swagger] 解決不支援多個操作行為

Swagger 是個不錯的文檔+測試工具,但是卻不支援多個行為,需要靠它來簡化文件的工作,怎麼辦?

開發環境

  • VS 2017 Enterprise 15.9.5
  • Swashbuckle 5.6.0

情境

public class DefaultController : ApiController
{
    public IHttpActionResult Get(string userName)
    {
        return this.Ok();
    }
    public IHttpActionResult Get(string userName, string department)
    {
        return this.Ok();
    }
}

 

執行的時候出現這樣的錯誤

"ExceptionMessage":"Not supported by Swagger 2.0: Multiple operations with path 'api/Default' and method 'GET'.


 

解決方案

以下方案擇一使用。

1.不要用他

放下 Swagger 右轉到 MS Help Page,https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with-aspnet-web-api/creating-api-help-pages

For a C# application: Install-Package Microsoft.AspNet.WebApi.HelpPage
For a Visual Basic application: Install-Package Microsoft.AspNet.WebApi.HelpPage.VB

2.更改 Route

[RoutePrefix("api/default")]
public class DefaultController : ApiController
{
    [Route("{userName}")]
    public IHttpActionResult Get(string userName)
    {
        return this.Ok();
    }
  
    public IHttpActionResult Get(string userName, string department)
    {
        return this.Ok();
    }
}

 

3.手動合併 Action

保留參數多的那一個,其他的靠程式判斷

 

4.只取一個 Action

@SwaggerConfig.cs

c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());

 

這樣做的話就只保留一個方法了

 

 

5.程式合併 Action

@SwaggerConfig.cs

c.ResolveConflictingActions(SwaggerHelper.ConflictingActionsResolver());

 

這一段代碼是把所有重複的方法合併他們的參數,把參數全改為非必要

apiDescriptions 由 Swagger 傳入,這裡可以得到重複的方法
public class SwaggerHelper
{
    public static Func<IEnumerable<ApiDescription>, ApiDescription> ConflictingActionsResolver()
    {
        return apiDescriptions =>
               {
                   var descriptions = apiDescriptions as ApiDescription[] ?? apiDescriptions.ToArray();
 
                   // 找第一個方法來改
                   var result = descriptions.First();
 
                   // 把所有的參數倒出來
                   var parameters = descriptions.SelectMany(=> d.ParameterDescriptions)
                                                .ToList();
 
                   // 重整參數
                   result.ParameterDescriptions.Clear();
                   
                   foreach (var parameter in parameters)
                   {
                       if (result.ParameterDescriptions.All(=> x.Name != parameter.Name))
                       {
                           result.ParameterDescriptions.Add(new ApiParameterDescription
                           {
                               Documentation = parameter.Documentation,
                               Name = parameter.Name,
                               ParameterDescriptor =
                                   new OptionalHttpParameterDescriptor((ReflectedHttpParameterDescriptor) parameter
                                                                           .ParameterDescriptor),
                               Source = parameter.Source
                           });
                       }
                   }
 
                   return result;
               };
    }
}

 

這個只是要把所有的參數改成非必要

public class OptionalHttpParameterDescriptor : ReflectedHttpParameterDescriptor
{
    public OptionalHttpParameterDescriptor(ReflectedHttpParameterDescriptor parameterDescriptor)
        : base(parameterDescriptor.ActionDescriptor, parameterDescriptor.ParameterInfo)
    {
    }
    public override bool IsOptional => true;
}

 

完成之後長這樣

看你傳入幾個參數,他就會跑到正確的 action,這個做法應該是我目前覺得最好的做法

 

範例位置:

https://github.com/yaochangyu/sample.dotblog/tree/master/WebAPI/Swagger/Multiple%20Operation
 

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo