Criar APIs Web com o ASP.NET CoreCreate web APIs with ASP.NET Core

Por Scott Addie e Tom DykstraBy Scott Addie and Tom Dykstra

O ASP.NET Core permite a criação de serviços RESTful, também conhecidos como APIs Web, usando C#.ASP.NET Core supports creating RESTful services, also known as web APIs, using C#. Para lidar com solicitações, uma API Web usa controladores.To handle requests, a web API uses controllers. Em uma API Web, os controladores são classes que derivam de ControllerBase.Controllers in a web API are classes that derive from ControllerBase. Este artigo mostra como usar controladores para lidar com solicitações da API.This article shows how to use controllers for handling API requests.

Exibir ou baixar o código de exemplo.View or download sample code. (Como baixar.)(How to download).

Classe ControllerBaseControllerBase class

Uma API Web tem uma ou mais classes de controlador derivadas de ControllerBase.A web API has one or more controller classes that derive from ControllerBase. Por exemplo, o modelo de projeto de API Web cria um controlador de Valores:For example, the web API project template creates a Values controller:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

Não crie um controlador de API Web derivando da classe base Controller.Don't create a web API controller by deriving from the Controller base class. Controller é derivado de ControllerBase e agrega suporte para exibições; portanto, serve para manipulação de páginas da Web, não para solicitações de API Web.Controller derives from ControllerBase and adds support for views, so it's for handling web pages, not web API requests. Há uma exceção a essa regra: se você pretende usar o mesmo controlador para exibições e APIs, derive-o de Controller.There's an exception to this rule: if you plan to use the same controller for both views and APIs, derive it from Controller.

A classe ControllerBase fornece muitas propriedades e métodos úteis para lidar com solicitações HTTP.The ControllerBase class provides many properties and methods that are useful for handling HTTP requests. Por exemplo, ControllerBase.CreatedAtAction retorna um código de status 201:For example, ControllerBase.CreatedAtAction returns a 201 status code:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

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

Veja mais alguns exemplos de métodos fornecidos por ControllerBase.Here are some more examples of methods that ControllerBase provides.

MétodoMethod ObservaçõesNotes
BadRequest Retorna o código de status 400.Returns 400 status code.
NotFound Retorna o código de status 404.Returns 404 status code.
PhysicalFile Retorna um arquivo.Returns a file.
TryUpdateModelAsync Invoca model binding.Invokes model binding.
TryValidateModel Invoca validação de modelo.Invokes model validation.

Confira uma lista com todos os métodos e propriedades disponíveis em ControllerBase.For a list of all available methods and properties, see ControllerBase.

AtributosAttributes

O namespace Microsoft.AspNetCore.Mvc fornece atributos que podem ser usados para configurar o comportamento de controladores de API Web e dos métodos de ação.The Microsoft.AspNetCore.Mvc namespace provides attributes that can be used to configure the behavior of web API controllers and action methods. O exemplo a seguir usa atributos para especificar o método HTTP aceito e os códigos de status retornado:The following example uses attributes to specify the HTTP method accepted and the status codes returned:

[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public ActionResult<Pet> Create(Pet pet)
{
    pet.Id = _petsInMemoryStore.Any() ? _petsInMemoryStore.Max(p => p.Id) + 1 : 1;
    _petsInMemoryStore.Add(pet);

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

Confira mais alguns exemplos de atributos disponíveis.Here are some more examples of attributes that are available.

AtributoAttribute ObservaçõesNotes
[Route][Route] Especifica o padrão de URL para um controlador ou ação.Specifies URL pattern for a controller or action.
[Bind][Bind] Especifica o prefixo e as propriedades que serão incluídos no model binding.Specifies prefix and properties to include for model binding.
[HttpGet][HttpGet] Identifica uma ação que dá suporte ao método HTTP GET.Identifies an action that supports the HTTP GET method.
[Consumes][Consumes] Especifica os tipos de dados aceitos por uma ação.Specifies data types that an action accepts.
[Produces][Produces] Especifica os tipos de dados retornados por uma ação.Specifies data types that an action returns.

Veja uma lista que inclui os atributos disponíveis no namespace Microsoft.AspNetCore.Mvc.For a list that includes the available attributes, see the Microsoft.AspNetCore.Mvc namespace.

Atributo ApiControllerApiController attribute

O atributo [ApiController] pode ser aplicado a uma classe de controlador para habilitar comportamentos específicos à API:The [ApiController] attribute can be applied to a controller class to enable API-specific behaviors:

Esses recursos exigem compatibilidade com a versão 2.1 ou posterior.These features require a compatibility version of 2.1 or later.

ApiController em controladores específicosApiController on specific controllers

O atributo [ApiController] pode ser aplicado a controladores específicos, como no exemplo a seguir do modelo de projeto:The [ApiController] attribute can be applied to specific controllers, as in the following example from the project template:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

ApiController em vários controladoresApiController on multiple controllers

Uma abordagem ao uso do atributo em mais de um controlador é a criação de uma classe de controlador base personalizada anotada com o atributo [ApiController].One approach to using the attribute on more than one controller is to create a custom base controller class annotated with the [ApiController] attribute. Veja um exemplo que mostra uma classe base personalizada e um controlador derivado dela:Here's an example showing a custom base class and a controller that derives from it:

[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces("application/json")]
[Route("api/[controller]")]
public class PetsController : MyControllerBase

ApiController em um assemblyApiController on an assembly

Se versão de compatibilidade estiver definida como 2.2 ou posterior, o atributo [ApiController] poderá ser aplicado a um assembly.If compatibility version is set to 2.2 or later, the [ApiController] attribute can be applied to an assembly. A anotação dessa maneira aplica o comportamento da API Web para todos os controladores no assembly.Annotation in this manner applies web API behavior to all controllers in the assembly. Não é possível recusar controladores individuais.There's no way to opt out for individual controllers. Aplique o atributo no nível do assembly à classe Startup conforme mostra o exemplo a seguir:Apply the assembly-level attribute to the Startup class as shown in the following example:

[assembly: ApiController]
namespace WebApiSample
{
    public class Startup
    {
        ...
    }
}

Requisito de roteamento de atributoAttribute routing requirement

O atributo ApiController transforma em requisito o roteamento de atributo.The ApiController attribute makes attribute routing a requirement. Por exemplo:For example:

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase

As ações são inacessíveis por meio de rotas convencionais definidas por UseMvc ou UseMvcWithDefaultRoute em Startup.Configure.Actions are inaccessible via conventional routes defined by UseMvc or UseMvcWithDefaultRoute in Startup.Configure.

Respostas automáticas do HTTP 400Automatic HTTP 400 responses

O atributo ApiController faz com que os erros de validação do modelo disparem automaticamente uma resposta HTTP 400.The ApiController attribute makes model validation errors automatically trigger an HTTP 400 response. Consequentemente, o código a seguir se torna desnecessário em um método de ação:Consequently, the following code is unnecessary in an action method:

if (!ModelState.IsValid)
{
    return BadRequest(ModelState);
}

Resposta BadRequest padrãoDefault BadRequest response

Com uma versão de compatibilidade de 2.2 ou posterior, o tipo de resposta padrão para respostas HTTP 400 é ValidationProblemDetails.With a compatibility version of 2.2 or later, the default response type for HTTP 400 responses is ValidationProblemDetails. O tipo ValidationProblemDetails está em conformidade com a especificação RFC 7807.The ValidationProblemDetails type complies with the RFC 7807 specification.

Para alterar a resposta padrão para SerializableError, defina a propriedade SuppressUseValidationProblemDetailsForInvalidModelStateResponses como true em Startup.ConfigureServices, conforme mostra o exemplo a seguir:To change the default response to SerializableError, set the SuppressUseValidationProblemDetailsForInvalidModelStateResponses property to true in Startup.ConfigureServices, as shown in the following example:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Personalizar a resposta de BadRequestCustomize BadRequest response

Para personalizar a resposta resultante de um erro de validação, use InvalidModelStateResponseFactory.To customize the response that results from a validation error, use InvalidModelStateResponseFactory. Adicione o código realçado a seguir após services.AddMvc().SetCompatibilityVersion:Add the following highlighted code after services.AddMvc().SetCompatibilityVersion:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.InvalidModelStateResponseFactory = context =>
        {
            var problemDetails = new ValidationProblemDetails(context.ModelState)
            {
                Type = "https://contoso.com/probs/modelvalidation",
                Title = "One or more model validation errors occurred.",
                Status = StatusCodes.Status400BadRequest,
                Detail = "See the errors property for details.",
                Instance = context.HttpContext.Request.Path
            };

            return new BadRequestObjectResult(problemDetails)
            {
                ContentTypes = { "application/problem+json" }
            };
        };
    });

Registrar respostas de 400 automáticaLog automatic 400 responses

