這里GET可以理解為獲取(查詢)資源, POST為添加資源, PUT為整體更新資源, PATCH為局部更新資源, DELETE為刪除資源.

這里需要提的是后兩個:

建立Controller

首先需要建立一個CountryController:

注意在CountryController上面標注的[Route]屬性標簽,它的值是整個Controller下所有的Action的路由前綴,可以寫成固定的地址,也可以寫成”api/[controller]”, 其中[controller]這部分會變成這個Controller的名字,這里也就是”api/country”.

如果使用[controller]的話,如果Controller重構后名字改了,那么該Controller的路由地址也就是資源的地址也就改了,這樣很不好,所以建議還是寫成固定的地址不要使用[controller]。

GET 資源

GET 所有的Country:

(AutoMapper的使用方法這里就不介紹了)

 GET 一個Country:

這兩個方法里返回的都是JsonResult,這看起來沒什么問題,因為我們想要的就是JSON格式的結果。以第二個方法為例,使用POSTMAN測試,如果能查詢到數(shù)據(jù):

這是沒有問題的,但是如果查詢一個不存在的資源:

這就有問題了,如果查詢不到資源,那么返回的應該是404 NOF FOUND 而不是200 OK.

狀態(tài)碼

狀態(tài)碼是非常重要的,因為只有狀態(tài)碼會告訴API的消費者:

下面再列舉一下web API會用到的狀態(tài)碼:

200級別,表示成功:

400級別,表示客戶端引起的錯誤:

500級別,服務器錯誤:

回到剛才的那兩個方法,默認情況下 JsonResult會返回200 OK狀態(tài)碼,可以去修改JsonResult以支持其它的狀態(tài)碼。但是Controller里提供了一些幫助方法返回IActionResult并指定特定的狀態(tài)碼,針對200,就是Ok()方法。

這時就不需要手動返回JsonResult了。

這里需要注意的是,針對集合的內容協(xié)商,如果集合是空的,也不應該返回404,因為這個Country資源是存在的,只不過它的內容是空的而已。

然后看一下GET 特定單個資源:

針對單個資源,如果沒有找到,就需要返回404 Not Found,這時就可以使用Controller的幫助方法 NotFound().

處理異常

當Action發(fā)生異常的時候,默認情況下ASP.NET Core會返回500:

但還是自己處理一下比較好,可以在Action里面使用try catch:

這里由于是服務器的錯誤,所以應該返回500狀態(tài)碼 Internal Server Error。

注意這里不應該返回Exception,因為這是程序的內部實現(xiàn)細節(jié),再說它對客戶來說也沒什么用。

此外,我們還可以全局處理異常。

在Startup里面的Configure方法:

使用app.UseExceptionHandler(),里面可以自定義一些邏輯。如果這地方代碼比較多的話,可以把它封裝成一個擴展方法,然后使用app.Usexxx的形式調用。

回頭我把Action里面的try catch去掉試試,但是這里要注意把環(huán)境變量ASPNETCORE_ENVIRONMENT的值改成Production(其實不是Development就可以):

GET 父子關系的資源

這是一個典型的情景,一個國家包含多個城市,這就是父子關系。

首先看一下domain model:

這個應該很簡單。

此外還要建立CityResource,Repository和IRepository,注冊配置,種子數(shù)據(jù)等等,這些就不貼了。

下面建立CityController

前面提到過,針對父子、主從關系的資源,其子資源的路由地址應該是上面這樣的,由于該Controller下所有的Action的路由前綴都是一樣的,所以把這個路由放到了Controller級別作為所有Action的前綴。

GET方法本身比較簡單,沒什么說的,里面涉及的一些方法請自行編寫。

看看運行結果:

如果找不到Country,則返回404:

下面GET 單個city:

注意,單個資源找不到就應該返回404,而空集合怎不是,這個前面也提過。

找到資源的結果:

找不到country或者city的時候都應該返回404,就不貼圖了。

內容協(xié)商

簡單來說就是,如果資源支持多種展現(xiàn)格式,那么消費者可以選擇它想要的格式。

這里就要用到media type,它可以通過請求的Accept Header來傳遞,常見的有:

application/json 和 application/xml…等等

在沒有指定Accept Header的情況下,就該返回一個默認的格式,在ASP.NET Core 2.0里面就是application/json

當請求的media type不可用的時候,并且消費者不支持默認格式,這時服務器就應該返回 406 Not Acceptable 狀態(tài)碼。

ASP.NET Core 支持輸出和輸入兩種格式化器。

輸出的media type在accept header里面,而輸入的media type在content-type header里面。

看一下當前的情況,請求的Accept Header為application/json時:

請求的Accept Header為application/xml時:

它們返回的都是json格式的。

因為服務器(項目)現(xiàn)在不支持xml,所以返回了默認的json格式,但嚴格來說,這樣做不正確,所以需要處理一下。

在Startup里,ConfigureServices方法:

把這個ReturnHttpNotAcceptable屬性設為true,如果想要的格式不支持,那么就會返回406 Not Acceptable:

