Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O ASP.NET Core suporta a criação de APIs da Web usando controladores ou usando APIs mínimas. Controladores em uma API da Web são classes que derivam de ControllerBase. Os controladores são ativados e eliminados por solicitação.
Este artigo mostra como usar controladores para lidar com solicitações de API da Web. Para obter informações sobre como criar APIs da Web sem controladores, consulte Tutorial: Criar uma API mínima com o ASP.NET Core.
Importante
A partir do ASP.NET Core 10, os pontos de extremidade de API conhecidos não redirecionam mais para páginas de login ao usar cookie a autenticação. Em vez disso, eles retornam códigos de status 401/403. Para obter detalhes, consulte Comportamento de autenticação de ponto de extremidade da API no ASP.NET Core.
ControllerBase classe
Uma API da Web baseada em controlador consiste em uma ou mais classes de controlador que derivam de ControllerBase. O modelo de projeto de API da Web fornece um controlador inicial:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
Os controladores de API da Web normalmente devem derivar de ControllerBase em vez de Controller.
Controller deriva de ControllerBase e adiciona suporte para visualizações, portanto, é para lidar com páginas da Web, não solicitações de API da Web. Se o mesmo controlador tiver que oferecer suporte a vistas e APIs da Web, derive de Controller.
A classe ControllerBase fornece muitas propriedades e métodos que são úteis para lidar com solicitações HTTP. Por exemplo, CreatedAtAction retorna um código de status 201:
[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);
}
A tabela a seguir contém exemplos de métodos em ControllerBase.
| Method | Notes |
|---|---|
| BadRequest | Retorna o código de status 400. |
| NotFound | Retorna o código de status 404. |
| PhysicalFile | Retorna um arquivo. |
| TryUpdateModelAsync | Invoca a vinculação de modelo. |
| TryValidateModel | Invoca a validação do modelo. |
Para obter uma lista de todos os métodos e propriedades disponíveis, consulte ControllerBase.
Attributes
O Microsoft.AspNetCore.Mvc namespace fornece atributos que podem ser usados para configurar o comportamento de controladores de API da Web e métodos de ação. O exemplo a seguir usa atributos para especificar o verbo de ação HTTP suportado e quaisquer códigos de status HTTP conhecidos que possam ser retornados:
[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);
}
Aqui estão mais alguns exemplos de atributos que estão disponíveis.
| Attribute | Notes |
|---|---|
[Route] |
Especifica o padrão de URL para um controlador ou ação. |
[Bind] |
Especifica o prefixo e as propriedades a serem incluídas para a vinculação do modelo. |
[HttpGet] |
Identifica uma ação que suporta o método HTTP GET. |
[Consumes] |
Especifica os tipos de dados que uma ação aceita. |
[Produces] |
Especifica os tipos de dados que uma ação retorna. |
Para obter uma lista que inclui os atributos disponíveis, consulte o Microsoft.AspNetCore.Mvc namespace.
Atributo ApiController
O [ApiController] atributo pode ser aplicado a uma classe de controlador para habilitar os seguintes comportamentos opinativos, específicos da API:
- Requisito de roteamento de atributos
- Respostas HTTP 400 automáticas
- Inferência de parâmetros de origem de vinculação
- Inferência de solicitação de várias partes/dados de formulário
- Detalhes do problema para códigos de status de erro
Atributo em controladores específicos
O [ApiController] atributo pode ser aplicado a controladores específicos, como no exemplo a seguir do modelo de projeto:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
Atributo em vários controladores
Uma abordagem para usar o atributo em mais de um controlador é criar uma classe de controlador base personalizada anotada com o [ApiController] atributo. O exemplo a seguir mostra uma classe base personalizada e um controlador que deriva dela:
[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces(MediaTypeNames.Application.Json)]
[Route("[controller]")]
public class PetsController : MyControllerBase
Atributo em um assembly
O atributo [ApiController] pode ser aplicado a um assembly. Quando o [ApiController] atributo é aplicado a um assembly, todos os controladores no assembly têm o [ApiController] atributo aplicado. Não há como desativar controladores individuais. Aplique o atributo de nível de assembly ao ficheiro Program.cs.
using Microsoft.AspNetCore.Mvc;
[assembly: ApiController]
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Requisito de roteamento de atributos
O [ApiController] atributo torna o roteamento de atributos um requisito. Por exemplo:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
As ações são inacessíveis através de vias convencionais definidas por UseEndpoints, UseMvcou UseMvcWithDefaultRoute.
Respostas HTTP 400 automáticas
O [ApiController] atributo faz com que os erros de validação do modelo acionem automaticamente uma resposta HTTP 400. Consequentemente, o código a seguir é desnecessário em um método de ação:
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
ASP.NET Core MVC usa o ModelStateInvalidFilter filtro de ação para fazer a verificação anterior.
Resposta padrão de "BadRequest"
O tipo de resposta padrão para uma resposta HTTP 400 é ValidationProblemDetails. O seguinte corpo de resposta é um exemplo do tipo serializado:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|7fb5e16a-4c8f23bbfc974667.",
"errors": {
"": [
"A non-empty request body is required."
]
}
}
O ValidationProblemDetails tipo:
- Fornece um formato legível por máquina para especificar erros em respostas de API da Web.
- Está em conformidade com a especificação RFC 7807.
Para tornar as respostas automáticas e personalizadas consistentes, chame o ValidationProblem método em vez de BadRequest.
ValidationProblem retorna o ValidationProblemDetails objeto e a resposta automática.
Registo automático de respostas 400
Para registrar 400 respostas automáticas, defina a propriedade delegate para executar processamento InvalidModelStateResponseFactory personalizado. Por padrão, InvalidModelStateResponseFactory usa ProblemDetailsFactory para criar uma instância de ValidationProblemDetails.
O exemplo a seguir mostra como recuperar uma instância de ILogger<TCategoryName> para registrar informações sobre uma resposta automática 400:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
// To preserve the default behavior, capture the original delegate to call later.
var builtInFactory = options.InvalidModelStateResponseFactory;
options.InvalidModelStateResponseFactory = context =>
{
var logger = context.HttpContext.RequestServices
.GetRequiredService<ILogger<Program>>();
// Perform logging here.
// ...
// Invoke the default behavior, which produces a ValidationProblemDetails
// response.
// To produce a custom response, return a different implementation of
// IActionResult instead.
return builtInFactory(context);
};
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Desativar resposta automática 400
Para desativar o comportamento automático 400, defina a SuppressModelStateInvalidFilter propriedade como true. Adicione o seguinte código realçado:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Inferência de parâmetros de fonte de ligação
Um atributo binding source define o local no qual o valor de um parâmetro action é encontrado. Existem os seguintes atributos de origem de ligação:
| Attribute | Fonte de ligação |
|---|---|
[FromBody] |
Corpo de solicitação |
[FromForm] |
Dados do formulário no corpo da solicitação |
[FromHeader] |
Cabeçalho do pedido |
[FromQuery] |
Parâmetro de cadeia de caracteres de consulta de solicitação |
[FromRoute] |
Dados de rota da solicitação atual |
[FromServices] |
O serviço de solicitação injetado como um parâmetro de ação |
[AsParameters] |
Parâmetros do método |
Warning
Não use [FromRoute] quando os valores podem conter %2f (ou seja /, ).
%2f não será desfeito para /. Use [FromQuery] se o valor pode conter %2f.
Sem o atributo [ApiController] ou atributos de origem de ligação como [FromQuery], o tempo de execução do ASP.NET Core tenta usar o binder de modelo de objeto complexo. O fichário de modelo de objeto complexo extrai dados de provedores de valor em uma ordem definida.
No exemplo a seguir, o [FromQuery] atributo indica que o valor do discontinuedOnly parâmetro é fornecido na cadeia de caracteres de consulta da URL da solicitação:
[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 [ApiController] atributo aplica regras de inferência para as fontes de dados padrão dos parâmetros de ação. Essas regras evitam que você precise identificar fontes de vinculação manualmente aplicando atributos aos parâmetros de ação. As regras de inferência de fontes vinculativas comportam-se da seguinte forma:
-
[FromServices]é inferido para parâmetros de tipo complexos registrados no DI Container. -
[FromBody]é inferido para parâmetros de tipo complexos não registrados no DI Container. Uma exceção à[FromBody]regra de inferência é qualquer tipo complexo, embutido com um significado especial, como IFormCollection e CancellationToken. O código-fonte de inferência de ligação ignora esses tipos especiais. -
[FromForm]é inferido para parâmetros de ação do tipo IFormFile e IFormFileCollection. Não é inferido para nenhum tipo simples ou definido pelo usuário. -
[FromRoute]é inferido para qualquer nome de parâmetro de ação correspondente a um parâmetro no modelo de rota. Quando mais de uma rota corresponde a um parâmetro action, qualquer valor de rota é considerado[FromRoute]. -
[FromQuery]é inferido para quaisquer outros parâmetros de ação.
Notas de inferência FromBody
[FromBody] não é inferido para tipos simples como string ou int. Portanto, o [FromBody] atributo deve ser usado para tipos simples quando essa funcionalidade é necessária.
Quando uma ação tem mais de um parâmetro vinculado do corpo da solicitação, uma exceção é lançada. Por exemplo, todas as seguintes assinaturas de método de ação causam uma exceção:
[FromBody]inferido em ambos porque são tipos complexos.[HttpPost] public IActionResult Action1(Product product, Order order)[FromBody]atributo num, inferido no outro por ser um tipo complexo.[HttpPost] public IActionResult Action2(Product product, [FromBody] Order order)[FromBody]atributo em ambos.[HttpPost] public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
Notas de inferência de FromServices
A vinculação de parâmetros vincula parâmetros por meio da injeção de dependência quando o tipo é configurado como um serviço. Isso significa que não é necessário aplicar explicitamente o [FromServices] atributo a um parâmetro. No código a seguir, ambas as ações retornam o tempo:
[Route("[controller]")]
[ApiController]
public class MyController : ControllerBase
{
public ActionResult GetWithAttribute([FromServices] IDateTime dateTime)
=> Ok(dateTime.Now);
[Route("noAttribute")]
public ActionResult Get(IDateTime dateTime) => Ok(dateTime.Now);
}
Em casos raros, a DI automática pode quebrar aplicativos que têm um tipo de DI que também é aceito nos métodos de ação de um controlador de API. Não é comum ter um tipo no DI e também como argumento numa ação de um controlador da API.
Para desabilitar [FromServices] a inferência para um único parâmetro de ação, aplique o atributo de origem de ligação desejado ao parâmetro. Por exemplo, aplique o [FromBody] atributo a um parâmetro action que deve ser vinculado a partir do corpo da solicitação.
Para desabilitar [FromServices] a inferência globalmente, defina DisableImplicitFromServicesParameters como true:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddSingleton<IDateTime, SystemDateTime>();
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.DisableImplicitFromServicesParameters = true;
});
var app = builder.Build();
app.MapControllers();
app.Run();
Os tipos são verificados na inicialização do aplicativo para IServiceProviderIsService determinar se um argumento em uma ação do controlador de API vem da DI ou de outras fontes.
O mecanismo para inferir a origem vinculante dos parâmetros de ação do Controlador de API usa as seguintes regras:
- Um
BindingInfo.BindingSourceespecificado anteriormente nunca é substituído. - Um parâmetro de tipo complexo, registrado no contêiner DI, é atribuído
BindingSource.Services. - Um parâmetro de tipo complexo, não registrado no contêiner DI, é atribuído
BindingSource.Body. - Um parâmetro com um nome que aparece como um valor de rota em qualquer modelo de rota em
tem a atribuição de . - Todos os outros parâmetros são
BindingSource.Query.
Desativar regras de inferência
Para desativar a inferência de origem de vinculação, defina SuppressInferBindingSourcesForParameters como true:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
options.DisableImplicitFromServicesParameters = true;
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Inferência de solicitação de várias partes/dados de formulário
O [ApiController] atributo aplica uma regra de inferência para parâmetros de ação do tipo IFormFile e IFormFileCollection. O multipart/form-data tipo de conteúdo da solicitação é inferido para esses tipos.
Para desativar o comportamento padrão, defina a SuppressConsumesConstraintForFormFileParameters propriedade como true:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Detalhes do problema para códigos de estado de erro
O MVC transforma um resultado de erro (um resultado com código de status 400 ou superior) em um resultado com ProblemDetails. O ProblemDetails tipo é baseado na especificação RFC 7807 para fornecer detalhes de erro legíveis por máquina em uma resposta HTTP.
Considere o seguinte código em uma ação do controlador:
if (pet == null)
{
return NotFound();
}
O NotFound método produz um código de status HTTP 404 com um ProblemDetails corpo. Por exemplo:
{
type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
title: "Not Found",
status: 404,
traceId: "0HLHLV31KRN83:00000001"
}
Desativar a resposta de ProblemDetails
A criação automática de um ProblemDetails para códigos de status de erro é desabilitada quando a SuppressMapClientErrors propriedade é definida como true. Adicione o seguinte código:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Definir tipos de conteúdo de solicitação suportados com o atributo [Consumes]
Por padrão, uma ação suporta todos os tipos de conteúdo de solicitação disponíveis. Por exemplo, se um aplicativo estiver configurado para dar suporte à entrada JSON e XML formatters, uma ação dará suporte a vários tipos de conteúdo, incluindo application/json e application/xml.
O atributo [Consumes] permite que uma ação limite os tipos de conteúdo de solicitação suportados. Aplique o [Consumes] atributo a uma ação ou controlador, especificando um ou mais tipos de conteúdo:
[HttpPost]
[Consumes("application/xml")]
public IActionResult CreateProduct(Product product)
No código anterior, a CreateProduct ação especifica o tipo application/xmlde conteúdo . As solicitações roteadas para essa ação devem especificar um Content-Type cabeçalho de application/xml. Solicitações que não especificam um cabeçalho Content-Type resultam em uma resposta application/xml.
O [Consumes] atributo também permite que uma ação influencie sua seleção com base no tipo de conteúdo de uma solicitação de entrada aplicando uma restrição de tipo. Considere o seguinte exemplo:
[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
[HttpPost]
[Consumes("application/json")]
public IActionResult PostJson(IEnumerable<int> values) =>
Ok(new { Consumes = "application/json", Values = values });
[HttpPost]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}
No código anterior, ConsumesController está configurado para lidar com solicitações enviadas para a https://localhost:5001/api/Consumes URL. Ambas as ações PostJson do controlador e PostForm, lidam com solicitações POST com a mesma URL. Sem que o [Consumes] atributo aplique uma restrição de tipo, uma exceção de correspondência ambígua é lançada.
O [Consumes] atributo é aplicado a ambas as ações. A ação PostJson lida com solicitações enviadas com um cabeçalho Content-Type de application/json. A ação PostForm lida com solicitações enviadas com um cabeçalho Content-Type de application/x-www-form-urlencoded.
Recursos adicionais
- Ver e descarregar código de exemplo. (Como fazer o download).
- Tipos de retorno de ação do controlador na API Web ASP.NET Core
- Manipular erros em APIs do ASP.NET Core
- Formatações personalizadas na Web API do ASP.NET Core
- Formatar dados de resposta em ASP.NET API Web Principal
- Documentação da ASP.NET Core web API com Swagger / OpenAPI
- Roteamento para ações do controlador no ASP.NET Core
- Utilizar o túnel de porta do Visual Studio para depurar APIs Web
- Criar uma API da Web com o ASP.NET Core
O ASP.NET Core suporta a criação de APIs da Web usando controladores ou usando APIs mínimas. Controladores em uma API da Web são classes que derivam de ControllerBase. Este artigo mostra como usar controladores para lidar com solicitações de API da Web. Para obter informações sobre como criar APIs da Web sem controladores, consulte Tutorial: Criar uma API mínima com o ASP.NET Core.
ControllerBase classe
Uma API da Web baseada em controlador consiste em uma ou mais classes de controlador que derivam de ControllerBase. O modelo de projeto de API da Web fornece um controlador inicial:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
Os controladores de API da Web normalmente devem derivar de ControllerBase em vez de Controller.
Controller deriva de ControllerBase e adiciona suporte para visualizações, portanto, é para lidar com páginas da Web, não solicitações de API da Web. Se o mesmo controlador tiver que oferecer suporte a vistas e APIs da Web, derive de Controller.
A classe ControllerBase fornece muitas propriedades e métodos que são úteis para lidar com solicitações HTTP. Por exemplo, CreatedAtAction retorna um código de status 201:
[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);
}
A tabela a seguir contém exemplos de métodos em ControllerBase.
| Method | Notes |
|---|---|
| BadRequest | Retorna o código de status 400. |
| NotFound | Retorna o código de status 404. |
| PhysicalFile | Retorna um arquivo. |
| TryUpdateModelAsync | Invoca a vinculação de modelo. |
| TryValidateModel | Invoca a validação do modelo. |
Para obter uma lista de todos os métodos e propriedades disponíveis, consulte ControllerBase.
Attributes
O Microsoft.AspNetCore.Mvc namespace fornece atributos que podem ser usados para configurar o comportamento de controladores de API da Web e métodos de ação. O exemplo a seguir usa atributos para especificar o verbo de ação HTTP suportado e quaisquer códigos de status HTTP conhecidos que possam ser retornados:
[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);
}
Aqui estão mais alguns exemplos de atributos que estão disponíveis.
| Attribute | Notes |
|---|---|
[Route] |
Especifica o padrão de URL para um controlador ou ação. |
[Bind] |
Especifica o prefixo e as propriedades a serem incluídas para a vinculação do modelo. |
[HttpGet] |
Identifica uma ação que suporta o método HTTP GET. |
[Consumes] |
Especifica os tipos de dados que uma ação aceita. |
[Produces] |
Especifica os tipos de dados que uma ação retorna. |
Para obter uma lista que inclui os atributos disponíveis, consulte o Microsoft.AspNetCore.Mvc namespace.
Atributo ApiController
O [ApiController] atributo pode ser aplicado a uma classe de controlador para habilitar os seguintes comportamentos opinativos, específicos da API:
- Requisito de roteamento de atributos
- Respostas HTTP 400 automáticas
- Inferência de parâmetros de origem de vinculação
- Inferência de solicitação de várias partes/dados de formulário
- Detalhes do problema para códigos de status de erro
Atributo em controladores específicos
O [ApiController] atributo pode ser aplicado a controladores específicos, como no exemplo a seguir do modelo de projeto:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
Atributo em vários controladores
Uma abordagem para usar o atributo em mais de um controlador é criar uma classe de controlador base personalizada anotada com o [ApiController] atributo. O exemplo a seguir mostra uma classe base personalizada e um controlador que deriva dela:
[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces(MediaTypeNames.Application.Json)]
[Route("[controller]")]
public class PetsController : MyControllerBase
Atributo em um assembly
O atributo [ApiController] pode ser aplicado a um assembly. Quando o [ApiController] atributo é aplicado a um assembly, todos os controladores no assembly têm o [ApiController] atributo aplicado. Não há como desativar controladores individuais. Aplique o atributo de nível de assembly ao ficheiro Program.cs.
using Microsoft.AspNetCore.Mvc;
[assembly: ApiController]
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Requisito de roteamento de atributos
O [ApiController] atributo torna o roteamento de atributos um requisito. Por exemplo:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
As ações são inacessíveis através de vias convencionais definidas por UseEndpoints, UseMvcou UseMvcWithDefaultRoute.
Respostas HTTP 400 automáticas
O [ApiController] atributo faz com que os erros de validação do modelo acionem automaticamente uma resposta HTTP 400. Consequentemente, o código a seguir é desnecessário em um método de ação:
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
ASP.NET Core MVC usa o ModelStateInvalidFilter filtro de ação para fazer a verificação anterior.
Resposta padrão de "BadRequest"
O seguinte corpo de resposta é um exemplo do tipo serializado:
{
"": [
"A non-empty request body is required."
]
}
O tipo de resposta padrão para uma resposta HTTP 400 é ValidationProblemDetails. O seguinte corpo de resposta é um exemplo do tipo serializado:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|7fb5e16a-4c8f23bbfc974667.",
"errors": {
"": [
"A non-empty request body is required."
]
}
}
O ValidationProblemDetails tipo:
- Fornece um formato legível por máquina para especificar erros em respostas de API da Web.
- Está em conformidade com a especificação RFC 7807.
Para tornar as respostas automáticas e personalizadas consistentes, chame o ValidationProblem método em vez de BadRequest.
ValidationProblem retorna o ValidationProblemDetails objeto e a resposta automática.
Registo automático de respostas 400
Para registrar 400 respostas automáticas, defina a propriedade delegate para executar processamento InvalidModelStateResponseFactory personalizado. Por padrão, InvalidModelStateResponseFactory usa ProblemDetailsFactory para criar uma instância de ValidationProblemDetails.
O exemplo a seguir mostra como recuperar uma instância de ILogger<TCategoryName> para registrar informações sobre uma resposta automática 400:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
// To preserve the default behavior, capture the original delegate to call later.
var builtInFactory = options.InvalidModelStateResponseFactory;
options.InvalidModelStateResponseFactory = context =>
{
var logger = context.HttpContext.RequestServices
.GetRequiredService<ILogger<Program>>();
// Perform logging here.
// ...
// Invoke the default behavior, which produces a ValidationProblemDetails
// response.
// To produce a custom response, return a different implementation of
// IActionResult instead.
return builtInFactory(context);
};
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Desativar resposta automática 400
Para desativar o comportamento automático 400, defina a SuppressModelStateInvalidFilter propriedade como true. Adicione o seguinte código realçado:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Inferência de parâmetros de fonte de ligação
Um atributo binding source define o local no qual o valor de um parâmetro action é encontrado. Existem os seguintes atributos de origem de ligação:
| Attribute | Fonte de ligação |
|---|---|
[FromBody] |
Corpo de solicitação |
[FromForm] |
Dados do formulário no corpo da solicitação |
[FromHeader] |
Cabeçalho do pedido |
[FromQuery] |
Parâmetro de cadeia de caracteres de consulta de solicitação |
[FromRoute] |
Dados de rota da solicitação atual |
[FromServices] |
O serviço de solicitação injetado como um parâmetro de ação |
Warning
Não use [FromRoute] quando os valores podem conter %2f (ou seja /, ).
%2f não será desfeito para /. Use [FromQuery] se o valor pode conter %2f.
Sem o atributo [ApiController] ou atributos de origem de ligação como [FromQuery], o tempo de execução do ASP.NET Core tenta usar o binder de modelo de objeto complexo. O fichário de modelo de objeto complexo extrai dados de provedores de valor em uma ordem definida.
No exemplo a seguir, o [FromQuery] atributo indica que o valor do discontinuedOnly parâmetro é fornecido na cadeia de caracteres de consulta da URL da solicitação:
[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 [ApiController] atributo aplica regras de inferência para as fontes de dados padrão dos parâmetros de ação. Essas regras evitam que você precise identificar fontes de vinculação manualmente aplicando atributos aos parâmetros de ação. As regras de inferência de fontes vinculativas comportam-se da seguinte forma:
-
[FromBody]é inferido para parâmetros de tipo complexos não registrados no DI Container. Uma exceção à[FromBody]regra de inferência é qualquer tipo complexo, embutido com um significado especial, como IFormCollection e CancellationToken. O código-fonte de inferência de ligação ignora esses tipos especiais. -
[FromForm]é inferido para parâmetros de ação do tipo IFormFile e IFormFileCollection. Não é inferido para nenhum tipo simples ou definido pelo usuário. -
[FromRoute]é inferido para qualquer nome de parâmetro de ação correspondente a um parâmetro no modelo de rota. Quando mais de uma rota corresponde a um parâmetro action, qualquer valor de rota é considerado[FromRoute]. -
[FromQuery]é inferido para quaisquer outros parâmetros de ação.
Notas de inferência FromBody
[FromBody] não é inferido para tipos simples como string ou int. Portanto, o [FromBody] atributo deve ser usado para tipos simples quando essa funcionalidade é necessária.
Quando uma ação tem mais de um parâmetro vinculado do corpo da solicitação, uma exceção é lançada. Por exemplo, todas as seguintes assinaturas de método de ação causam uma exceção:
[FromBody]inferido em ambos porque são tipos complexos.[HttpPost] public IActionResult Action1(Product product, Order order)[FromBody]atributo num, inferido no outro por ser um tipo complexo.[HttpPost] public IActionResult Action2(Product product, [FromBody] Order order)[FromBody]atributo em ambos.[HttpPost] public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
Desativar regras de inferência
Para desativar a inferência de origem de vinculação, defina SuppressInferBindingSourcesForParameters como true:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Inferência de solicitação de várias partes/dados de formulário
O [ApiController] atributo aplica uma regra de inferência para parâmetros de ação do tipo IFormFile e IFormFileCollection. O multipart/form-data tipo de conteúdo da solicitação é inferido para esses tipos.
Para desativar o comportamento padrão, defina a SuppressConsumesConstraintForFormFileParameters propriedade como true:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Detalhes do problema para códigos de estado de erro
O MVC transforma um resultado de erro (um resultado com código de status 400 ou superior) em um resultado com ProblemDetails. O ProblemDetails tipo é baseado na especificação RFC 7807 para fornecer detalhes de erro legíveis por máquina em uma resposta HTTP.
Considere o seguinte código em uma ação do controlador:
if (pet == null)
{
return NotFound();
}
O NotFound método produz um código de status HTTP 404 com um ProblemDetails corpo. Por exemplo:
{
type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
title: "Not Found",
status: 404,
traceId: "0HLHLV31KRN83:00000001"
}
Desativar a resposta de ProblemDetails
A criação automática de um ProblemDetails para códigos de status de erro é desabilitada quando a SuppressMapClientErrors propriedade é definida como true:
using Microsoft.AspNetCore.Mvc;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
Definir tipos de conteúdo de solicitação suportados com o atributo [Consumes]
Por padrão, uma ação suporta todos os tipos de conteúdo de solicitação disponíveis. Por exemplo, se um aplicativo estiver configurado para dar suporte à entrada JSON e XML formatters, uma ação dará suporte a vários tipos de conteúdo, incluindo application/json e application/xml.
O atributo [Consumes] permite que uma ação limite os tipos de conteúdo de solicitação suportados. Aplique o [Consumes] atributo a uma ação ou controlador, especificando um ou mais tipos de conteúdo:
[HttpPost]
[Consumes("application/xml")]
public IActionResult CreateProduct(Product product)
No código anterior, a CreateProduct ação especifica o tipo application/xmlde conteúdo . As solicitações roteadas para essa ação devem especificar um Content-Type cabeçalho de application/xml. Solicitações que não especificam um cabeçalho Content-Type resultam em uma resposta application/xml.
O [Consumes] atributo também permite que uma ação influencie sua seleção com base no tipo de conteúdo de uma solicitação de entrada aplicando uma restrição de tipo. Considere o seguinte exemplo:
[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
[HttpPost]
[Consumes("application/json")]
public IActionResult PostJson(IEnumerable<int> values) =>
Ok(new { Consumes = "application/json", Values = values });
[HttpPost]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}
No código anterior, ConsumesController está configurado para lidar com solicitações enviadas para a https://localhost:5001/api/Consumes URL. Ambas as ações PostJson do controlador e PostForm, lidam com solicitações POST com a mesma URL. Sem que o [Consumes] atributo aplique uma restrição de tipo, uma exceção de correspondência ambígua é lançada.
O [Consumes] atributo é aplicado a ambas as ações. A ação PostJson lida com solicitações enviadas com um cabeçalho Content-Type de application/json. A ação PostForm lida com solicitações enviadas com um cabeçalho Content-Type de application/x-www-form-urlencoded.
Recursos adicionais
- Ver e descarregar código de exemplo. (Como fazer o download).
- Tipos de retorno de ação do controlador na API Web ASP.NET Core
- Manipular erros em APIs do ASP.NET Core
- Formatações personalizadas na Web API do ASP.NET Core
- Formatar dados de resposta em ASP.NET API Web Principal
- Documentação da ASP.NET Core web API com Swagger / OpenAPI
- Roteamento para ações do controlador no ASP.NET Core
- Utilizar o túnel de porta do Visual Studio para depurar APIs Web
- Criar uma API da Web com o ASP.NET Core
O ASP.NET Core suporta a criação de serviços RESTful, também conhecidos como APIs da Web, usando C#. Para lidar com solicitações, uma API da Web usa controladores.
Controladores em uma API da Web são classes que derivam de ControllerBase. Este artigo mostra como usar controladores para lidar com solicitações de API da Web.
Ver e descarregar código de exemplo. (Como fazer o download).
ControllerBase classe
Uma API da Web consiste em uma ou mais classes de controlador que derivam do ControllerBase. O modelo de projeto de API da Web fornece um controlador inicial:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
Não crie um controlador de API da Web derivando da Controller classe.
Controller deriva de ControllerBase e adiciona suporte para visualizações, portanto, é para lidar com páginas da Web, não solicitações de API da Web. Há uma exceção a essa regra: se você planeja usar o mesmo controlador para exibições e APIs da Web, derive-o de Controller.
A classe ControllerBase fornece muitas propriedades e métodos que são úteis para lidar com solicitações HTTP. Por exemplo, ControllerBase.CreatedAtAction retorna um código de status 201:
[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);
}
Aqui estão mais alguns exemplos de métodos que ControllerBase fornece.
| Method | Notes |
|---|---|
| BadRequest | Retorna o código de status 400. |
| NotFound | Retorna o código de status 404. |
| PhysicalFile | Retorna um arquivo. |
| TryUpdateModelAsync | Invoca a vinculação de modelo. |
| TryValidateModel | Invoca a validação do modelo. |
Para obter uma lista de todos os métodos e propriedades disponíveis, consulte ControllerBase.
Attributes
O Microsoft.AspNetCore.Mvc namespace fornece atributos que podem ser usados para configurar o comportamento de controladores de API da Web e métodos de ação. O exemplo a seguir usa atributos para especificar o verbo de ação HTTP suportado e quaisquer códigos de status HTTP conhecidos que possam ser retornados:
[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);
}
Aqui estão mais alguns exemplos de atributos que estão disponíveis.
| Attribute | Notes |
|---|---|
[Route] |
Especifica o padrão de URL para um controlador ou ação. |
[Bind] |
Especifica o prefixo e as propriedades a serem incluídas para a vinculação do modelo. |
[HttpGet] |
Identifica uma ação que suporta o método HTTP GET. |
[Consumes] |
Especifica os tipos de dados que uma ação aceita. |
[Produces] |
Especifica os tipos de dados que uma ação retorna. |
Para obter uma lista que inclui os atributos disponíveis, consulte o Microsoft.AspNetCore.Mvc namespace.
Atributo ApiController
O [ApiController] atributo pode ser aplicado a uma classe de controlador para habilitar os seguintes comportamentos opinativos, específicos da API:
- Requisito de roteamento de atributos
- Respostas HTTP 400 automáticas
- Inferência de parâmetros de origem de vinculação
- Inferência de solicitação de várias partes/dados de formulário
- Detalhes do problema para códigos de status de erro
Atributo em controladores específicos
O [ApiController] atributo pode ser aplicado a controladores específicos, como no exemplo a seguir do modelo de projeto:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
Atributo em vários controladores
Uma abordagem para usar o atributo em mais de um controlador é criar uma classe de controlador base personalizada anotada com o [ApiController] atributo. O exemplo a seguir mostra uma classe base personalizada e um controlador que deriva dela:
[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces(MediaTypeNames.Application.Json)]
[Route("[controller]")]
public class PetsController : MyControllerBase
Atributo em um assembly
O atributo [ApiController] pode ser aplicado a um assembly. Anotação nesta forma aplica o comportamento da API Web a todos os controladores no conjunto. Não há como desativar controladores individuais. Aplique o atributo assembly-level à declaração de namespace ao redor da Startup classe:
[assembly: ApiController]
namespace WebApiSample
{
public class Startup
{
...
}
}
Requisito de roteamento de atributos
O [ApiController] atributo torna o roteamento de atributos um requisito. Por exemplo:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
As ações são inacessíveis através de rotas convencionais definidas por UseEndpoints, UseMvcou UseMvcWithDefaultRoute em Startup.Configure.
Respostas HTTP 400 automáticas
O [ApiController] atributo faz com que os erros de validação do modelo acionem automaticamente uma resposta HTTP 400. Consequentemente, o código a seguir é desnecessário em um método de ação:
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
ASP.NET Core MVC usa o ModelStateInvalidFilter filtro de ação para fazer a verificação anterior.
Resposta padrão de "BadRequest"
O seguinte corpo de solicitação é um exemplo do tipo serializado:
{
"": [
"A non-empty request body is required."
]
}
O tipo de resposta padrão para uma resposta HTTP 400 é ValidationProblemDetails. O seguinte corpo de solicitação é um exemplo do tipo serializado:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|7fb5e16a-4c8f23bbfc974667.",
"errors": {
"": [
"A non-empty request body is required."
]
}
}
O ValidationProblemDetails tipo:
- Fornece um formato legível por máquina para especificar erros em respostas de API da Web.
- Está em conformidade com a especificação RFC 7807.
Para tornar as respostas automáticas e personalizadas consistentes, chame o ValidationProblem método em vez de BadRequest.
ValidationProblem retorna o ValidationProblemDetails objeto e a resposta automática.
Registo automático de respostas 400
Para registrar 400 respostas automáticas, defina a propriedade delegate para executar o InvalidModelStateResponseFactory processamento personalizado no Startup.ConfigureServices. Por padrão, InvalidModelStateResponseFactory usa ProblemDetailsFactory para criar uma instância de ValidationProblemDetails.
O exemplo a seguir mostra como recuperar uma instância de ILogger<TCategoryName> para registrar informações sobre uma resposta automática 400:
services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
// To preserve the default behavior, capture the original delegate to call later.
var builtInFactory = options.InvalidModelStateResponseFactory;
options.InvalidModelStateResponseFactory = context =>
{
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<Startup>>();
// Perform logging here.
// ...
// Invoke the default behavior, which produces a ValidationProblemDetails response.
// To produce a custom response, return a different implementation of IActionResult instead.
return builtInFactory(context);
};
});
Desativar resposta automática 400
Para desativar o comportamento automático 400, defina a SuppressModelStateInvalidFilter propriedade como true. Adicione o seguinte código realçado em Startup.ConfigureServices:
services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
options.DisableImplicitFromServicesParameters = true;
});
Inferência de parâmetros de fonte de ligação
Um atributo binding source define o local no qual o valor de um parâmetro action é encontrado. Existem os seguintes atributos de origem de ligação:
| Attribute | Fonte de ligação |
|---|---|
[FromBody] |
Corpo de solicitação |
[FromForm] |
Dados do formulário no corpo da solicitação |
[FromHeader] |
Cabeçalho do pedido |
[FromQuery] |
Parâmetro de cadeia de caracteres de consulta de solicitação |
[FromRoute] |
Dados de rota da solicitação atual |
[FromServices] |
O serviço de solicitação injetado como um parâmetro de ação |
Warning
Não use [FromRoute] quando os valores podem conter %2f (ou seja /, ).
%2f não será desfeito para /. Use [FromQuery] se o valor pode conter %2f.
Sem o atributo [ApiController] ou atributos de origem de ligação como [FromQuery], o tempo de execução do ASP.NET Core tenta usar o binder de modelo de objeto complexo. O fichário de modelo de objeto complexo extrai dados de provedores de valor em uma ordem definida.
No exemplo a seguir, o [FromQuery] atributo indica que o valor do discontinuedOnly parâmetro é fornecido na cadeia de caracteres de consulta da URL da solicitação:
[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 [ApiController] atributo aplica regras de inferência para as fontes de dados padrão dos parâmetros de ação. Essas regras evitam que você precise identificar fontes de vinculação manualmente aplicando atributos aos parâmetros de ação. As regras de inferência de fontes vinculativas comportam-se da seguinte forma:
-
[FromBody]é inferida para parâmetros de tipo complexos. Uma exceção à[FromBody]regra de inferência é qualquer tipo complexo, embutido com um significado especial, como IFormCollection e CancellationToken. O código-fonte de inferência de ligação ignora esses tipos especiais. -
[FromForm]é inferido para parâmetros de ação do tipo IFormFile e IFormFileCollection. Não é inferido para nenhum tipo simples ou definido pelo usuário. -
[FromRoute]é inferido para qualquer nome de parâmetro de ação correspondente a um parâmetro no modelo de rota. Quando mais de uma rota corresponde a um parâmetro action, qualquer valor de rota é considerado[FromRoute]. -
[FromQuery]é inferido para quaisquer outros parâmetros de ação.
Notas de inferência FromBody
[FromBody] não é inferido para tipos simples como string ou int. Portanto, o [FromBody] atributo deve ser usado para tipos simples quando essa funcionalidade é necessária.
Quando uma ação tem mais de um parâmetro vinculado do corpo da solicitação, uma exceção é lançada. Por exemplo, todas as seguintes assinaturas de método de ação causam uma exceção:
[FromBody]inferido em ambos porque são tipos complexos.[HttpPost] public IActionResult Action1(Product product, Order order)[FromBody]atributo num, inferido no outro por ser um tipo complexo.[HttpPost] public IActionResult Action2(Product product, [FromBody] Order order)[FromBody]atributo em ambos.[HttpPost] public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
Desativar regras de inferência
Para desativar a inferência de origem de vinculação, defina SuppressInferBindingSourcesForParameters como true. Adicione o seguinte código em Startup.ConfigureServices:
services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
options.DisableImplicitFromServicesParameters = true;
});
Inferência de solicitação de várias partes/dados de formulário
O [ApiController] atributo aplica uma regra de inferência para parâmetros de ação do tipo IFormFile e IFormFileCollection. O multipart/form-data tipo de conteúdo da solicitação é inferido para esses tipos.
Para desativar o comportamento padrão, defina a SuppressConsumesConstraintForFormFileParameters propriedade como true em Startup.ConfigureServices:
services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
options.DisableImplicitFromServicesParameters = true;
});
Detalhes do problema para códigos de estado de erro
O MVC transforma um resultado de erro (um resultado com código de status 400 ou superior) em um resultado com ProblemDetails. O ProblemDetails tipo é baseado na especificação RFC 7807 para fornecer detalhes de erro legíveis por máquina em uma resposta HTTP.
Considere o seguinte código em uma ação do controlador:
if (pet == null)
{
return NotFound();
}
O NotFound método produz um código de status HTTP 404 com um ProblemDetails corpo. Por exemplo:
{
type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
title: "Not Found",
status: 404,
traceId: "0HLHLV31KRN83:00000001"
}
Desativar a resposta de ProblemDetails
A criação automática de um ProblemDetails para códigos de status de erro é desabilitada quando a SuppressMapClientErrors propriedade é definida como true. Adicione o seguinte código em Startup.ConfigureServices:
services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
options.DisableImplicitFromServicesParameters = true;
});
Definir tipos de conteúdo de solicitação suportados com o atributo [Consumes]
Por padrão, uma ação suporta todos os tipos de conteúdo de solicitação disponíveis. Por exemplo, se um aplicativo estiver configurado para dar suporte à entrada JSON e XML formatters, uma ação dará suporte a vários tipos de conteúdo, incluindo application/json e application/xml.
O atributo [Consumes] permite que uma ação limite os tipos de conteúdo de solicitação suportados. Aplique o [Consumes] atributo a uma ação ou controlador, especificando um ou mais tipos de conteúdo:
[HttpPost]
[Consumes("application/xml")]
public IActionResult CreateProduct(Product product)
No código anterior, a CreateProduct ação especifica o tipo application/xmlde conteúdo . As solicitações roteadas para essa ação devem especificar um Content-Type cabeçalho de application/xml. Solicitações que não especificam um cabeçalho Content-Type resultam em uma resposta application/xml.
O [Consumes] atributo também permite que uma ação influencie sua seleção com base no tipo de conteúdo de uma solicitação de entrada aplicando uma restrição de tipo. Considere o seguinte exemplo:
[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
[HttpPost]
[Consumes("application/json")]
public IActionResult PostJson(IEnumerable<int> values) =>
Ok(new { Consumes = "application/json", Values = values });
[HttpPost]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}
No código anterior, ConsumesController está configurado para lidar com solicitações enviadas para a https://localhost:5001/api/Consumes URL. Ambas as ações PostJson do controlador e PostForm, lidam com solicitações POST com a mesma URL. Sem que o [Consumes] atributo aplique uma restrição de tipo, uma exceção de correspondência ambígua é lançada.
O [Consumes] atributo é aplicado a ambas as ações. A ação PostJson lida com solicitações enviadas com um cabeçalho Content-Type de application/json. A ação PostForm lida com solicitações enviadas com um cabeçalho Content-Type de application/x-www-form-urlencoded.
Recursos adicionais
- Tipos de retorno de ação do controlador na API Web ASP.NET Core
- Manipular erros em APIs do ASP.NET Core
- Formatações personalizadas na Web API do ASP.NET Core
- Formatar dados de resposta em ASP.NET API Web Principal
- Documentação da ASP.NET Core web API com Swagger / OpenAPI
- Roteamento para ações do controlador no ASP.NET Core
- Criar uma API da Web com o ASP.NET Core
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
Não crie um controlador de API da Web derivando da Controller classe.
Controller deriva de ControllerBase e adiciona suporte para visualizações, portanto, é para lidar com páginas da Web, não solicitações de API da Web. Há uma exceção a essa regra: se você planeja usar o mesmo controlador para exibições e APIs da Web, derive-o de Controller.
A classe ControllerBase fornece muitas propriedades e métodos que são úteis para lidar com solicitações HTTP. Por exemplo, ControllerBase.CreatedAtAction retorna um código de status 201:
[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);
}
Aqui estão mais alguns exemplos de métodos que ControllerBase fornece:
| Method | Notes |
|---|---|
| BadRequest | Retorna o código de status 400. |
| NotFound | Retorna o código de status 404. |
| PhysicalFile | Retorna um arquivo. |
| TryUpdateModelAsync | Invoca a vinculação de modelo. |
| TryValidateModel | Invoca a validação do modelo. |
Para obter uma lista de todos os métodos e propriedades disponíveis, consulte ControllerBase.
Attributes
O Microsoft.AspNetCore.Mvc namespace fornece atributos que podem ser usados para configurar o comportamento de controladores de API da Web e métodos de ação. O exemplo a seguir usa atributos para especificar o verbo de ação HTTP suportado e quaisquer códigos de status HTTP conhecidos que possam ser retornados:
[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);
}
Aqui estão mais alguns exemplos de atributos disponíveis:
| Attribute | Notes |
|---|---|
[Route] |
Especifica o padrão de URL para um controlador ou ação. |
[Bind] |
Especifica o prefixo e as propriedades a serem incluídas para a vinculação do modelo. |
[HttpGet] |
Identifica uma ação que suporta o método HTTP GET. |
[Consumes] |
Especifica os tipos de dados que uma ação aceita. |
[Produces] |
Especifica os tipos de dados que uma ação retorna. |
Para obter uma lista que inclui os atributos disponíveis, consulte o Microsoft.AspNetCore.Mvc namespace.
Atributo ApiController
O [ApiController] atributo pode ser aplicado a uma classe de controlador para habilitar os seguintes comportamentos opinativos, específicos da API:
- Requisito de roteamento de atributos
- Respostas HTTP 400 automáticas
- Inferência de parâmetros de origem de vinculação
- Inferência de solicitação de várias partes/dados de formulário
- Detalhes do problema para códigos de status de erro O recurso Detalhes do problema para códigos de status de erro requer uma versão de compatibilidade 2.2 ou posterior. Os outros recursos exigem uma versão de compatibilidade 2.1 ou posterior.
- Requisito de roteamento de atributos
- Respostas HTTP 400 automáticas
- Inferência de parâmetros de origem de vinculação
- Inferência de solicitação de várias partes/dados de formulário Esses recursos exigem uma versão de compatibilidade 2.1 ou posterior.
Atributo em controladores específicos
O [ApiController] atributo pode ser aplicado a controladores específicos, como no exemplo a seguir do modelo de projeto:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
Atributo em vários controladores
Uma abordagem para usar o atributo em mais de um controlador é criar uma classe de controlador base personalizada anotada com o [ApiController] atributo. O exemplo a seguir mostra uma classe base personalizada e um controlador que deriva dela:
[ApiController]
public class MyControllerBase : ControllerBase
{
}
[Produces(MediaTypeNames.Application.Json)]
[Route("api/[controller]")]
public class PetsController : MyControllerBase
Atributo em um assembly
Se a versão de compatibilidade estiver definida como 2.2 ou posterior, o [ApiController] atributo poderá ser aplicado a um assembly. Anotação nesta forma aplica o comportamento da API Web a todos os controladores no conjunto. Não há como desativar controladores individuais. Aplique o atributo assembly-level à declaração de namespace ao redor da Startup classe:
[assembly: ApiController]
namespace WebApiSample
{
public class Startup
{
...
}
}
Requisito de roteamento de atributos
O [ApiController] atributo torna o roteamento de atributos um requisito. Por exemplo:
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
As ações são inacessíveis através de vias convencionais definidas por UseMvc ou UseMvcWithDefaultRoute em Startup.Configure.
Respostas HTTP 400 automáticas
O [ApiController] atributo faz com que os erros de validação do modelo acionem automaticamente uma resposta HTTP 400. Consequentemente, o código a seguir é desnecessário em um método de ação:
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
ASP.NET Core MVC usa o ModelStateInvalidFilter filtro de ação para fazer a verificação anterior.
Resposta padrão de "BadRequest"
Com uma versão de compatibilidade de 2.1, o tipo de resposta padrão para uma resposta HTTP 400 é SerializableError. O seguinte corpo de solicitação é um exemplo do tipo serializado:
{
"": [
"A non-empty request body is required."
]
}
Com uma versão de compatibilidade 2.2 ou posterior, o tipo de resposta padrão para uma resposta HTTP 400 é ValidationProblemDetails. O seguinte corpo de solicitação é um exemplo do tipo serializado:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|7fb5e16a-4c8f23bbfc974667.",
"errors": {
"": [
"A non-empty request body is required."
]
}
}
O ValidationProblemDetails tipo:
- Fornece um formato legível por máquina para especificar erros em respostas de API da Web.
- Está em conformidade com a especificação RFC 7807.
Para tornar as respostas automáticas e personalizadas consistentes, chame o ValidationProblem método em vez de BadRequest.
ValidationProblem retorna o ValidationProblemDetails objeto e a resposta automática.
Registo automático de respostas 400
Desativar resposta automática 400
Para desativar o comportamento automático 400, defina a SuppressModelStateInvalidFilter propriedade como true. Adicione o seguinte código realçado em Startup.ConfigureServices:
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
});
Inferência de parâmetros de fonte de ligação
Um atributo binding source define o local no qual o valor de um parâmetro action é encontrado. Existem os seguintes atributos de origem de ligação:
| Attribute | Fonte de ligação |
|---|---|
[FromBody] |
Corpo de solicitação |
[FromForm] |
Dados do formulário no corpo da solicitação |
[FromHeader] |
Cabeçalho do pedido |
[FromQuery] |
Parâmetro de cadeia de caracteres de consulta de solicitação |
[FromRoute] |
Dados de rota da solicitação atual |
[FromServices] |
O serviço de solicitação injetado como um parâmetro de ação |
Warning
Não use [FromRoute] quando os valores podem conter %2f (ou seja /, ).
%2f não será desfeito para /. Use [FromQuery] se o valor pode conter %2f.
Sem o atributo [ApiController] ou atributos de origem de ligação como [FromQuery], o tempo de execução do ASP.NET Core tenta usar o binder de modelo de objeto complexo. O fichário de modelo de objeto complexo extrai dados de provedores de valor em uma ordem definida.
No exemplo a seguir, o [FromQuery] atributo indica que o valor do discontinuedOnly parâmetro é fornecido na cadeia de caracteres de consulta da URL da solicitação:
[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 [ApiController] atributo aplica regras de inferência para as fontes de dados padrão dos parâmetros de ação. Essas regras evitam que você precise identificar fontes de vinculação manualmente aplicando atributos aos parâmetros de ação. As regras de inferência de fontes vinculativas comportam-se da seguinte forma:
-
[FromBody]é inferida para parâmetros de tipo complexos. Uma exceção à[FromBody]regra de inferência é qualquer tipo complexo, embutido com um significado especial, como IFormCollection e CancellationToken. O código-fonte de inferência de ligação ignora esses tipos especiais. -
[FromForm]é inferido para parâmetros de ação do tipo IFormFile e IFormFileCollection. Não é inferido para nenhum tipo simples ou definido pelo usuário. -
[FromRoute]é inferido para qualquer nome de parâmetro de ação correspondente a um parâmetro no modelo de rota. Quando mais de uma rota corresponde a um parâmetro action, qualquer valor de rota é considerado[FromRoute]. -
[FromQuery]é inferido para quaisquer outros parâmetros de ação.
Notas de inferência FromBody
[FromBody] não é inferido para tipos simples como string ou int. Portanto, o [FromBody] atributo deve ser usado para tipos simples quando essa funcionalidade é necessária.
Quando uma ação tem mais de um parâmetro vinculado do corpo da solicitação, uma exceção é lançada. Por exemplo, todas as seguintes assinaturas de método de ação causam uma exceção:
[FromBody]inferido em ambos porque são tipos complexos.[HttpPost] public IActionResult Action1(Product product, Order order)[FromBody]atributo num, inferido no outro por ser um tipo complexo.[HttpPost] public IActionResult Action2(Product product, [FromBody] Order order)[FromBody]atributo em ambos.[HttpPost] public IActionResult Action3([FromBody] Product product, [FromBody] Order order)
Note
No ASP.NET Core 2.1, parâmetros de tipo de coleção, como listas e matrizes, são incorretamente inferidos como [FromQuery]. O [FromBody] atributo deve ser usado para esses parâmetros se eles devem ser vinculados a partir do corpo da solicitação. Esse comportamento é corrigido no ASP.NET Core 2.2 ou posterior, onde os parâmetros de tipo de coleção são inferidos para serem vinculados do corpo por padrão.
Desativar regras de inferência
Para desativar a inferência de origem de vinculação, defina SuppressInferBindingSourcesForParameters como true. Adicione o seguinte código em Startup.ConfigureServices:
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
});
Inferência de solicitação de várias partes/dados de formulário
O [ApiController] atributo aplica uma regra de inferência para parâmetros de ação do tipo IFormFile e IFormFileCollection. O multipart/form-data tipo de conteúdo da solicitação é inferido para esses tipos.
Para desativar o comportamento padrão, defina a SuppressConsumesConstraintForFormFileParameters propriedade como true em Startup.ConfigureServices:
services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
});
Detalhes do problema para códigos de estado de erro
Quando a versão de compatibilidade é 2.2 ou posterior, o MVC transforma um resultado de erro (um resultado com código de status 400 ou superior) em um resultado com ProblemDetails. O ProblemDetails tipo é baseado na especificação RFC 7807 para fornecer detalhes de erro legíveis por máquina em uma resposta HTTP.
Considere o seguinte código em uma ação do controlador:
if (pet == null)
{
return NotFound();
}
O NotFound método produz um código de status HTTP 404 com um ProblemDetails corpo. Por exemplo:
{
type: "https://tools.ietf.org/html/rfc7231#section-6.5.4",
title: "Not Found",
status: 404,
traceId: "0HLHLV31KRN83:00000001"
}
Desativar a resposta de ProblemDetails
A criação automática de um ProblemDetails para códigos de status de erro é desabilitada quando a SuppressMapClientErrors propriedade é definida como true. Adicione o seguinte código em Startup.ConfigureServices:
Definir tipos de conteúdo de solicitação suportados com o atributo [Consumes]
Por padrão, uma ação suporta todos os tipos de conteúdo de solicitação disponíveis. Por exemplo, se um aplicativo estiver configurado para dar suporte à entrada JSON e XML formatters, uma ação dará suporte a vários tipos de conteúdo, incluindo application/json e application/xml.
O atributo [Consumes] permite que uma ação limite os tipos de conteúdo de solicitação suportados. Aplique o [Consumes] atributo a uma ação ou controlador, especificando um ou mais tipos de conteúdo:
[HttpPost]
[Consumes("application/xml")]
public IActionResult CreateProduct(Product product)
No código anterior, a CreateProduct ação especifica o tipo application/xmlde conteúdo . As solicitações roteadas para essa ação devem especificar um Content-Type cabeçalho de application/xml. Solicitações que não especificam um cabeçalho Content-Type resultam em uma resposta application/xml.
O [Consumes] atributo também permite que uma ação influencie sua seleção com base no tipo de conteúdo de uma solicitação de entrada aplicando uma restrição de tipo. Considere o seguinte exemplo:
[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
[HttpPost]
[Consumes("application/json")]
public IActionResult PostJson(IEnumerable<int> values) =>
Ok(new { Consumes = "application/json", Values = values });
[HttpPost]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}
No código anterior, ConsumesController está configurado para lidar com solicitações enviadas para a https://localhost:5001/api/Consumes URL. Ambas as ações PostJson do controlador e PostForm, lidam com solicitações POST com a mesma URL. Sem que o [Consumes] atributo aplique uma restrição de tipo, uma exceção de correspondência ambígua é lançada.
O [Consumes] atributo é aplicado a ambas as ações. A ação PostJson lida com solicitações enviadas com um cabeçalho Content-Type de application/json. A ação PostForm lida com solicitações enviadas com um cabeçalho Content-Type de application/x-www-form-urlencoded.
Recursos adicionais
- Tipos de retorno de ação do controlador na API Web ASP.NET Core
- Manipular erros em APIs do ASP.NET Core
- Formatações personalizadas na Web API do ASP.NET Core
- Formatar dados de resposta em ASP.NET API Web Principal
- Documentação da ASP.NET Core web API com Swagger / OpenAPI
- Roteamento para ações do controlador no ASP.NET Core
- Criar uma API da Web com o ASP.NET Core