首頁>技術>

傳統的 asp.net mvc 對應著 .netcore 中的 asp.net core mvc,可以利用 asp.net core mvc 去構建跨平臺,可擴充套件,高效能的web應用和 api 介面。

程式設計師都有一些潔癖,很多時候我們都想很完美的包裝一些錯誤資訊,如一些返回空response的request請求,或者一些 action 中返回 null value 的情況,通常這些情況下,asp.net core mvc 都會返回 http status 204 (No Content),在本篇中,我準備修改一下這種從 action 返回 null value 的預設行為。

在 Asp.NET Core 中新建 Controller

在解決方案視窗中的 Controller 資料夾上右鍵並選擇 Add -> Controller 去新建Controller,指定這個 Controller 的名字為 DemoController,接下來用下面的程式碼替換 DemoController。

    [Route("api/[controller]")]    [ApiController]    public class DemoController : ControllerBase    {        readonly Repository repository = new Repository();        [HttpGet]        public ActionResult Get()        {            string item = repository.GetMessage();            return Ok(item);        }        [HttpGet("{id}", Name = "Get")]        public IActionResult Get(int id)        {            string item = repository.GetMessage();            return Ok(item);        }    }
建立一個 Repository

下面是一個 Repository 類,裡面包含了一個返回 null 的 GetMessage 方法,當然這僅僅是為了演示目的。

    public class Repository    {        public string GetMessage()        {            return null;        }    }
在 asp.net core mvc 中如何處理 null 值

當用 httpGet 的方式去請求 DemoController 的 GetMessage 方法,mvc 會返回 Http Status 204 (No Content),如下圖所示:

為什麼會這樣呢? 當response準備返回時,asp.net core mvc 會從當前可用的 格式化器 列表中選擇一個合適的去處理當前的 response 物件,比如說:這個格式化器可以是 Json formatter,又可以是 Xml formatter,或者任何合適於該資源的 formatter。

對了,當遇到 null 值時,asp.net core mvc 框架會使用一個叫做 HttpNoContentOutputFormatter,它的職責就是將 null 轉換成 Http Status 204(No Content),下面展示了原始碼實現:

public class HttpNoContentOutputFormatter : IOutputFormatter{    public Task WriteAsync(OutputFormatterWriteContext context)    {        HttpResponse response = context.HttpContext.Response;        response.ContentLength = 0L;        if (response.StatusCode == 200)        {            response.StatusCode = 204;        }        return Task.CompletedTask;    }}
禁用 HttpNoContentOutputFormatter

如果你好奇的話,可以把 HttpNoContentOutputFormatter 禁用掉,這樣就切斷了 asp.net mvc core 處理 null 值的預設行為,如果要這麼做的話,在 Startup 類的 ConfigureServices 方法做如下配置。

services.AddMvc(f =>  {      f.OutputFormatters.RemoveType      (typeof(HttpNoContentOutputFormatter));      f.OutputFormatters.Insert(0, new      HttpNoContentOutputFormatter      {          TreatNullValueAsNoContent = false      });});

上面的程式碼禁用了 http status 204 的行為,取而代之的就是返回 http status 200 (OK),然後 null 值會被塞到 response body 中。

在 Asp.Net Core 中返回 http status 404

為了能夠達到404的效果,我來更新一下 action 的名字,下面就是 DemoController 更新後的程式碼片段:

    [Route("api/[controller]")]    [ApiController]    public class DemoController : ControllerBase    {        readonly Repository repository = new Repository();        [HttpGet]        public ActionResult Get()        {            string item = repository.GetMessage();            if (item == null)                return NotFound();            return Ok(item);        }          }

當你再次請求 DemoController 時,框架會返回 http status 404(Not Found),如下面圖片所示:

一個更完善的的返回 http 404 的方式

一個更好的返回 http status 404 的方式是使用 action filter 或者 result filter,如下程式碼:

    public class NotFoundActionFilterAttribute : ActionFilterAttribute    {        public override void OnActionExecuted(ActionExecutedContext context)        {            if (context.Result is ObjectResult)            {                ObjectResult objectResult = context.Result                as ObjectResult;                if (objectResult.Value == null)                    context.Result = new NotFoundResult();            }        }    }

你可以將這個 filter 放置在 action級別,controller級別 或者 全域性級別,如果你要放到全域性級別,可以在 Startup 的 ConfigureServices 方法中新增如下程式碼:

public void ConfigureServices(IServiceCollection services){    services.AddMvc(f =>    {        f.Filters.Add(new NotFoundResultFilterAttribute());    });}

當在使用 asp.net core mvc 時,你可以在 action 返回值處使用 IActionResultActionResult<T> 或其他任何物件,在 Action 返回資料後,框架底層會對你的返回結果做必要的 序列化操作。

然而,當 action 返回 null 值時, asp.net core mvc 並不會嘗試用任何可用的序列化器去處理這個 null 值,換句話說,框架會返回 Http status 204,表示請求成功但無內容,幸運的是,你可以按需改變這個預設的行為。

12
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 2021年值得關注的8種自動化趨勢