Roteamento no ASP.NET Web API

Este artigo descreve como ASP.NET Web API roteia solicitações HTTP para controladores.

Observação

Se você estiver familiarizado com ASP.NET MVC, o roteamento de API Web será muito semelhante ao roteamento MVC. A diferença main é que a API Web usa o verbo HTTP, não o caminho do URI, para selecionar a ação. Você também pode usar o roteamento no estilo MVC na API Web. Este artigo não pressupõe nenhum conhecimento de ASP.NET MVC.

Tabelas de roteamento

Em ASP.NET Web API, um controlador é uma classe que manipula solicitações HTTP. Os métodos públicos do controlador são chamados de métodos de ação ou simplesmente ações. Quando a estrutura da API Web recebe uma solicitação, ela encaminha a solicitação para uma ação.

Para determinar qual ação invocar, a estrutura usa uma tabela de roteamento. O modelo de projeto do Visual Studio para API Web cria uma rota padrão:

routes.MapHttpRoute(
    name: "API Default",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

Essa rota é definida no arquivo WebApiConfig.cs , que é colocado no diretório App_Start :

Imagem de Gerenciador de Soluções onde as rotas são definidas.

Para obter mais informações sobre a WebApiConfig classe , consulte Configurando ASP.NET Web API.

Se você auto-hospedar a API Web, deverá definir a tabela de roteamento diretamente no HttpSelfHostConfiguration objeto . Para obter mais informações, consulte Auto-hospedar uma API Web.

Cada entrada na tabela de roteamento contém um modelo de rota. O modelo de rota padrão para a API Web é "api/{controller}/{id}". Neste modelo, "api" é um segmento de caminho literal e {controller} e {id} são variáveis de espaço reservado.

Quando a estrutura da API Web recebe uma solicitação HTTP, ela tenta corresponder o URI com um dos modelos de rota na tabela de roteamento. Se nenhuma rota corresponder, o cliente receberá um erro 404. Por exemplo, os seguintes URIs correspondem à rota padrão:

  • /api/contacts
  • /api/contacts/1
  • /api/products/gizmo1

No entanto, o URI a seguir não corresponde, pois ele não tem o segmento "api":

  • /contacts/1

Observação

O motivo para usar a "api" na rota é evitar colisões com ASP.NET roteamento MVC. Dessa forma, você pode fazer com que "/contacts" acessem um controlador MVC e "/api/contacts" acesse um controlador de API Web. É claro que, se você não gostar dessa convenção, poderá alterar a tabela de rotas padrão.

Depois que uma rota correspondente é encontrada, a API Web seleciona o controlador e a ação:

  • Para localizar o controlador, a API Web adiciona "Controller" ao valor da variável {controller }.
  • Para localizar a ação, a API Web examina o verbo HTTP e procura uma ação cujo nome começa com esse nome de verbo HTTP. Por exemplo, com uma solicitação GET, a API Web procura uma ação prefixada com "Get", como "GetContact" ou "GetAllContacts". Essa convenção se aplica somente aos verbos GET, POST, PUT, DELETE, HEAD, OPTIONS e PATCH. Você pode habilitar outros verbos HTTP usando atributos no controlador. Veremos um exemplo disso mais tarde.
  • Outras variáveis de espaço reservado no modelo de rota, como {id}, são mapeadas para parâmetros de ação.

Vamos examinar um exemplo. Suponha que você defina o seguinte controlador:

public class ProductsController : ApiController
{
    public IEnumerable<Product> GetAllProducts() { }
    public Product GetProductById(int id) { }
    public HttpResponseMessage DeleteProduct(int id){ }
}

Aqui estão algumas solicitações HTTP possíveis, juntamente com a ação que é invocada para cada uma:

Verbo HTTP Caminho do URI Ação Parâmetro
GET api/products GetAllProducts (none)
GET api/products/4 GetProductById 4
Delete (excluir) api/products/4 DeleteProduct 4
POST api/products (sem correspondência)

Observe que o segmento {id} do URI, se presente, é mapeado para o parâmetro id da ação. Neste exemplo, o controlador define dois métodos GET, um com um parâmetro id e outro sem parâmetros.

Além disso, observe que a solicitação POST falhará, pois o controlador não define um método "Post...".

Variações de roteamento

A seção anterior descreveu o mecanismo de roteamento básico para ASP.NET Web API. Esta seção descreve algumas variações.

Verbos HTTP

Em vez de usar a convenção de nomenclatura para verbos HTTP, você pode especificar explicitamente o verbo HTTP para uma ação decorando o método de ação com um dos seguintes atributos:

  • [HttpGet]
  • [HttpPut]
  • [HttpPost]
  • [HttpDelete]
  • [HttpHead]
  • [HttpOptions]
  • [HttpPatch]

No exemplo a seguir, o FindProduct método é mapeado para solicitações GET:

public class ProductsController : ApiController
{
    [HttpGet]
    public Product FindProduct(id) {}
}

Para permitir vários verbos HTTP para uma ação ou permitir verbos HTTP diferentes de GET, PUT, POST, DELETE, HEAD, OPTIONS e PATCH, use o [AcceptVerbs] atributo , que usa uma lista de verbos HTTP.

public class ProductsController : ApiController
{
    [AcceptVerbs("GET", "HEAD")]
    public Product FindProduct(id) { }

    // WebDAV method
    [AcceptVerbs("MKCOL")]
    public void MakeCollection() { }
}

Roteamento por nome da ação

Com o modelo de roteamento padrão, a API Web usa o verbo HTTP para selecionar a ação. No entanto, você também pode criar uma rota em que o nome da ação está incluído no URI:

routes.MapHttpRoute(
    name: "ActionApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

Neste modelo de rota, o parâmetro {action} nomeia o método de ação no controlador. Com esse estilo de roteamento, use atributos para especificar os verbos HTTP permitidos. Por exemplo, suponha que o controlador tenha o seguinte método:

public class ProductsController : ApiController
{
    [HttpGet]
    public string Details(int id);
}

Nesse caso, uma solicitação GET para "api/products/details/1" seria mapeada para o Details método . Esse estilo de roteamento é semelhante a ASP.NET MVC e pode ser apropriado para uma API no estilo RPC.

Você pode substituir o nome da ação usando o [ActionName] atributo . No exemplo a seguir, há duas ações que são mapeadas para "api/products/thumbnail/id. Um dá suporte a GET e o outro dá suporte a POST:

public class ProductsController : ApiController
{
    [HttpGet]
    [ActionName("Thumbnail")]
    public HttpResponseMessage GetThumbnailImage(int id);

    [HttpPost]
    [ActionName("Thumbnail")]
    public void AddThumbnailImage(int id);
}

Não Ações

Para impedir que um método seja invocado como uma ação, use o [NonAction] atributo . Isso sinaliza para a estrutura que o método não é uma ação, mesmo que ele corresponda às regras de roteamento de outra forma.

// Not an action method.
[NonAction]  
public string GetPrivateData() { ... }

Leitura Adicional

Este tópico forneceu uma exibição de alto nível do roteamento. Para obter mais detalhes, consulte Seleção de Roteamento e Ação, que descreve exatamente como a estrutura corresponde um URI a uma rota, seleciona um controlador e, em seguida, seleciona a ação a ser invocada.