如何使用 .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] |
- 使用
HttpPost
attribute 描述LoginMember
使用 POST action - 使用
FromBody
attribute 描述 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 提供了
HttpPost
attribute 與FromBody
attribute,讓我們簡單的將 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 上找到