創建一個好的API需要特別注意一些事情,本文介紹的7個技巧將幫助開發人員在使用ASP.NET Core時輕鬆創建更好的API。
好的API由許多因素組成,包括日誌、文檔、性能等。隨着Web API的流行,實現好的API是作爲Web開發人員的日常工作中非常常見的任務,特別是使用Microsoft的技術,如ASP.NET Core。
Telerik_KendoUI產品技術交流羣:726377843 歡迎一起進羣討論
Tip 1:寫出好的端點
總是使用名詞
在創建端點時,總是使用名詞替代動詞,請看下面錯誤的方法和正確的方法。
命名約定
雖然在命名方面存在差異,但很常見的是,技術巨頭的url總是使用小寫字母。如果有必要使用一個由多個名詞組成的單詞,請嘗試使用下劃線(_)或破折號(-)將它們分開。示例如下:
名詞是複數還是單數?
如前所述,應該使用名詞替代動詞,但常見的問題是這些名詞是用複數還是單數來寫。
答案是沒有正確的形式,部分開發者更喜歡用複數形式,因爲這樣它們表示一組可以是一個或多個的特徵。當使用單數時,將端點限制爲一項。
無論您使用哪種方式,目標始終是簡化。
版本
API在第一次發佈後不斷髮展是很常見的,因此爲同一個API創建不同版本非常重要。許多公司選擇在端點中明確表示,即通過字母“v”+版本號表示API版本。所以,通常在第一個版本中我們看到“v1”
對API進行版本控制有助於系統維護,使用v1端點的系統不會受到影響,因爲所有更改都在另一個端點上可用——在本例中爲v2。
但重要的是要明確這不是強制性的,許多公司通常不爲他們的API創建版本,在這種情況下,將創建新的API並替換就得API。
Tip 2:使用正確的HTTP動詞
首先,開發人員應該學習HTTP的基礎知識。
以下是主要的HTTP動詞及其各自的功能:
使用正確的HTTP狀態碼
HTTP中一個有價值的特性是狀態,這些狀態在服務器響應中返回,這取決於請求中發送的操作結果,可能是命中,也可能是失敗。不管結果如何,有幾種類型的狀態——由開發人員根據情況實現正確的狀態。
例如,API通過查詢字符串接收對方的id。如果數據庫中存在該id, API將返回相應對方的數據。如果不是,API返回一個帶有詳細描述的錯誤。以下是兩種場景:
1. 發現對方
HTTP/1.1 200 OK Content-Type: text/html { "status": "success", "data": { { "idSeller": "100002132", "name": "SellerExample", "offerCode": "4", "smallSeller": false } } }
2. 未發現對方
HTTP/1.1 404 Not Found Content-Type: text/html { "status": "error", "messages": [ { "code": "018", "message": "Seller not found" } ] }
另一個要點是返回狀態的一致使用。例如,在success這個例子中,每個動詞都有一個常用的模式。
- GET: 200 OK
- POST: 201 Created
- PUT: 200 OK
- DELETE: 204 No Content
- PATCH: 200 OK
Tip 3:避免將業務規則放在端點上
API的端點用於數據的輸入和輸出,因此最好的選擇是創建一個類(通常稱爲Service),將業務規則放在其中,然後在端點上調用服務類的主方法。如下面的例子所示:
❌ Wrong:
app.MapPost("v1/products", (Product product, ProductDbContext dbContext) => { string errorMessage = string.Empty; if (string.IsNullOrEmpty(product.Name)) errorMessage += "Name is mandatory"; if (string.IsNullOrEmpty(product.Category)) errorMessage += "Category is mandatory"; if (!string.IsNullOrEmpty(product.Name)) Results.BadRequest("Error creating the product"); else { dbContext.Products.Add(product); dbContext.SaveChanges(); return Results.Ok(); } }).WithName("CreateProduct");
✅ Correct:
app.MapPost("v1/products", (ProductService service, Product product) => { var resultMessage = service.Create(product); if (!string.IsNullOrEmpty(resultMessage)) Results.BadRequest($"Error creating the product, error validation: {resultMessage}"); return Results.Ok(); }).WithName("CreateProduct");
Tip 4:使用分頁和過濾
應用程序隨着時間的推移而增長是很常見的,允許API使用者根據需要選擇只獲得一定數量的項是很重要的,對此的一個建議是分頁。
要實現分頁而不要求數據庫提供太多性能,最好的方法是提供可以“切割”記錄集合的參數(標識符)和數量限制器。
你可以在下面看到一個好的和壞的例子,在第一個示例中,沒有分頁選項或限制。在第二種情況下,可以在端點路由中注意到這些參數。
Tip 5:使運行狀況端點可用
讓所有消費者都可以使用Health路由是一種很好的實踐,顧名思義,該路徑用於檢查API的運行狀況。在這種情況下,不僅API可用,而且可以檢查API依賴關係並返回在每個API中獲得的結果。
例如,在需要在外部API中生成令牌的API中,開發人員可以檢入運行狀況端點(如果該外部API可用)並在運行狀況路由中返回檢查結果。
因此,在API返回錯誤500(內部服務器錯誤)的情況下,消費者可以快速知道問題的原因可能在哪裏,下面是運行狀況端點的示例。
GET - v1/products/health
app.MapGet("v1/products/health", (ProductService service) => { var externalAPIResponse = service.ExternalAPIHealthVerify(); return Results.Ok($"External API response: {externalAPIResponse.StatusCode} - {externalAPIResponse.Message}"); }).WithName("Health");
Tip 6:使用API緩存
緩存是一種用於存儲頻繁使用的數據的技術,它非常有用,因爲它旨在通過將數據存儲在易於訪問的地方來獲得性能並減少web/數據庫服務的負載,這些地方可以是內存內緩存(服務器的內存)、持久進程內緩存(文件或數據庫)或分佈式緩存(多進程)。
下面可以看到一個在ASP. NET Core Web API中實現內存緩存的例子。
app.MapGet ("v1/products", (ProductService service) => { const string ProductsKey = "_Products"; if (!cache.TryGetValue(ProductsKey, out List<Product> products)) { products = service.GetAll(); var cacheEntryOptions = new MemoryCacheEntryOptions { AbsoluteExpiration = DateTime.Now.AddMinutes(3), SlidingExpiration = TimeSpan.FromMinutes(2), Size = 1024, }; cache.Set(ProductsKey, products, cacheEntryOptions); } return Results.Ok(products); }).WithName("GetProducts");
Tip 7:編寫好的文檔
在開發API時,編寫好的文檔是必不可少的——畢竟,開發人員將通過文檔實現API的使用者。
大公司使用彼此非常相似的模型來提供關於其API的文檔,它通常是一個非常簡單的網頁,包含了從頭開始創建的所需的所有信息。
以下是良好文檔的一些要求。
- 對API函數做一個簡單的描述,始終添加關於任何業務規則的重要細節。例如:“要取消購買,您需要在下訂單後等待24小時……”
- 始終將請求和響應分開,對於它們中的每一個,提供HTTP謂詞和要訪問的路由,並在Request中發送並在Response中返回一個數據示例。
- 如果API包含一些複雜性,請始終提供流程流程圖——使用圖像描述流程比使用文字描述流程更直觀。