如何使用 .NET Core 開發 Web API (GET) ?
當前後端分離後,後端退守 API,使用 .NET Core 實現 Web API 為最常見的功能,本文將以實務上常使用的 查詢會員
為範例,示範如何實作出 GET action 的 Web API。
Version
macOS High Sierra 10.13.4
.NET Core 2.1
Rider 2018.2
Paw 3.1.5
Check API (GET)
Is Member
使用
GET
,http://localhost:5001/api/exists/Sam
查詢回傳
1 | { |
若為會員,會回傳 exists
為 true
。
Not Member
使用
GET
,http://localhost:5001/api/exists/Kevin
回傳
1 | { |
若為會員,會回傳 exists
為 false
。
ExistsController.cs
1 | using System.Collections.Generic; |
12 行
1 | private readonly List<Member> _members |
為簡化起見,就沒從 database 判斷 username 與 password,暫時將資料放在 List
內。
16 行
1 | [HttpGet("{username}")] |
- 使用
HttpGet
attribute 描述LoginMember
使用 GET action - 回傳值
Response
自訂型別,被包在 .NET Core 規定的ActionResult
內
19 行
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) => x.Username == username; |
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 很短,很容易看到看到其型別定義,所以沒有閱讀與維護的問題。
27 行
1 | Member DefaultMember() |
DefaultMember()
Local Function,主要提供 DefaultIfEmpty()
所需要的 default object。
32 行
1 | Response Result(Member x) |
Result()
Local Function,主要提供 Select()
所需要的 data 與型別轉換。
Conclusion
- .NET Core 提供了
HttpGet
attribute,讓我們簡單的將 Controller 的 Method 提供 Web API 的 GET 服務 - 使用 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 上找到