使用ASP.NET Core 3.x 構建 RESTful API – 3.3 狀態碼、錯誤/故障、ProblemDetails
- 2019 年 12 月 20 日
- 筆記
HTTP狀態碼
HTTP狀態碼會告訴API的消費者以下事情:
- 請求是否執行成功了
- 如果請求失敗了,那麼誰為它負責
HTTP的狀態碼有很多,但是Web API不一定需要支援所有的狀態碼。HTTP狀態碼一共分為5個級別:
- 1xx,屬於資訊性的狀態碼。Web API並不使用1xx的狀態碼。
- 2xx,意味著請求執行的很成功。
- 200 – Ok,表示請求成功;
- 201 – Created,請求成功並創建了資源;
- 204 – No Content,請求成功,但是不應該返回任何東西,例如刪除操作。
- 3xx,用於跳轉。例如告訴搜素引擎,某個頁面的網址已經永久的改變了。絕大多數的Web API都不需要使用這類狀態碼。
- 4xx,客戶端錯誤:
- 400 – Bad Request,表示API消費者發送到伺服器的請求是有錯誤的;
- 401 – Unauthorized,表示沒有提供授權資訊或者提供的授權資訊不正確;
- 403 – Forbidden,表示身份認證已經成功,但是已認證的用戶卻無法訪問請求的資源;
- 404 – Not Found,表示請求的資源不存在;
- 405 – Method not allowed,當嘗試發送請求到資源的時候,使用了不被支援的HTTP方法時,就會返回405狀態碼;
- 406 – Not acceptable,這表示API消費者請求的表述格式並不被Web API所支援,並且API不會提供默認的表述格式。例如請求的媒體類型是application/xml,但是Web API僅支援application/json類型,並且API不會將application/json作為默認格式提供;
- 409 – Conflict,表示請求與伺服器當前狀態衝突。通常指更新資源時發生的衝突,例如,當你編輯某個資源的時候,該資源在伺服器上又進行了更新,所以你編輯的資源版本和伺服器的不一致。當然有時候也用來表示你想要創建的資源在伺服器上已經存在了。它就是用來處理並發問題的狀態碼。
- 415 – Unsupported media type,與406正好相反,有一些請求必須帶著數據發往伺服器,這些數據都屬於特定的媒體類型,如果API不支援該媒體類型格式,415就會被返回。
- 422 – Unprocessable entity,它是HTTP擴展協議的一部分。它說明伺服器已經懂得了實體的Content Type,也就是說415狀態碼肯定不合適;此外,實體的語法也沒有問題,所以400也不合適。但是伺服器仍然無法處理這個實體數據,這時就可以返回422。所以它通常是用來表示語意上有錯誤,通常就表示實體驗證的錯誤。
- 5xx,伺服器錯誤:
- 500 – Internal server error,表示伺服器出現了錯誤,客戶端無能為力,只能以後再試試了。
錯誤和故障
系統時不時的會出現一些問題,這些問題可以劃分為兩類:錯誤和故障。
錯誤 Errors
錯誤通常是由API的消費者引起的。API消費者請求時傳遞的數據是不合理的,這時API就會正常的將其拒絕。例如,請求的憑證是不合理的,或者請求的參數不合理等等。
這些就是HTTP 4xx錯誤。
錯誤並不會影響API的可用性。
故障 Faults
故障是指,針對一個合理的請求,API無法返回它的響應。 換句話說就是API引起的問題。
這些是HTTP 5xx錯誤。
故障確實會對API整體的可用性造成影響。
ProblemDetails
當ASP.NET Core 大約在 2.1 版本的時候,它引入了 ProblemDetails。ProblemDetails是基於 RFC7807 這個規範,目的是讓 HTTP 響應可以攜帶錯誤的詳細資訊,而不是只返回一個錯誤的狀態碼。
在 ASP.NET Core 2.2的時候,如果Controller使用了 [ApiController] 這個屬性,那麼 ProblemDetails 就是客戶端錯誤碼的標準響應。
例如,當返回類型為 IActionResult 的方法返回客戶端錯誤狀態碼的時候(4xx),同時還會返回一個body,這個 body 就是 ProblemDetails。 這個結果里還會包含著一個相關的ID,使用這個ID,就可以把錯誤和相應的請求日誌關聯起來。
關於ProblemDetails這個類,可以查看:官方文檔。
為了使用ProblemDetails?
- 需要為應用程式定義一個通用的錯誤顯示格式;
- 很多時候,只返回HTTP狀態碼並不能表達和傳遞出足夠的資訊。
在ASP.NET Core 3.x裡面,同樣也使用了 ProblemDetails。
看一個返回404的例子:

這是一個Get請求,但是並沒有找到該資源,返回的狀態碼是404,而響應的body就是 ProblemDetails。
值得注意的是,這個響應的 Content-Type 是 application/problem+json:
