Tipos de retorno de ação do controlador na API Web ASP.NET CoreController action return types in ASP.NET Core Web API

Por Scott AddieBy Scott Addie

Exibir ou baixar código de exemplo (como baixar)View or download sample code (how to download)

O ASP.NET Core oferece as seguintes opções para os tipos de retorno da ação do controlador da API Web:ASP.NET Core offers the following options for Web API controller action return types:

Este documento explica quando é mais adequado usar cada tipo de retorno.This document explains when it's most appropriate to use each return type.

Tipo específicoSpecific type

A ação mais simples retorna um tipo de dados complexo ou primitivo (por exemplo, string ou um tipo de objeto personalizado).The simplest action returns a primitive or complex data type (for example, string or a custom object type). Considere a seguinte ação, que retorna uma coleção de objetos Product personalizados:Consider the following action, which returns a collection of custom Product objects:

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

Sem condições conhecidas contra as quais se proteger durante a execução da ação, retornar um tipo específico pode ser suficiente.Without known conditions to safeguard against during action execution, returning a specific type could suffice. A ação anterior não aceita parâmetros, assim, validação de restrições de parâmetro não é necessária.The preceding action accepts no parameters, so parameter constraints validation isn't needed.

Quando condições conhecidas precisarem ser incluídas em uma ação, vários caminhos de retorno serão introduzidos.When known conditions need to be accounted for in an action, multiple return paths are introduced. Nesse caso, é comum combinar um tipo de retorno ActionResult com o tipo de retorno primitivo ou complexo.In such a case, it's common to mix an ActionResult return type with the primitive or complex return type. IActionResult ou ActionResult<T > é necessário para acomodar esse tipo de ação.Either IActionResult or ActionResult<T> are necessary to accommodate this type of action.

Tipo IActionResultIActionResult type

O tipo de retorno IActionResult é apropriado quando vários tipos de retorno ActionResult são possíveis em uma ação.The IActionResult return type is appropriate when multiple ActionResult return types are possible in an action. Os tipos ActionResult representam vários códigos de status HTTP.The ActionResult types represent various HTTP status codes. Alguns tipos de retorno comuns que se enquadram nessa categoria são BadRequestResult (400) NotFoundResult (404) e OkObjectResult (200).Some common return types falling into this category are BadRequestResult (400), NotFoundResult (404), and OkObjectResult (200).

Porque há vários tipos de retorno e caminhos na ação, o uso liberal do atributo [ProducesResponseType] é necessário.Because there are multiple return types and paths in the action, liberal use of the [ProducesResponseType] attribute is necessary. Esse atributo produz detalhes de resposta mais descritivos para páginas de ajuda da API geradas por ferramentas como Swagger.This attribute produces more descriptive response details for API help pages generated by tools like Swagger. [ProducesResponseType] indica os tipos conhecidos e os códigos de status HTTP a serem retornados pela ação.[ProducesResponseType] indicates the known types and HTTP status codes to be returned by the action.

Ação síncronaSynchronous action

Considere a seguinte ação síncrona em que há dois tipos de retorno possíveis: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);
}

Na ação anterior, um código de status 404 é retornado quando o produto representado por id não existe no armazenamento de dados subjacente.In the preceding action, a 404 status code is returned when the product represented by id doesn't exist in the underlying data store. O método auxiliar NotFound é invocado como um atalho para return new NotFoundResult();.The NotFound helper method is invoked as a shortcut to return new NotFoundResult();. Se o produto existir, um objeto Product que representa o conteúdo será retornado com um código de status 200.If the product does exist, a Product object representing the payload is returned with a 200 status code. O método auxiliar OK é invocado como a forma abreviada de return new OkObjectResult(product);.The Ok helper method is invoked as the shorthand form of return new OkObjectResult(product);.

Ação assíncronaAsynchronous action

Considere a seguinte ação assíncrona em que há dois tipos de retorno possíveis: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);
}

No código anterior:In the preceding code:

  • O tempo de execução do ASP.NET Core retorna um código de status 400 (BadRequest) quando a descrição do produto contém "Widget XYZ".A 400 status code (BadRequest) is returned by the ASP.NET Core runtime when the product description contains "XYZ Widget".
  • O método CreatedAtAction gera um código de status 201 quando um produto é criado.A 201 status code is generated by the CreatedAtAction method when a product is created. Nesse caminho de código, o objeto Product é retornado.In this code path, the Product object is returned.

Por exemplo, o modelo a seguir indica que as solicitações devem incluir as propriedades Name e Description.For example, the following model indicates that requests must include the Name and Description properties. Portanto, a falha em fornecer Name e Description na solicitação causa falha na validação do modelo.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; }
}

Se o atributo [ApiController] no ASP.NET Core 2.1 ou posterior for aplicado, erros de validação de modelo resultarão em um código de status 400.If the [ApiController] attribute in ASP.NET Core 2.1 or later is applied, model validation errors result in a 400 status code. Para obter mais informações, veja Respostas automáticas HTTP 400.For more information, see Automatic HTTP 400 responses.