Confira Como registrar respostas de 400 automática sobre erros de validação de modelo (aspnet/AspNetCore.Docs #12157).See How to log automatic 400 responses on model validation errors (aspnet/AspNetCore.Docs #12157).

Desabilitar 400 automáticaDisable automatic 400

Para desabilitar o comportamento 400 automático, defina a propriedade SuppressModelStateInvalidFilter como true.To disable the automatic 400 behavior, set the SuppressModelStateInvalidFilter property to true. Adicione o código realçado a seguir em Startup.ConfigureServices após services.AddMvc().SetCompatibilityVersion:Add the following highlighted code in Startup.ConfigureServices after services.AddMvc().SetCompatibilityVersion:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Inferência de parâmetro de origem de associaçãoBinding source parameter inference

Um atributo de origem de associação define o local no qual o valor do parâmetro de uma ação é encontrado.A binding source attribute defines the location at which an action parameter's value is found. Os seguintes atributos da origem da associação existem:The following binding source attributes exist:

AtributoAttribute Fonte de associaçãoBinding source
[FromBody][FromBody] Corpo da solicitaçãoRequest body
[FromForm][FromForm] Dados do formulário no corpo da solicitaçãoForm data in the request body
[FromHeader][FromHeader] Cabeçalho da solicitaçãoRequest header
[FromQuery][FromQuery] Parâmetro de cadeia de caracteres de consulta de solicitaçãoRequest query string parameter
[FromRoute][FromRoute] Dados de rota da solicitação atualRoute data from the current request
[FromServices][FromServices] O serviço de solicitação inserido como um parâmetro de açãoThe request service injected as an action parameter

Aviso

Não use [FromRoute] quando os valores puderem conter %2f (ou seja, /).Don't use [FromRoute] when values might contain %2f (that is /). %2f não ficará sem escape para /.%2f won't be unescaped to /. Use [FromQuery], se o valor puder conter %2f.Use [FromQuery] if the value might contain %2f.

Sem o atributo [ApiController] ou outros atributos de origem da associação, como [FromQuery], o tempo de execução do ASP.NET Core tenta usar o associador de modelos de objeto complexo.Without the [ApiController] attribute or binding source attributes like [FromQuery], the ASP.NET Core runtime attempts to use the complex object model binder. O associador de modelos de objeto complexo extrai os dados dos provedores de valor em uma ordem definida.The complex object model binder pulls data from value providers in a defined order.

No exemplo a seguir, o atributo [FromQuery] indica que o valor do parâmetro discontinuedOnly é fornecido na cadeia de caracteres de consulta da URL de solicitação:In the following example, the [FromQuery] attribute indicates that the discontinuedOnly parameter value is provided in the request URL's query string:

[HttpGet]
public ActionResult<List<Product>> Get(
    [FromQuery] bool discontinuedOnly = false)
{
    List<Product> products = null;

    if (discontinuedOnly)
    {
        products = _productsInMemoryStore.Where(p => p.IsDiscontinued).ToList();
    }
    else
    {
        products = _productsInMemoryStore;
    }

    return products;
}

O atributo [ApiController] aplica regras de inferência para as fontes de dados padrão dos parâmetros de ação.The [ApiController] attribute applies inference rules for the default data sources of action parameters. Essas regras poupam você da necessidade de identificar as origens de associação manualmente aplicando atributos aos parâmetros de ação.These rules save you from having to identify binding sources manually by applying attributes to the action parameters. As regras de inferência da origem de associação se comportam da seguinte maneira:The binding source inference rules behave as follows:

  • [FromBody] é inferido para parâmetros de tipo complexo.[FromBody] is inferred for complex type parameters. Uma exceção à regra de inferência [FromBody] é qualquer tipo interno complexo com um significado especial, como IFormCollection e CancellationToken.An exception to the [FromBody] inference rule is any complex, built-in type with a special meaning, such as IFormCollection and CancellationToken. O código de inferência da origem da associação ignora esses tipos especiais.The binding source inference code ignores those special types.
  • [FromForm] é inferido para parâmetros de ação do tipo IFormFile e IFormFileCollection.[FromForm] is inferred for action parameters of type IFormFile and IFormFileCollection. Ele não é inferido para qualquer tipo simples ou definido pelo usuário.It's not inferred for any simple or user-defined types.
  • [FromRoute] é inferido para qualquer nome de parâmetro de ação correspondente a um parâmetro no modelo de rota.[FromRoute] is inferred for any action parameter name matching a parameter in the route template. Quando mais de uma rota correspondem a um parâmetro de ação, qualquer valor de rota é considerado [FromRoute].When more than one route matches an action parameter, any route value is considered [FromRoute].
  • [FromQuery] é inferido para todos os outros parâmetros de ação.[FromQuery] is inferred for any other action parameters.

Notas de inferência FromBodyFromBody inference notes

[FromBody] não é inferido para tipos simples, como string ou int.[FromBody] isn't inferred for simple types such as string or int. Portanto, o atributo [FromBody] deve ser usado para tipos simples quando essa funcionalidade for necessária.Therefore, the [FromBody] attribute should be used for simple types when that functionality is needed.

Quando uma ação tiver mais de um parâmetro associado ao corpo da solicitação, uma exceção será lançada.When an action has more than one parameter bound from the request body, an exception is thrown. Por exemplo, todas as assinaturas de método de ação a seguir causam uma exceção:For example, all of the following action method signatures cause an exception:

  • [FromBody] inferido em ambos, pois são tipos complexos.[FromBody] inferred on both because they're complex types.

    [HttpPost]
    public IActionResult Action1(Product product, Order order)
    
  • O atributo [FromBody] em um, inferido no outro, porque é um tipo complexo.[FromBody] attribute on one, inferred on the other because it's a complex type.

    [HttpPost]
    public IActionResult Action2(Product product, [FromBody] Order order)
    
  • Atributo [FromBody] em ambos.[FromBody] attribute on both.

    [HttpPost]
    public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
    

Observação

No ASP.NET Core 2.1, os parâmetros de tipo de coleção, como listas e matrizes, são inferidos incorretamente como [FromQuery].In ASP.NET Core 2.1, collection type parameters such as lists and arrays are incorrectly inferred as [FromQuery]. O atributo [FromBody] deve ser usado para esses parâmetros se eles forem vinculados ao corpo da solicitação.The [FromBody] attribute should be used for these parameters if they are to be bound from the request body. Esse comportamento é corrigido no ASP.NET Core 2.2 ou posterior, onde os parâmetros do tipo de coleção são inferidos para serem associados ao corpo por padrão.This behavior is corrected in ASP.NET Core 2.2 or later, where collection type parameters are inferred to be bound from the body by default.

Desabilitar regras de inferênciaDisable inference rules

Para desabilitar a inferência da origem da associação, defina SuppressInferBindingSourcesForParameters como true.To disable binding source inference, set SuppressInferBindingSourcesForParameters to true. Adicione o seguinte código em Startup.ConfigureServices após services.AddMvc().SetCompatibilityVersion:Add the following code in Startup.ConfigureServices after services.AddMvc().SetCompatibilityVersion:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Inferência de solicitação de várias partes/dados de formulárioMultipart/form-data request inference

O atributo [ApiController] aplicar uma regra de inferência quando um parâmetro de ação é anotado com o atributo [FromForm]: o tipo de conteúdo de solicitação multipart/form-data é inferido.The [ApiController] attribute applies an inference rule when an action parameter is annotated with the [FromForm] attribute: the multipart/form-data request content type is inferred.

Para desabilitar o comportamento padrão, defina SuppressConsumesConstraintForFormFileParameters como true em Startup.ConfigureServices, conforme mostra o exemplo a seguir:To disable the default behavior, set SuppressConsumesConstraintForFormFileParameters to true in Startup.ConfigureServices, as shown in the following example:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Detalhes do problema dos códigos de status de erroProblem details for error status codes

Quando a versão de compatibilidade for 2.2 ou posterior, o MVC transformará um resultado de erro (um resultado com o código de status 400 ou superior) em um resultado com ProblemDetails.When the compatibility version is 2.2 or later, MVC transforms an error result (a result with status code 400 or higher) to a result with ProblemDetails. O tipo ProblemDetails tem base na especificação RFC 7807 para fornecer detalhes de erro legíveis por computador em uma resposta HTTP.The ProblemDetails type is based on the RFC 7807 specification for providing machine-readable error details in an HTTP response.

Considere o seguinte código em uma ação do controlador:Consider the following code in a controller action:

if (pet == null)
{
    return NotFound();
}

A resposta HTTP para NotFound tem um código de status 404 com um corpo ProblemDetails.The HTTP response for NotFound has a 404 status code with a ProblemDetails body. Por exemplo:For example:

{
    type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
    title: "Not Found",
    status: 404,
    traceId: "0HLHLV31KRN83:00000001"
}

Personalizar a resposta de ProblemDetailsCustomize ProblemDetails response

Use a propriedade ClientErrorMapping para configurar o conteúdo da resposta ProblemDetails.Use the ClientErrorMapping property to configure the contents of the ProblemDetails response. Por exemplo, o código a seguir atualiza a propriedade type para respostas 404:For example, the following code updates the type property for 404 responses:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Desabilitar a resposta de ProblemDetailsDisable ProblemDetails response

A criação automática de ProblemDetails fica desabilitada quando a propriedade SuppressMapClientErrors é definida como true.The automatic creation of ProblemDetails is disabled when the SuppressMapClientErrors property is set to true. Adicione o seguinte código em Startup.ConfigureServices:Add the following code in Startup.ConfigureServices:

services.AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(options =>
    {
        options.SuppressConsumesConstraintForFormFileParameters = true;
        options.SuppressInferBindingSourcesForParameters = true;
        options.SuppressModelStateInvalidFilter = true;
        options.SuppressMapClientErrors = true;
        options.SuppressUseValidationProblemDetailsForInvalidModelStateResponses = true;
        options.ClientErrorMapping[404].Link =
            "https://httpstatuses.com/404";
    });

Recursos adicionaisAdditional resources