為團隊訂製一個優秀文件和友善的測試,使用SWAGGER
前言
web api通常開發出來,就代表了可以多個專案使用同樣的邏輯,甚至是排除了任何程式語言,不管你是手機或者javascript或者是ruby etc..,全部都可以使用,所以現在有很多專案都漸漸的翻成了web api,甚至有多微服務的概念也是用web api的角度去思考而架構,但是如果有一天發現不同部門也想用到我們的資料,這時候文件就很重要,然而如果是提供紙本文件的話,我們工程師都知道,文件可能都還需要溝通過,然後了解怎麼使用才開始寫code去try,就會很浪費時間和成本,所以如果我們能提供一份線上文件,直接給團隊去瀏覽和測試,就能節省很多時間成本的浪費,至少如果我們用swagger來寫文件,有比較統一的文件格式,甚至是一些qa或pm都能直接透過線上文件來了解細節或測試,接著我就來說明一下如何使用Swagger吧。
導覽
安裝swashbuckle
首先使用nuget安裝相關必要的package
安裝完之後可以看到多了一支檔案是App_Start/SwaggerConfig.cs的檔案,裡面已經很詳細的註解了每段程式碼的意義了。
開始一個簡單的swagger文件吧
首先我們來改一下SwaggerConfig.cs吧
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "WebApiTest");
c.IncludeXmlComments(GetXmlCommentsPath());
})
.EnableSwaggerUi();
}
internal static string GetXmlCommentsPath()
{
return string.Format(@"{0}\App_Data\XmlDocument.xml",
System.AppDomain.CurrentDomain.BaseDirectory); //XmlDocument.xml是建置後產生的檔案,Swagger會參考這份xml
}
}
接著對專案選擇屬性
然後把XML documentation file: 的部份打上我們剛剛swagger要輸出的xml
然後把web api都加入summary的部份
/// <summary>
/// 員工相關
/// </summary>
[RoutePrefix("/Api/Values")]
public class ValuesController : ApiController
{
/// <summary>
/// 取得資料
/// </summary>
/// <returns></returns>
[Route("Get")]
[HttpGet]
public IHttpActionResult Get()
{
return Ok(EmployeeDao.Employees);
}
/// <summary>
/// 用單號取得單筆資料
/// </summary>
/// <param name="id">單號</param>
/// <returns></returns>
[Route("GetById")]
[HttpGet]
public IHttpActionResult GetById(int id)
{
return Ok(EmployeeDao.Employees.FirstOrDefault(x => x.EmployeeId == id));
}
/// <summary>
/// 搜尋資料
/// </summary>
/// <param name="search">搜尋物件</param>
/// <returns></returns>
[Route("Search")]
[HttpGet]
public IHttpActionResult Search([FromUri]Search search)
{
return Ok(EmployeeDao.Employees.FirstOrDefault(x => x.Name.Contains(search.Name) &&
x.Address.Contains(search.Address)));
}
/// <summary>
/// 新增資料
/// </summary>
/// <param name="employee">員工</param>
/// <returns></returns>
[Route("Post")]
[HttpPost]
public IHttpActionResult Post(Employee employee )
{
EmployeeDao.Employees.Add(employee);
return Ok(EmployeeDao.Employees);
}
/// <summary>
/// 修改資料
/// </summary>
/// <param name="employee">員工</param>
/// <returns></returns>
[Route("Put")]
[HttpPut]
public IHttpActionResult Put(Employee employee)
{
var result=EmployeeDao.Employees.FirstOrDefault(x => x.EmployeeId == employee.EmployeeId);
if (result != null)
{
result.Name = employee.Name;
result.PhoneNumber = employee.PhoneNumber;
result.Address = employee.Address;
}
return Ok(EmployeeDao.Employees);
}
/// <summary>
/// 刪除資料
/// </summary>
/// <param name="id">單號</param>
/// <returns></returns>
[Route("Delete")]
[HttpDelete]
public IHttpActionResult Delete(int id)
{
EmployeeDao.Employees.RemoveAll(x=>x.EmployeeId==id);
return Ok(EmployeeDao.Employees);
}
}
緊接著只要在我們的網址後面加上路由/swagger,就可以訪問了
針對傳輸物件或者是回傳物件定義較清楚的說明
在此以Post來做範例,假設我所有的物件都有加上summary的說明,示例如下
然後我們Post的Api程式碼如下
/// <summary>
/// 新增資料
/// </summary>
/// <param name="employee">員工</param>
/// <returns></returns>
[Route("Post")]
[HttpPost]
public IHttpActionResult Post(Employee employee )
{
EmployeeDao.Employees.Add(employee);
return Ok(EmployeeDao.Employees);
}
接著就可以看到swagger的post顯示內容如下
可以看到回傳的部份沒有資料,這個是因為我們使用了IHttpActionResult,導致沒有回傳型別,如果我們使用的是有型別的回傳,那麼就能看到回傳型別了
不過這不符合我們的需求,因為我們需要回應狀態碼給前端,告訴前端伺服器到底遇到了什麼狀況,所以我們必須得使用IHttpActionResult的方式,那我們可以加上ResponseType的attribute
/// <summary>
/// 新增資料
/// </summary>
/// <param name="employee">員工</param>
/// <returns></returns>
[ResponseType(typeof(Employee))]
[Route("Post")]
[HttpPost]
public IHttpActionResult Post(Employee employee )
{
EmployeeDao.Employees.Add(employee);
return Ok(EmployeeDao.Employees);
}
結果會像這個樣子
如何在佈署的時候,也自動產生一份XML
在預設的狀況下,我們在Debug的時候,只要建置的時候,就會重新產生一XmlDocument.xml在App_Data裡面,但是在實際狀況下此份xml可能並不會簽入版控,甚至如果有搭配ci的話,可能會在例如jenkins甚至team city等等的機器上,自動建置甚至是自動佈署,但是當我們切換去release的狀態,甚至是其他如果我們自己有新增別的configuration的話,可能就沒辦法自動產生xml,就會造成編譯失敗,或者是預期該看到swagger卻沒有看到的狀況,那接下來就來說明一下我們該怎麼設定也能在任何configuration都能自動產生xml出來。
假設我們現在把XmlDocument.xml這個檔案在方案總管給刪除了,然後切換到release做建置的話,其實xml是不會產生出來的,只有在Debug的狀態才會產生xml出來
然後把檔案刪掉,接著切換到release再建置專案,其實xml是不會產生出來的
這時候我們只要打開專案下的csproj,接著搜尋我們的xml名稱,然後把那行複製到release或者是自定義的其他configuration,切換到那個configuration做建置,就會自動產生xml出來了
在線上階段,關掉swagger的功能
因為swagger是為了方便理解還有測試和溝通,所以我們才製作此種文檔,但是我們不可能會把這種功能放到production上面,那我們又該如何在上線階段去關閉呢?其實也很簡單,比如說我只想在Debug或者Qa的環境,可以去使用swagger功能,我們只要在App_Start/SwaggerConfig.cs,修改切換環境的方式就可以了。
public class SwaggerConfig
{
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "WebApiTest");
c.IncludeXmlComments(GetXmlCommentsPath());
#if DEBUG || QA
})
.EnableSwaggerUi();
#else
});
#endif
}
internal static string GetXmlCommentsPath()
{
return string.Format(@"{0}\App_Data\XmlDocument.xml",
System.AppDomain.CurrentDomain.BaseDirectory); //XmlDocument.xml是建置後產生的檔案,Swagger會參考這份xml
}
}
結論
swagger還有蠻多的內容,有興趣的讀者可以自行再去研究一下,如果有任何建議的話,再請不吝指教