ASP.NET Core Web API 中控制器操作的返回类型Controller action return types in ASP.NET Core Web API

作者:Scott AddieBy Scott Addie

查看或下载示例代码如何下载View or download sample code (how to download)

ASP.NET Core 提供以下 Web API 控制器操作返回类型选项:ASP.NET Core offers the following options for Web API controller action return types:

本文档说明每种返回类型的最佳适用情况。This document explains when it's most appropriate to use each return type.

特定类型Specific type

最简单的操作返回基元或复杂数据类型(如 string 或自定义对象类型)。The simplest action returns a primitive or complex data type (for example, string or a custom object type). 请参考以下操作,该操作返回自定义 Product 对象的集合:Consider the following action, which returns a collection of custom Product objects:

[HttpGet]
public IEnumerable<Product> Get()
{
    return _repository.GetProducts();
}

在执行操作期间无需防范已知条件,返回特定类型即可满足要求。Without known conditions to safeguard against during action execution, returning a specific type could suffice. 上述操作不接受任何参数,因此不需要参数约束验证。The preceding action accepts no parameters, so parameter constraints validation isn't needed.

当在操作中需要考虑已知条件时,将引入多个返回路径。When known conditions need to be accounted for in an action, multiple return paths are introduced. 在此类情况下,通常会将 ActionResult 返回类型和基元或复杂返回类型混合。In such a case, it's common to mix an ActionResult return type with the primitive or complex return type. 要支持此类操作,必须使用 IActionResultActionResult<T>Either IActionResult or ActionResult<T> are necessary to accommodate this type of action.

IActionResult 类型IActionResult type

当操作中可能有多个 ActionResult 返回类型时,适合使用 IActionResult 返回类型。The IActionResult return type is appropriate when multiple ActionResult return types are possible in an action. ActionResult 类型表示多种 HTTP 状态代码。The ActionResult types represent various HTTP status codes. 属于此类别的一些常见返回类型包括:BadRequestResult (400)、NotFoundResult (404) 和 OkObjectResult (200)。Some common return types falling into this category are BadRequestResult (400), NotFoundResult (404), and OkObjectResult (200).

由于操作中有多个返回类型和路径,因此必须自由使用 [ProducesResponseType] 特性。Because there are multiple return types and paths in the action, liberal use of the [ProducesResponseType] attribute is necessary. 此特性可针对 Swagger 等工具生成的 API 帮助页生成更多描述性响应详细信息。This attribute produces more descriptive response details for API help pages generated by tools like Swagger. [ProducesResponseType] 指示操作将返回的已知类型和 HTTP 状态代码。[ProducesResponseType] indicates the known types and HTTP status codes to be returned by the action.

同步操作Synchronous action

请参考以下同步操作,其中有两种可能的返回类型:Consider the following synchronous action in which there are two possible return types:

[HttpGet("{id}")]
[ProducesResponseType(typeof(Product), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public IActionResult GetById(int id)
{
    if (!_repository.TryGetProduct(id, out var product))
    {
        return NotFound();
    }

    return Ok(product);
}

在上述操作中,当 id 代表的产品不在基础数据存储中时,则返回 404 状态代码。In the preceding action, a 404 status code is returned when the product represented by id doesn't exist in the underlying data store. 调用 NotFound 帮助程序方法作为 return new NotFoundResult(); 的快捷方式。The NotFound helper method is invoked as a shortcut to return new NotFoundResult();. 如果产品确实存在,则返回代表有效负载的 Product 对象和状态代码 200。If the product does exist, a Product object representing the payload is returned with a 200 status code. 调用 Ok 帮助程序方法作为 return new OkObjectResult(product); 的快捷方式。The Ok helper method is invoked as the shorthand form of return new OkObjectResult(product);.

异步操作Asynchronous action

请参考以下异步操作,其中有两种可能的返回类型:Consider the following asynchronous action in which there are two possible return types:

[HttpPost]
[ProducesResponseType(typeof(Product), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> CreateAsync([FromBody] Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    await _repository.AddProductAsync(product);

    return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}

在上述代码中:In the preceding code:

  • 如果项目说明包含“XYZ 小组件”,ASP.NET Core 运行时返回 400 状态代码 (BadRequest)。A 400 status code (BadRequest) is returned by the ASP.NET Core runtime when the product description contains "XYZ Widget".
  • 在产品创建后,CreatedAtAction 方法生成 201 状态代码。A 201 status code is generated by the CreatedAtAction method when a product is created. 在此代码路径中,返回的对象是 ProductIn this code path, the Product object is returned.

例如,以下模型指明请求必须包含 NameDescription 属性。For example, the following model indicates that requests must include the Name and Description properties. 因此,如果没有在请求中提供 NameDescription,便会导致模型验证失败。Therefore, failure to provide Name and Description in the request causes model validation to fail.

public class Product
{
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public string Description { get; set; }
}

如果应用的是 ASP.NET Core 2.1 或更高版本中的 [ApiController] 属性,模型验证错误会导致 400 状态代码生成。If the [ApiController] attribute in ASP.NET Core 2.1 or later is applied, model validation errors result in a 400 status code. 有关详细信息,请参阅自动 HTTP 400 响应For more information, see Automatic HTTP 400 responses.

ActionResult<T> 类型ActionResult<T> type

ASP.NET Core 2.1 引入了面向 Web API 控制器操作的 ActionResult<T> 返回类型。ASP.NET Core 2.1 introduces the ActionResult<T> return type for Web API controller actions. 它支持返回从 ActionResult 派生的类型或返回特定类型It enables you to return a type deriving from ActionResult or return a specific type. ActionResult<T> 通过 IActionResult 类型可提供以下优势:ActionResult<T> offers the following benefits over the IActionResult type:

  • 可排除 [ProducesResponseType] 特性的 Type 属性。The [ProducesResponseType] attribute's Type property can be excluded. 例如,[ProducesResponseType(200, Type = typeof(Product))] 可简化为 [ProducesResponseType(200)]For example, [ProducesResponseType(200, Type = typeof(Product))] is simplified to [ProducesResponseType(200)]. 此操作的预期返回类型改为根据 ActionResult<T> 中的 T 进行推断。The action's expected return type is instead inferred from the T in ActionResult<T>.
  • 隐式强制转换运算符支持将 TActionResult 均转换为 ActionResult<T>Implicit cast operators support the conversion of both T and ActionResult to ActionResult<T>. T 转换为 ObjectResult,也就是将 return new ObjectResult(T); 简化为 return T;T converts to ObjectResult, which means return new ObjectResult(T); is simplified to return T;.

C# 不支持对接口使用隐式强制转换运算符。C# doesn't support implicit cast operators on interfaces. 因此,必须使用 ActionResult<T>,才能将接口转换为具体类型。Consequently, conversion of the interface to a concrete type is necessary to use ActionResult<T>. 例如,在下面的示例中,使用 IEnumerable 不起作用:For example, use of IEnumerable in the following example doesn't work:

[HttpGet]
public ActionResult<IEnumerable<Product>> Get()
{
    return _repository.GetProducts();
}

上面代码的一种修复方法是返回 _repository.GetProducts().ToList();One option to fix the preceding code is to return _repository.GetProducts().ToList();.

大多数操作具有特定返回类型。Most actions have a specific return type. 执行操作期间可能出现意外情况,不返回特定类型就是其中之一。Unexpected conditions can occur during action execution, in which case the specific type isn't returned. 例如,操作的输入参数可能无法通过模型验证。For example, an action's input parameter may fail model validation. 在此情况下,通常会返回相应的 ActionResult 类型,而不是特定类型。In such a case, it's common to return the appropriate ActionResult type instead of the specific type.

同步操作Synchronous action

请参考以下同步操作,其中有两种可能的返回类型:Consider a synchronous action in which there are two possible return types:

[HttpGet("{id}")]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<Product> GetById(int id)
{
    if (!_repository.TryGetProduct(id, out var product))
    {
        return NotFound();
    }

    return product;
}

在上述代码中,当产品不在数据库中时则返回状态代码 404。In the preceding code, a 404 status code is returned when the product doesn't exist in the database. 如果产品确实存在,则返回相应的 Product 对象。If the product does exist, the corresponding Product object is returned. ASP.NET Core 2.1 之前,return product; 行是 return Ok(product);Before ASP.NET Core 2.1, the return product; line would have been return Ok(product);.

提示

从 ASP.NET Core 2.1 开始,使用 [ApiController] 特性修饰控制器类时,将启用操作参数绑定源推理。As of ASP.NET Core 2.1, action parameter binding source inference is enabled when a controller class is decorated with the [ApiController] attribute. 与路由模板中的名称相匹配的参数名称将通过请求路由数据自动绑定。A parameter name matching a name in the route template is automatically bound using the request route data. 因此,不会使用 [FromRoute] 特性对上述操作中的 id 参数进行显示批注。Consequently, the preceding action's id parameter isn't explicitly annotated with the [FromRoute] attribute.

异步操作Asynchronous action

请参考以下异步操作,其中有两种可能的返回类型:Consider an asynchronous action in which there are two possible return types:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult<Product>> CreateAsync(Product product)
{
    if (product.Description.Contains("XYZ Widget"))
    {
        return BadRequest();
    }

    await _repository.AddProductAsync(product);

    return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}

在上述代码中:In the preceding code:

  • 在以下情况下,ASP.NET Core 运行时返回 400 状态代码 (BadRequest):A 400 status code (BadRequest) is returned by the ASP.NET Core runtime when:
    • 已应用 [ApiController] 属性,且模型验证失败。The [ApiController] attribute has been applied and model validation fails.
    • 产品说明包含“XYZ 小组件”。The product description contains "XYZ Widget".
  • 在产品创建后,CreatedAtAction 方法生成 201 状态代码。A 201 status code is generated by the CreatedAtAction method when a product is created. 在此代码路径中,返回的对象是 ProductIn this code path, the Product object is returned.

提示

从 ASP.NET Core 2.1 开始,使用 [ApiController] 特性修饰控制器类时,将启用操作参数绑定源推理。As of ASP.NET Core 2.1, action parameter binding source inference is enabled when a controller class is decorated with the [ApiController] attribute. 复杂类型参数通过请求正文自动绑定。Complex type parameters are automatically bound using the request body. 因此,不会使用 [FromBody] 特性对前面操作中的 product 参数进行显示批注。Consequently, the preceding action's product parameter isn't explicitly annotated with the [FromBody] attribute.

其他资源Additional resources