使用 ASP.NET Core MVC 創建 Web API 使用 ASP.NET Core MVC 創建 Web API(一) 使用 ASP.NET Core MVC 創建 Web API(二) 使用 ASP.NET Core MVC 創建 Web API(三) 十三、返回值 在上一篇文章(使用 ...
使用 ASP.NET Core MVC 創建 Web API
使用 ASP.NET Core MVC 創建 Web API(一)
使用 ASP.NET Core MVC 創建 Web API(二)
使用 ASP.NET Core MVC 創建 Web API(三)
十三、返回值
在上一篇文章(使用 ASP.NET Core MVC 創建 Web API(二))中我們創建了GetBookItems和 GetBookItem兩個方法,這兩個方法的返回類型是 ActionResult<T> 類型。 ASP.NET Core 自動將對象序列化為 JSON,並將 JSON 寫入響應消息的正文中。 GetBookItems和 GetBookItem方法正確執行,沒有未經處理的異常的情況下,返回類型的響應代碼為200。如果有未經處理的異常返回的響應代碼為5xx。
一些操作方法的結果返回類型會是特殊格式,例如 JsonResult
和 ContentResult
。操作可以返回始終以特定方式進行格式設置的特定結果。 例如,返回 JsonResult
將返回 JSON 格式的數據,而不考慮客戶端首選項。 同樣,返回 ContentResult
將返回純文本格式的字元串數據(僅返回字元串也是如此)。
ActionResult
返回類型可以表示大範圍的 HTTP狀態代碼。例如, 在上一篇文章(使用 ASP.NET Core MVC 創建 Web API(二))我們創建的GetBookItem方法可以返回兩個不同的狀態值,如下:
1) 如果沒有資料庫中沒有存在與請求 ID相匹配的書籍信息,則該方法將返回 404 NotFound 錯誤代碼。如下圖。
2)如果資料庫中存在與請求ID相匹配的書籍信息,則此方法將返回 JSON格式數據的響應正文,並且產生 HTTP 200 響應。 如下圖。
一)特定類型
在應用程式中我們對於操作方法的返回值最簡單做法是返回.NET簡單類型或複雜數據類型(如 string
或自定義對象類型)。請參考以下代碼,該操作方法返回自定義 Book
對象的集合:
public Book GetBook(int id) { var bookItem = _context.Book.Find(id); return bookItem; }
1)在執行操作方法期間無需考慮已知條件時,返回特定類型即可滿足要求。
2)當在操作方法執行期間需要考慮已知條件時,可能會有多個結果類型需要返回。在這種情況下,通常會將返回類型設為ActionResult或 ActionResult<T>,這樣就可以返回基本簡單類型或複雜返類型。
二)IActionResult 類型
當操作方法存在多個 ActionResult 需要返回時,適合使用 IActionResult 返回類型。 ActionResult
類型表示多種 HTTP 狀態代碼。 屬於此類別的一些常見返回類型包括:BadRequestResult (400)、NotFoundResult (404) 和 OkObjectResult (200)。
由於操作中有多個返回類型和路徑,因此可以使用 [ProducesResponseType] 特性。 此特性方便 Swagger 等工具生成的 API 幫助頁生成更多描述性響應詳細信息。 [ProducesResponseType]
指示操作將返回的已知類型和 HTTP 狀態代碼。如下麵的示例:
[HttpGet("{id}")] [ProducesResponseType(typeof(Book), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async IActionResult GetBookById(int id) { var bookItem = await _context.Book.FindAsync(id); if (bookItem == null) { return NotFound(); } return Ok(bookItem); }
在上面的代碼中,當與id相匹配
的書籍不存在資料庫中時,則返回 404 狀態代碼。 調用 NotFound 幫助程式方法作為 return new NotFoundResult();
的快捷方式。 如果書籍信息存在資料庫中,則返回代表有效負載的 bookItem對象和狀態代碼 200。 調用 Ok 幫助程式方法作為 return new OkObjectResult(bookItem);
的快捷方式。
三)ActionResult<T> 類型
ASP.NET Core 2.1 引入了面向 Web API 控制器操作的 ActionResult<T> 返回類型。 它支持返回從 ActionResult 派生的類型或返回特定類型。 ActionResult<T>
通過 IActionResult 類型可提供以下優勢:
1) 可排除 [ProducesResponseType] 特性的 Type
屬性。 例如,[ProducesResponseType(200, Type = typeof(
Book))]
可簡化為 [ProducesResponseType(200)]
。 此操作的預期返回類型改為根據 ActionResult<T>
中的 T
進行推斷。
2) 隱式強制轉換運算符支持將 T
和 ActionResult
均轉換為 ActionResult<T>
。 將 T
轉換為 ObjectResult,也就是將 return new ObjectResult(T);
簡化為 return T;
。
C# 不支持對介面使用隱式強制轉換運算符。 因此,必須使用 ActionResult<T>
,才能將介面轉換為具體類型。 例如,在下麵的示例中,使用 IEnumerable
返回全部書籍信息:
[HttpGet] public async Task<ActionResult<IEnumerable<Book>>> GetBookItems() { return await _context.Book.ToListAsync(); }
大多數操作具有特定返回類型。 執行操作期間可能出現意外情況,不返回特定類型就是其中之一。 例如,操作的輸入參數可能無法通過模型驗證。 在此情況下,通常會返回相應的 ActionResult
類型,而不是特定類型。
十四、添加新增方法
接下來我們來實現一個新增方法,在WEB API中使用什麼來實現新增方法呢?
特性[HttpPost]指示這個方法接收HTTP POST方法請求傳過來的數據,並從 HTTP 請求正文中獲取書籍信息的值。
在Visual Studio 2017中打開BookController.cs文件,在文件中添加以下 PostBookItem
方法:
// POST: api/Book [HttpPost] public async Task<ActionResult<Book>> PostBookItem(Book item) { _context.Book.Add(item); await _context.SaveChangesAsync(); return CreatedAtAction(nameof(GetBookItem), new { id = item.ID }, item); }
對於CreatedAtAction
方法的說明:
- 如果成功,則返回 HTTP 201 狀態代碼。 HTTP 201 是在伺服器上創建新資源的 HTTP POST 方法的標準響應。
- 將
Location
標頭添加到響應。Location
標頭指定新建的書籍信息的 URI。 - 引用 GetBookItem操作以創建
Location
標頭的 URI。 C#nameof
關鍵字用於避免在CreatedAtAction
調用中硬編碼操作名稱。
一)測試 PostBookItem 方法
1) 在Visual Studio 2017中按F5,啟動BookApi應用程式。
2) 打開Firefox瀏覽器,並打開 Rester,在Reseter中,將 HTTP 方法設置為 POST
。
3) 選擇“Headers”選項卡,選擇“Content-Type”選項,並將值設置為 JSON (application/json),如下圖。
4) 然後選擇“BODY”選項卡,在請求正文中,輸入我們想新增的書籍信息的 JSON,如下圖:
JSON字元串:
{"name":"Python編程實踐","releaseDate":"2018-02-12","price":55.49,"author":"馬瑟斯","publishing":"機械工業出版社"}
5) 使用滑鼠左鍵,單擊“SEND”按鈕。成功創建了一條新的書籍信息,返迴響應為201。如下圖。
如果收到 500內部伺服器錯誤,則檢查代碼與數據是否符合資料庫要求,405 不允許的方法錯誤,則可能是由於未在添加 PostBookItem
方法之後編譯項目。
二) 測試位置標頭 URI
6) 在前文我們對代碼進行過解釋,成功創建新的書籍信息之後,響應返回中的Location
標頭指向新建的書籍信息的 URI。接下來我們來測試一下,在“Response”窗格中複製“位置”標頭值,如下圖。
7) 在Rester中把方法設置為“GET”。
8) 在URL輸入框中,粘貼剛纔複製的 URI(例如,https://localhost:5000/api/Book/24
),如下圖。
9) 選擇“SEND”,我們會獲取ID=24的書籍信息,就是我們剛纔新增的書籍信息。如下圖。