不指定Accept Header的情況下就返回默認的json格式:

下面,為項目添加Xml輸出格式的支持:

再試試:

這時就成功的返回了xml

創(chuàng)建資源

首先了解一下方法的安全性和冪等性。

安全性是指方法執(zhí)行后并不會改變資源的表述。

冪等性是指方法無論執(zhí)行多少次都會得到同樣的結果。

下面是HTTP方法的安全性和冪等性列表:

參考這個列表可以幫助決定在某種情況下用哪種HTTP方法。

下面看看創(chuàng)建Country的代碼:

這個代碼很簡單,數(shù)據(jù)是從請求的body帶進來的。

需要注意的是返回什么,如果POST操作執(zhí)行成功的話,標準的做法是返回201 Created 狀態(tài)碼。

在這里就可以使用CreatedAtRoute() 這個方法,它允許響應里帶著Location Header,在這個Location Header里包含著一個uri,通過這個uri就可以GET到我們剛剛創(chuàng)建好的資源(Country)。

這個方法的第一個參數(shù)是一個路由名,使用這個路由名可以用來生成剛才提到的uri。在本例里,這個路由名應該對應的是GetCountry這個Action方法,所以為這個Action添加路由名:

這樣就和Post方法返回中用到的路由名一致了,第二個參數(shù)是一個匿名類里面有個屬性id,它會編程路由里的參數(shù),最后一個參數(shù)是響應會返回的數(shù)據(jù)。

下面進行測試,發(fā)送請求的時候別忘了設置Content-type為applicaiton/json:

然后是數(shù)據(jù):

然后發(fā)送請求,查看響應的body部分:

再看響應的header:

這里可以看到Location Header的uri,通過這個uri,你就可以GET到這個剛剛創(chuàng)建的Country資源,這里我就不測試了。

如果再次執(zhí)行這個POST操作,看看結果:

這次返回的數(shù)據(jù)的id為6,與前面不一樣,所以POST不是冪等的,它每次執(zhí)行后的結果是不一樣的。

創(chuàng)建子資源

Country的創(chuàng)建做完了,現(xiàn)在可以創(chuàng)建City了。

這個跟上面的差不多,只不過注意需要一下路由的參數(shù)即可。

測試:

同時創(chuàng)建父子資源

這是個常見的需求,一個Country和它下屬的Cities同時被傳遞進來,然后在Action里一同創(chuàng)建。

首先需要修改CountryAddResource:

然后,就沒有然后了,所有的映射操作都交給AutoMapper和EntityFramework Core了。。

測試:

然后GET這兩個Cities:

創(chuàng)建集合資源

這次我要一次性添加一個集合的Countries。

由于Country的集合相當于是另外一種資源,所以可以把它放到單獨的Controller里面,不放也沒問題。

這個其實也沒什么特別的,注意傳進來的參數(shù)是IEnumerable。為了方便,暫時先返回OK()。

測試:

OK, 下面解決返回的問題.

我們要返回的是CreatedAtRoute方法, 由于里面要包含可以返回該集合資源的路由地址, 所以需要創(chuàng)建一個Action, 它的參數(shù)應該是POST方法返回數(shù)據(jù)的Id的集合. 但是由于路由參數(shù)不支持集合形式, 只能以字符串形式傳遞, 所以可以做成這樣的路由參數(shù): api/xx/(1,2,3,4,5).

而Action方法呢, 接受的參數(shù)應該是Id的集合, 應該是一個集合類型, 所以我們可以使用ModelBinder把id字符串轉化為id的集合:

然后, 還需要對應這個POST Action 做一個GET集合的Action 方法:

這個Action所期待的參數(shù)類型是Id的集合, 而實際傳入的是id的字符串, 通過ArrayModelBinder來實現(xiàn)轉化.

最后修改POST方法的返回:

測試一下:

然后再GET這個鏈接:

如果POST到單個資源的地址

如果POST到這個地址 http://localhost:5000/api/countries/{id}, 

那么, 如果該id的資源不存在, 則應該返回404;

如果該id的資源存在, 則應該返回409 Conflict.

(POST不是冪等性的, 它無法多次請求都產生同樣的結果).

測試一下id的資源不存在的情況:

在測試一下Id的資源存在的情況:

還是404, 這個不行, 所以需要手動處理:

看看結果:

OK, 無論是Id存在的資源還是不存在的資源都會返回正確的狀態(tài)碼.

支持輸入其它類型的Content-Type

之前講過如何返回xml的格式, 下面介紹一下如何使用xml格式進行請求, 首先在Startup.cs里面添加這個:

然后, 需要把請求的Content-Type設為application/xml:

我就不適用xml數(shù)據(jù)進行測試了.

文章轉自微信公眾號@朗坤技術團隊

上一篇:

在 ASP .NET Core中通過 Web API 中將 HTML 轉換為 PDF

下一篇:

Asp.Net Core 5 REST API
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數(shù)據(jù)驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費