在 ASP.NET Core 中有三种返回 数据HTTP状态码 的形式,最简略的就是间接返回指定的类型实例,如下代码所示:

    [ApiController]    [Route("[controller]")]    public class WeatherForecastController : ControllerBase    {        [HttpGet]        public IEnumerable<WeatherForecast> Get()        {            var rng = new Random();            return Enumerable.Range(1, 5).Select(index => new WeatherForecast            {                Date = DateTime.Now.AddDays(index),                TemperatureC = rng.Next(-20, 55),                Summary = Summaries[rng.Next(Summaries.Length)]            })            .ToArray();        }    }

除了这种,也能够返回 IActionResult 实例 和 ActionResult <T> 实例。

尽管返回指定的类型 是最简略粗犷的,但它只能返回数据,附带不了http状态码,而 IActionResult 实例能够将 数据 + Http状态码 一起带给前端,最初就是 ActionResult<T> 它封装了后面两者,能够实现两种模式的自在切换,????吧。

接下来一起探讨下如何在 ASP.NET Core Web API 中应用这三种形式。

创立 Controller 和 Model 类

在我的项目的 Models 文件夹下新建一个 Author 类,代码如下:

    public class Author    {        public int Id { get; set; }        public string FirstName { get; set; }        public string LastName { get; set; }    }

有了这个 Author 类,接下来创立一个 DefaultController 类。

using Microsoft.AspNetCore.Mvc;using System.Collections.Generic;namespace IDGCoreWebAPI.Controllers{    [Route("api/[controller]")]    [ApiController]    public class DefaultController : ControllerBase    {        private readonly List<Author> authors = new List<Author>();        public DefaultController()        {            authors.Add(new Author()            {                Id = 1,                FirstName = "Joydip",                LastName = "Kanjilal"            });            authors.Add(new Author()            {                Id = 2,                FirstName = "Steve",                LastName = "Smith"            });        }        [HttpGet]        public IEnumerable<Author> Get()        {            return authors;        }        [HttpGet("{id}", Name = "Get")]        public Author Get(int id)        {            return authors.Find(x => x.Id == id);        }    }}

在 Action 中返回 指定类型

最简略的形式就是在 Action 中间接返回一个 简略类型 或者 简单类型,其实在下面的代码清单中,能够看到 Get 办法返回了一个 authors 汇合,看清楚了,这个办法定义的是 IEnumerable<Author>

[HttpGet]public IEnumerable<Author> Get(){   return authors;}

在 ASP.NET Core 3.0 开始,你不仅能够定义同步模式的 IEnumerable<Author>办法,也能够定义异步模式的 IAsyncEnumerable<T>办法,后者的不同点在于它是一个异步模式的汇合,益处就是 不阻塞 以后的调用线程,对于 IAsyncEnumerable<T> 更多的常识,我会在前面的文章中和大家分享。

上面的代码展现了如何用 异步汇合 来革新 Get 办法。

[HttpGet]public async IAsyncEnumerable<Author> Get(){   var authors = await GetAuthors();   await foreach (var author in authors)   {        yield return author;   }}

在 Action 中返回 IActionResult 实例

如果你要返回 data + httpcode 的双重需要,那么 IActionResult 就是你要找的货色,上面的代码片段展现了如何去实现。

[HttpGet]public IActionResult Get(){  if (authors == null)      return NotFound("No records");  return Ok(authors);}

下面的代码有 OkNotFound 两个办法,对应着 OKResult,NotFoundResult, Http Code 对应着 200,404。当然还有其余的如:CreatedResult, NoContentResult, BadRequestResult, UnauthorizedResult, 和 UnsupportedMediaTypeResult,都是 IActionResult 的子类。

在 Action 中返回 ActionResult<T> 实例

ActionResult<T> 是在 ASP.NET Core 2.1 中被引入的,它的作用就是包装了后面这种模式,怎么了解呢? 就是即能够返回 IActionResult ,也能够返回指定类型,从 ActionResult<TValue> 类下的两个构造函数中就可以看的进去。

public sealed class ActionResult<TValue> : IConvertToActionResult{    public ActionResult Result  {get;}    public TValue Value  {get;}    public ActionResult(TValue value)    {        if (typeof(IActionResult).IsAssignableFrom(typeof(TValue)))        {            throw new ArgumentException(Resources.FormatInvalidTypeTForActionResultOfT(typeof(TValue), "ActionResult<T>"));        }        Value = value;    }    public ActionResult(ActionResult result)    {        if (typeof(IActionResult).IsAssignableFrom(typeof(TValue)))        {            throw new ArgumentException(Resources.FormatInvalidTypeTForActionResultOfT(typeof(TValue), "ActionResult<T>"));        }        Result = (result ?? throw new ArgumentNullException("result"));    }}

有了这个根底,接下来看看如何在 Action 办法中去接这两种类型。

[HttpGet]public ActionResult<IEnumerable<Author>> Get(){  if (authors == null)       return NotFound("No records");   return authors;}

和文章之前的 Get 办法相比,这里间接返回 authors 而不须要再用 OK(authors) 包装,是不是一个十分好的简化呢? 接下来再把 Get 办法异步化,首先思考上面返回 authors 汇合的异步办法。

private async Task<List<Author>> GetAuthors(){    await Task.Delay(100).ConfigureAwait(false);    return authors;}

值得注意的是,异步办法必须要有至多一个 await 语句,如果不这样做的话,编译器会提醒一个正告谬误,告知你这个办法将会被 同步执行,为了避免出现这种难堪,我在 Task.Delay 上做了一个 await。

上面就是更新后的 Get 办法,留神一下这里我用了 await 去调用方才创立的异步办法,代码参考如下。

[HttpGet]public async Task<ActionResult<IEnumerable<Author>>> Get(){   var data = await GetAuthors();   if (data == null)        return NotFound("No record");   return data;}

如果你有一些定制化需要,能够实现一个自定义的 ActionResult 类,做法就是实现 IActionResult 中的 ExecuteResultAsync 办法即可。

译文链接:https://www.infoworld.com/art...

更多高质量干货:参见我的 GitHub: csharptranslate