在 ASP.NET Core ApiController 加入多個 HttpGet/HttpPost Action
| | 4 | | ![]() |
過去 ASP.NET MVC 時代,我偏好用一般的 MVC Controller 寫 WebAPI,而非走 RESTful 風格的 ApiController。但 RESTful WebAPI 畢竟是當前主流,ASP.NET Core 的內建支援與緊密整合實在太香,於是,要在 ASP.NET Core 裡寫 WebAPI,我還是會選擇使用 WebAPI 範本及 ApiController。 ' 以 .NET 6 為例,來看看內建的 WebAPI Swagger 有多方便。用 dotnet new webapi -o WebApiDemo
建個全新 WebAPI 網站,裡面有個簡單的天氣預報 WebAPI 範例。由於專案已整合Swagger UI,執行網站輸入 /swagger 網址,我們可以從網頁看到所有 WebAPI 方法及參數資訊:
甚至可以從網頁介面輸入參數按執行看結果:
Swagger.json / OpenAPI 是公開標準,用 NSwag Studio 之類工具可自動產生呼叫端程式碼(不限 C#,其他語言平台也都找得到工具),我們只需專心寫好 WebAPI 邏輯,剩下工作都有現成介面與工具接手,叫人怎能捨得走出舒適圈?
不過,雖然選用 WebAPI 範本,在設計上我倒沒想轉向 RESTful 哲學 - 用 URI 指定資源、用 Get()、Post()、Put()、Delete() 方法對映動作。我仍然偏好在同一 Controller 用不同 Action 名稱定義多個方法的做法,覺得這樣比較簡單輕巧。
註:更詳細的理由可參考閒聊 - Web API 是否一定要 RESTful?一文,RESTful 與否見仁見智,若你偏好 RESTful 精神,文章後面可以跳過了。
不過,以 WebApi 專案範本中的 WeatherForecastController 為例,由於其宣告了 [ApiController] Attribute,預設要依循 RESTful 規則,一個 Controller 只能有一個 HTTP Get、一個 Post,若試著再加一個[HttpGet]方法(如以下的 GetNowString),將會得到 SwaggerGeneratorException: Conflicting method/path combination "GET WeatherForecast" for actions - WebApiDemo.Controllers.WeatherForecastController.GetNowString (WebApiDemo),WebApiDemo.Controllers.WeatherForecastController.Get (WebApiDemo). Actions require a unique method/path combination for Swagger/OpenAPI 3.0. Use ConflictingActionsResolver as a workaround
錯誤:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
//...省略...
[HttpGet]
public string GetNowString()
{
return DateTime.Now.ToString();
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
所幸,這問題一點也不難解,只需加上一行 [Route("[action]")] 就可以囉。以下一併示範無參數,用 URL 路徑傳參數及 Query String 參數寫法:
[HttpGet]
[Route("[action]")]
public string GetNowString()
{
return DateTime.Now.ToString();
}
[HttpGet]
[Route("[action]/{id}")]
public string EchoId(int id)
{
return id.ToString();
}
[HttpGet]
[Route("[action]")]
public string AddNumbers(int a, int b)
{
return (a + b).ToString();
}
成功!
感謝讀者 Chin Khai Hong 補充,路由設定亦可直接寫在 HttpGet 或 HttpPost,例如:HttpGet("[action]")。參考: Attribute routing with Http verb attributes
學會以上技巧,我們便能彈性擴充 ApiController,加入名稱不同的 HttpGet 或 HttpPost 方法,既享受 Swagger 整合,又不必受限於 RESTful 規則,兩全其美。
Tips of how to add multiple HttpGet or HttpPost actions in ASP.NET Core ApiController.
Comments
# by 小黑
感謝黑大~ 請教,WebApi 發行佈署後,能否有效的移除swagger 網頁?
# by Jeffrey
to 小黑,專案模版的 SwaggerUI 設定原本就只會在開發環境啟用 if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); }
# by UwUtencell
Fly
# by UwUtencell
Fly