使用 Swagger 建立 api 文件

  • 215
  • 0
  • C#
  • 2023-07-27

使用 swagger 產生 相關的 api document 與 sample

環境 .net framework 4.7.2

Nuget 安裝

1. Swashbuckle (安裝完會產生SwaggerConfig.cs)
2. Swashbuckle.Core 5.6.0
3. Swashbuckle.Examples 4.0.0


調整 SwaggerConfig.cs

1. 將 c.IncludeXmlComments(GetXmlCommentsPath()); 反註解掉 


2. 設定 project 輸出路徑為 App_Data\SwaggerApi.xml


3. 新增 GetXmlCommentsPath  私有方法

private static string GetXmlCommentsPath() 
{ 
   return Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"App_Data\SwaggerApi.xml"); 
}

 

新增 ValuesController 進行測試
    public class ValuesController : ApiController
    {
        /// <summary>
        /// api index page
        /// </summary>
        /// <returns></returns>
        [SwaggerResponse(HttpStatusCode.OK, "成功", typeof(string))]
        [SwaggerResponse(HttpStatusCode.NoContent, "沒有資料", typeof(void))]
        [SwaggerResponse(HttpStatusCode.InternalServerError, "內部錯誤", typeof(ResponseModel))]
        [HttpGet]
        [Route("Index")]
        public string Index()
        {
            return "Welcome api home";
        }

        /// <summary>
        /// Custom Action by demo purpose
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        [Route("CustomAction")]
        public ResponseModel CustomAction([FromBody] RequestModel request)
        {
            return new ResponseModel()
            {
                Message = $"{request.Name}:{request.Age}",
                StatusCode = HttpStatusCode.OK.GetHashCode()
            };
        }
    }

相關Model 如下

    public class RequestModel
    {
        public int Age { set; get; }
        public string Name { set; get; }
    }
    
    public class ResponseModel
    {
        public string Message { get; set; }
        public int StatusCode {get; set; }
    }

裡面的內容就會包含了 200, 204, 500 的各種說明,甚至裡面的 response model 也特別設成不一樣的

然而這邊的 example value 都是空的,如果我們希望做一個 sample 給讀 spec 的人呢?

增加 example

1. 確認在上列步驟已經安裝了 Swashbuckle.Examples 4.0.0

2. 打開 SwaggerConfig.cs 將 c.OperationFilter<AddDefaultResponse>(); 反註解掉
  並改為 c.OperationFilter<ExamplesOperationFilter>();

3. 建立 example model

    public class RequestExampleModel : IExamplesProvider
    {
        public object GetExamples()
        {
            return new RequestModel
            {
                Name = "Ace",
                Age = 99
            };
        }
    }
    
    public class ResponseExampleModel : IExamplesProvider
    {
        public object GetExamples()
        {
            return new ResponseModel
            {
                Message = "Example Message",
                StatusCode = 200
            };
        }
    }

將 swgger example 的 attribute 掛上相對應的 action

        /// <summary>
        /// Custom Action by demo purpose
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("CustomAction")]
        [HttpPost]
        [SwaggerRequestExample(
           typeof(RequestModel),
           typeof(RequestExampleModel))]
        [SwaggerResponseExample(HttpStatusCode.OK,
            typeof(ResponseExampleModel))]
        public ResponseModel CustomAction([FromBody] RequestModel request)
        {
            return new ResponseModel()
            {
                Message = $"{request.Name}:{request.Age}",
                StatusCode = HttpStatusCode.OK.GetHashCode()
            };
        }

這邊的 request 與 response 就會有相對應的 example 了,有助其他人看文件更快可以了解 sample 裡的資料所代表的意義

 

如果有仔細看的話,會發現 example 上面會有 "application/json" 的資料,導致 sample 格式會略有不同

在搜尋的時候發現這個 issue 已經 closed 了,把 swagger-ui 改成 v3 就能解決,但改了還是沒有解決
 

翻了 Swashbuckle.Examples 的 source code 後會發現問題所在

 

Request 時 media type 設成 false

Response 時 media type 設為 true

這也能解釋為什麼 request 時沒有 application/json ,但 response 卻會有

 

參考資料

https://dotblogs.com.tw/yc421206/2019/01/23/tips_write_write_web_api_document_via_swagger
https://github.com/mattfrear/Swashbuckle.Examples
 https://github.com/esi/esi-issues/issues/438
https://github.com/mattfrear/Swashbuckle.Examples/blob/master/Swashbuckle.Examples/Examples/ExamplesOperationFilter.cs