3

ASP.NET MVC 回傳 HTTP 400 Bad Request 並附加錯誤訊息

 3 years ago
source link: https://blog.darkthread.net/blog/aspnetmvc-return-http-400-with-result/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
ASP.NET MVC 回傳 HTTP 400 Bad Request 並附加錯誤訊息-黑暗執行緒

同事的專案遇到以下需求:依規格實作 WebAPI (考量開發彈性,使用 ASP.NET MVC Controller,未走 ApiController ),規格定義遇到某些狀況需抛回 HTTP 400 Bad Rquest 並以 JSON 格式回傳錯誤訊息。

一開始的寫法如下:

排版顯示純文字
        public ActionResult BadRequestFail()
        {
            Response.SetStatus(HttpStatusCode.BadRequest);
            return Content(
                "{ \"error\": \"朕不給的,你不能拿!\" }", "application/json");
        }

實測不成功。Response.SetStatus(HttpStatusCode.BadRequest) 雖然有傳回 HTTP 400,但 Body 無內容,return 的 Content() 消失無蹤。

4393-e290-o.gif

經爬文與實驗後,獲得以下心得:

  1. 使用 Response.SetStatus(HttpStatusCode.BadRequest) 會中止 Reponse,導致 return Content() 被無視。由 System.Web.WebPages.ResponseExtensions 原始碼可證實此點:
    排版顯示純文字
    public static void SetStatus(this HttpResponseBase response, int httpStatusCode)
    {
        response.StatusCode = httpStatusCode;
        response.End();
    }
  2. Response.StatusCode 屬性支援寫入,不用 SetStatus() 改成直接指定 StatusCode = 400 可避免 Response.End()。
  3. IIS 遇到 StatusCode 400 時預設是顯示自訂錯誤頁面,也會忽略 return Content() 內容。如要強制回傳結果,需加上 Response.TrySkipIisCustomErrors = true。

綜合上述結論,修改程式如下:

排版顯示純文字
        public ActionResult BadRequest()
        {
            //用SetStatus()會有副作用,阻止傳回Content
            Response.StatusCode = 400;
            //設定TrySkipIisCustomErrors,停用IIS自訂錯誤頁面
            Response.TrySkipIisCustomErrors = true;
            return Content(
                "{ \"error\": \"朕不給的,你不能拿!\" }", "application/json");
        }

HTTP 400 Bad Request 並傳回 error 訊息,測試成功!

4394-ddec-o.gif

另外,systen.webServer 有個 <httpErrors existingResponse="PassThrough" /> 設定也會影響上述行為。預設值為 Auto,由 Response.TrySkipIisCustomErrors 屬性決定是否使用 IIS 自訂錯誤頁面;若 existingResponse="Replace" 將永遠使用 IIS 錯誤頁面,設為 PassThrough 則永遠使用程式輸出結果。Stackoverflow 上有一則詳細解說,值得參考。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK