如何使用 .NET Core 開發 Web API (POST) ?
當前後端分離後,後端退守 API,使用 .NET Core 實現 Web API 為最常見的功能,本文將以實務上常使用的 會員登入 為範例,示範如何實作出 POST action 的 Web API。
Version
macOS High Sierra 10.13.4
.NET Core 2.1
Rider 2018.2
Paw 3.1.5
Login API (POST)
Login Success

- 使用
POST,http://localhost:5001/api/login - 傳入
1 | { |
- 回傳
1 | { |
若 login 成功,會回傳 success 為 true,與 username 為 user 名稱。
Login Failed

- 使用
POST,http://localhost:5001/api/login - 傳入
1 | { |
- 回傳
1 | { |
若 login 失敗,會回傳 success 為 false,與 username 為 空白。
LoginController.cs
1 | using System.Collections.Generic; |
12 行
1 | private readonly List<Member> _members |
為簡化起見,就沒從 database 判斷 username 與 password,暫時將資料放在 List 內。
16 行
1 | [HttpPost] |
- 使用
HttpPostattribute 描述LoginMember使用 POST action - 使用
FromBodyattribute 描述 data 來自於 Body,並且自動轉型Member自訂型別 - 回傳值
Response自訂型別,被包在 .NET Core 規定的ActionResult內
25 行
1 | return _members |
Where():判斷資料是否在 List 內
LINQ 的
Where()相當於 FP 的filter()
DefaultIfEmpty() :Where() 一定可能找不到資料,因此會回傳 null,但 null 相當於癌細胞,只要一使用到 null,就必須到處判斷 null ,非常麻煩,而且只要有一個地方沒判斷到 null,程式就可能在 run-time 出錯。
比較好的方式是在 Where() 之後馬上配上 DefaultIfEmpty() 描述,只要 Where() 找不到資料,就不會回傳 null,而是回傳 default object。
DefaultIfEmpty()就是 LINQ 支援 Null Object Pattern / Default Object Pattern 的一種實現
Select():我們要回傳的是 Response 自訂型別,而不是 Member 型別,勢必要做轉換,Select() 幫我們將 Member 自訂型別轉成 Result 自訂型別。
LINQ 的
Select()相當於 FP 的map()
First():別忘了 Select() 的轉換有個特色:原本是 Collection,Select() 之後還是 Collection,但我們要的是 Response,因此使用 First() 只取一筆 Response。
25 行
1 | bool IsMember(Member x) |
IsMember() Local Function,提供 Where() 的 Predicate Function。
Q : Parameter 使用
x符合 Clean Code 原則 ?
Local Function 與 Lambda 強調的就是 function 要短要小,且常常配合 Body Expression,若 parameter 名稱取太長,Lambda 就不美了。
由於 Lambda 來自於數學,一般會採用數學 y = f(x) 習慣,使用 x、y、z 即可。
x 會難閱讀嗎 ? 由於 Local Function 與 Lambda 很短,很容易看到看到其型別定義,所以沒有閱讀與維護的問題。
28 行
1 | Member DefaultMember() |
DefaultMember() Local Function,主要提供 DefaultIfEmpty() 所需要的 default object。
31 行
1 | Response Result(Member x) |
Result() Local Function,主要提供 Select() 所需要的 data 與型別轉換。
Conclusion
- .NET Core 提供了
HttpPostattribute 與FromBodyattribute,讓我們簡單的將 Controller 的 Method 提供 Web API 的 POST 服務 - 使用 LINQ 的
Where()與DefaultIfEmpty()讓我們避開null魔咒,不用再到處判斷null,也就是所謂的 Null Object Pattern 或 Default Object Pattern 的實踐 - Local Function 與 Lambda 的 parameter 可以打破 OOP 與 Imperative 的習慣,以
x、y、z命名即可,因為 Lambda 功能都很單一,且 function 很短,不像 Imperative 會拉很長,因此才需要取有意義的 parameter 名稱
Sample Code
完整的範例可以在我的 GitHub 上找到