Tipo ActionResult<T>ActionResult<T> type

O ASP.NET Core 2.1 apresenta o tipo de retorno ActionResult<T > para ações do controlador de API Web.ASP.NET Core 2.1 introduces the ActionResult<T> return type for Web API controller actions. Permite que você retorne um tipo derivado de ActionResult ou retorne um tipo específico.It enables you to return a type deriving from ActionResult or return a specific type. ActionResult<T> oferece os seguintes benefícios em relação ao tipo IActionResult:ActionResult<T> offers the following benefits over the IActionResult type:

  • O atributo [ProducesResponseType] pode ter sua propriedade Type excluída.The [ProducesResponseType] attribute's Type property can be excluded. Por exemplo, [ProducesResponseType(200, Type = typeof(Product))] é simplificado para [ProducesResponseType(200)].For example, [ProducesResponseType(200, Type = typeof(Product))] is simplified to [ProducesResponseType(200)]. O tipo de retorno esperado da ação é inferido do T em ActionResult<T>.The action's expected return type is instead inferred from the T in ActionResult<T>.
  • Operadores de conversão implícita são compatíveis com a conversão de T e ActionResult em ActionResult<T>.Implicit cast operators support the conversion of both T and ActionResult to ActionResult<T>. T converte em ObjectResult, o que significa que return new ObjectResult(T); é simplificado para return T;.T converts to ObjectResult, which means return new ObjectResult(T); is simplified to return T;.

C# não dá suporte a operadores de conversão implícita em interfaces.C# doesn't support implicit cast operators on interfaces. Consequentemente, a conversão da interface para um tipo concreto é necessário para usar ActionResult<T>.Consequently, conversion of the interface to a concrete type is necessary to use ActionResult<T>. Por exemplo, o uso de IEnumerable no exemplo a seguir não funciona:For example, use of IEnumerable in the following example doesn't work:

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

Uma opção para corrigir o código anterior é retornar a _repository.GetProducts().ToList();.One option to fix the preceding code is to return _repository.GetProducts().ToList();.

A maioria das ações tem um tipo de retorno específico.Most actions have a specific return type. Condições inesperadas podem ocorrer durante a execução da ação, caso em que o tipo específico não é retornado.Unexpected conditions can occur during action execution, in which case the specific type isn't returned. Por exemplo, o parâmetro de entrada de uma ação pode falhar na validação do modelo.For example, an action's input parameter may fail model validation. Nesse caso, é comum retornar o tipo ActionResult adequado, em vez do tipo específico.In such a case, it's common to return the appropriate ActionResult type instead of the specific type.

Ação síncronaSynchronous action

Considere uma ação síncrona em que há dois tipos de retorno possíveis: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;
}

No código anterior, um código de status 404 é retornado quando o produto não existe no banco de dados.In the preceding code, a 404 status code is returned when the product doesn't exist in the database. Se o produto existir, o objeto Product correspondente será retornado.If the product does exist, the corresponding Product object is returned. Antes do ASP.NET Core 2.1, a linha return product; teria sido return Ok(product);.Before ASP.NET Core 2.1, the return product; line would have been return Ok(product);.

Dica

Do ASP.NET Core 2.1 em diante, a inferência de origem de associação de parâmetro de ação é habilitada quando uma classe de controlador é decorada com o atributo [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. Um nome de parâmetro correspondente a um nome do modelo de rota é associado automaticamente usando os dados de rota de solicitação.A parameter name matching a name in the route template is automatically bound using the request route data. Consequentemente, o parâmetro id da ação anterior não é explicitamente anotado com o atributo [FromRoute].Consequently, the preceding action's id parameter isn't explicitly annotated with the [FromRoute] attribute.

Ação assíncronaAsynchronous action

Considere uma ação assíncrona em que há dois tipos de retorno possíveis: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);
}

No código anterior:In the preceding code:

  • O tempo de execução do ASP.NET Core retorna um código de status 400 (BadRequest) quando:A 400 status code (BadRequest) is returned by the ASP.NET Core runtime when:
    • O atributo [ApiController] tiver sido aplicado e o modelo de validação falhar.The [ApiController] attribute has been applied and model validation fails.
    • A descrição do produto contém "Widget XYZ".The product description contains "XYZ Widget".
  • O método CreatedAtAction gera um código de status 201 quando um produto é criado.A 201 status code is generated by the CreatedAtAction method when a product is created. Nesse caminho de código, o objeto Product é retornado.In this code path, the Product object is returned.

Dica

Do ASP.NET Core 2.1 em diante, a inferência de origem de associação de parâmetro de ação é habilitada quando uma classe de controlador é decorada com o atributo [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. Parâmetros de tipo complexo são vinculados automaticamente usando o corpo da solicitação.Complex type parameters are automatically bound using the request body. Consequentemente, o parâmetro product da ação anterior não é explicitamente anotado com o atributo [FromBody].Consequently, the preceding action's product parameter isn't explicitly annotated with the [FromBody] attribute.

Recursos adicionaisAdditional resources