如何在 Asp.Net Core MVC 中处理 null 值

共 4216字,需浏览 9分钟

 ·

2020-12-13 00:14

译文链接:https://www.infoworld.com/article/3434624/how-to-handle-null-values-in-aspnet-core-mvc.html

传统的 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 的默认行为。

要想运行本篇的例子,你需要安装一下 Visual Studio 2019,如果没有安装,可以到官网安装一下:https://visualstudio.microsoft.com/downloads/

在 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(0new
      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 或其他任何对象,在 Action 返回数据后,框架底层会对你的返回结果做必要的 序列化操作。

然而,当 action 返回 null 值时, asp.net core mvc 并不会尝试用任何可用的序列化器去处理这个 null 值,换句话说,框架会返回 Http status 204,表示请求成功但无内容,幸运的是,你可以按需改变这个默认的行为。


浏览 46
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报