最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

ASP.NET Core Mvc中空返回值的处理方法详解

来源:动视网 责编:小采 时间:2020-11-27 22:34:45
文档

ASP.NET Core Mvc中空返回值的处理方法详解

ASP.NET Core Mvc中空返回值的处理方法详解:前言 如果你是一个初学者开始学习 ASP.NET 或 ASP.NET MVC, 你可能并不知道什么是. net Framework和. net ore。不用担心!我建议您看下官方文档https://docs.microsoft.com/zh-cn/aspnet/index , 您可以轻松地看到比较和差异。 .NET
推荐度:
导读ASP.NET Core Mvc中空返回值的处理方法详解:前言 如果你是一个初学者开始学习 ASP.NET 或 ASP.NET MVC, 你可能并不知道什么是. net Framework和. net ore。不用担心!我建议您看下官方文档https://docs.microsoft.com/zh-cn/aspnet/index , 您可以轻松地看到比较和差异。 .NET


通过修改配置移除默认的null值格式化器

我们可以通过设置HttpNoContentOutputFormatter对象的TreatNullValueAsNoContent属性为false,去除默认的HttpNoContentOutputFormatter对null值的格式化。

在Startup.cs文件的ConfigureService方法中, 我们在添加Mvc服务的地方,修改默认的输出格式化器,代码如下

public void ConfigureServices(IServiceCollection services)
{
 services.AddMvc(o =>
 {
 o.OutputFormatters.RemoveType(typeof(HttpNoContentOutputFormatter));
 o.OutputFormatters.Insert(0, new HttpNoContentOutputFormatter 
 { 
 TreatNullValueAsNoContent = false;
 });
 });
}

修改之后我们重新运行程序,并使用Postman访问/api/book/3

结果如下, 返回值200 OK, 内容为null, 这说明我们的修改成功了。

使用404 Not Found代替204 No Content

在上面的例子中, 我们禁用了204 No Content行为,响应结果变为了200 OK, 内容为null。 但是有时候,我们期望当找不到任何结果时,返回404 Not Found , 那么这时候我们应该修改代码,进行扩展呢?

在.NET Core Mvc中我们可以使用自定义过滤器(Custom Filter), 来改变这一行为。

这里我们创建2个特性类NotFoundActionFilterAttribute和NotFoundResultFilterAttribute , 代码如下:

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

public class NotFoundResultFilterAttribute : ResultFilterAttribute
{
 public override void OnResultExecuting(ResultExecutingContext context)
 {
 if (context.Result is ObjectResult objectResult && objectResult.Value == null)
 {
 context.Result = new NotFoundResult();
 }
 }
}

代码解释

  • 这里使用了ActionFilterAttribute和ResultFilterAttribute,ActionFilterAttribute中的OnActionExecuted方法会在action执行完后触发, ResultFilterAttribute的OnResultExecuting会在action返回结果前触发。
  • 这2个方法都是针对action的返回结果进行了替换操作,如果返回结果的值是null, 就将其替换成NotFoundResult
  • 添加完成后,你可以任选一个类,将他们添加在

    controller头部

    [Route("api/[controller]")]
    [ApiController]
    [NotFoundResultFilter]
    public class BookController : ControllerBase
    {
     ...
    }

    或者action头部

    [HttpGet("{id}")]
    [NotFoundResultFilter]
    public IActionResult GetById(int id)
    {
     var item = _books.FirstOrDefault(p => p.BookId == id);
     return Ok(item);
    }

    你还可以在添加Mvc服务的时候配置他们

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

    选择一种重新运行项目之后,效果和通过修改配置移除默认的null值格式化器是一样的。

    IAlwaysRunResultFilter

    以上的几种解决方案看似完美无缺,但实际上还是存在一点瑕疵。由于ASP.NET Core Mvc中过滤器的短路机制(即在任何一个过滤器中对Result赋值都会导致程序跳过管道中剩余的过滤器),可能现在使用某些第三方组件后, 第三方组件在管道中插入自己的短路过滤器,从而导致我们的代码失效。

    ASP.NET Core Mvc的过滤器,可以参见这篇文章

    下面我们添加以下的短路过滤器。

    public class ShortCircuitingFilterAttribute : ActionFilterAttribute
    {
     public override void OnActionExecuting(ActionExecutingContext context)
     {
     context.Result = new ObjectResult(null);
     }
    }

    然后修改BookController中GetById的方法

    [HttpGet("{id}")]
    [ShortCircuitingFilter]
    [NotFoundActionFilter]
    public IActionResult GetById(int id)
    {
     var item = _books.FirstOrDefault(p => p.BookId == id);
     return Ok(item);
    }

    重新运行程序后,使用Postman访问/api/book/3, 程序又返回了204 Not Content, 这说明我们的代码失效了。

    这时候,为了解决这个问题,我们需要使用.NET Core 2.1中新引入的接口IAlwaysRunResultFilter。实现IAlwaysRunResultFilter接口的过滤器总是会执行,不论前面的过滤器是否触发短路。

    这里我们添加一个新的过滤器NotFoundAlwaysRunFilterAttribute。

    public class NotFoundAlwaysRunFilterAttribute : Attribute, IAlwaysRunResultFilter
    {
     public void OnResultExecuted(ResultExecutedContext context)
     {
     }
    
     public void OnResultExecuting(ResultExecutingContext context)
     {
     if (context.Result is ObjectResult objectResult && objectResult.Value == null)
     {
     context.Result = new NotFoundResult();
     }
     }
    }

    然后我们继续修改BookController中的GetById方法, 为其添加NotFoundAlwaysRunFilter特性

    [HttpGet("{id}")]
    [ShortCircuitingFilter]
    [NotFoundActionFilter]
    [NotFoundAlwaysRunFilter]
    public IActionResult GetById(int id)
    {
     var item = _books.FirstOrDefault(p => p.BookId == id);
     return Ok(item);
    }

    重新运行程序后,使用Postman访问/api/book/3, 程序又成功返回了404 Not Found, 这说明我们的代码又生效了。

    本篇源代码: https://github.com/lamondlu/NullAction (本地下载)

    原文地址:https://www.strathweb.com/2018/10/convert-null-valued-results-to-404-in-asp-net-core-mvc/

    作者: Filip W.

    译者: Lamond Lu

    总结

    文档

    ASP.NET Core Mvc中空返回值的处理方法详解

    ASP.NET Core Mvc中空返回值的处理方法详解:前言 如果你是一个初学者开始学习 ASP.NET 或 ASP.NET MVC, 你可能并不知道什么是. net Framework和. net ore。不用担心!我建议您看下官方文档https://docs.microsoft.com/zh-cn/aspnet/index , 您可以轻松地看到比较和差异。 .NET
    推荐度:
    标签: 处理 返回 net
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top