Enrutamiento en ASP.NET WEB API

En este artículo se describe cómo ASP.NET API web enruta las solicitudes HTTP a los controladores.

Nota:

Si está familiarizado con ASP.NET MVC, el enrutamiento de API web es muy similar al enrutamiento de MVC. La principal diferencia es que la API web usa el verbo HTTP, no la ruta de acceso del URI, para seleccionar la acción. También puede usar el enrutamiento de estilo MVC en la API web. En este artículo no se supone ningún conocimiento de ASP.NET MVC.

Tablas de enrutamiento

En ASP.NET API web, un controlador es una clase que controla las solicitudes HTTP. Los métodos públicos del controlador se denominan métodos de acción o simplemente acciones. Cuando el marco de API web recibe una solicitud, la dirige a una acción.

Para determinar qué acción se va a invocar, el marco usa una tabla de enrutamiento. La plantilla de proyecto de Visual Studio para la API web crea una ruta predeterminada:

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

Esta ruta se define en el archivo WebApiConfig.cs, que se coloca en el directorio App_Start:

Image of Solution Explorer where routes are defined.

Para obtener más información sobre la clase WebApiConfig, vea Configuración de ASP.NET API web.

Si autohospeda la API web, debe establecer la tabla de enrutamiento directamente en el objeto HttpSelfHostConfiguration. Para obtener más información, vea Autohospede una API web.

Cada entrada de la tabla de enrutamiento contiene una plantilla de ruta. La plantilla de ruta predeterminada para la API web es "api/{controller}/{id}". En esta plantilla, "api" es un segmento de ruta de acceso literal y {controller} y {id} son variables de marcador de posición.

Cuando el marco de API web recibe una solicitud HTTP, intenta hacer coincidir el URI con una de las plantillas de ruta de la tabla de enrutamiento. Si no coincide ninguna ruta, el cliente recibe un error 404. Por ejemplo, los siguientes URI coinciden con la ruta predeterminada:

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

Sin embargo, el siguiente URI no coincide, ya que carece del segmento "api":

  • /contacts/1

Nota:

El motivo del uso de "api" en la ruta es evitar colisiones con ASP.NET enrutamiento de MVC. De este modo, puede hacer que "/contacts" vaya a un controlador MVC y "/api/contacts" vaya a un controlador de API web. Por supuesto, si no le gusta esta convención, puede cambiar la tabla de rutas predeterminada.

Una vez que se encuentra una ruta coincidente, la API web selecciona el controlador y la acción:

  • Para buscar el controlador, la API web agrega "Controller" al valor de la variable de {controller}.
  • Para buscar la acción, la API web examina el verbo HTTP y, a continuación, busca una acción cuyo nombre comienza con ese nombre de verbo HTTP. Por ejemplo, con una solicitud GET, la API web busca una acción con el prefijo "Get", como "GetContact" o "GetAllContacts". Esta convención solo se aplica a los verbos GET, POST, PUT, DELETE, HEAD, OPTIONS y PATCH. Puede habilitar otros verbos HTTP mediante atributos en el controlador. Veremos un ejemplo de eso más adelante.
  • Otras variables de marcador de posición de la plantilla de ruta, como {id}, se asignan a parámetros de acción.

Veamos un ejemplo. Supongamos que define el controlador siguiente:

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

Estas son algunas posibles solicitudes HTTP, junto con la acción que se invoca para cada una:

Verbo HTTP Ruta de acceso de URI Action Parámetro
OBTENER api/products GetAllProducts (none)
OBTENER api/products/4 GetProductById 4
Delete api/products/4 DeleteProduct 4
PUBLICAR api/products (sin coincidencia)

Observe que el {id} segmento del URI, si está presente, se asigna al id parámetro de la acción. En este ejemplo, el controlador define dos métodos GET, uno con un parámetroid y otro sin parámetros.

Además, tenga en cuenta que se producirá un error en la solicitud POST, ya que el controlador no define un método "Post...".

Variaciones de enrutamiento

En la sección anterior se describe el mecanismo de enrutamiento básico para ASP.NET API web. En esta sección se describen algunas variaciones.

Verbos HTTP

En lugar de usar la convención de nomenclatura para verbos HTTP, puede especificar explícitamente el verbo HTTP para una acción mediante la decoración del método de acción con uno de los atributos siguientes:

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

En el ejemplo siguiente, el método FindProduct se asigna a las solicitudes GET:

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

Para permitir varios verbos HTTP para una acción o permitir verbos HTTP distintos de GET, PUT, POST, DELETE, HEAD, OPTIONS y PATCH, use el atributo [AcceptVerbs], que toma una lista de verbos HTTP.

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

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

Enrutamiento por nombre de acción

Con la plantilla de enrutamiento predeterminada, la API web usa el verbo HTTP para seleccionar la acción. Sin embargo, también puede crear una ruta en la que el nombre de la acción se incluye en el URI:

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

En esta plantilla de ruta, el {action} nombre de parámetro del método de acción en el controlador. Con este estilo de enrutamiento, use atributos para especificar los verbos HTTP permitidos. Por ejemplo, supongamos que el controlador tiene el método siguiente:

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

En este caso, una solicitud GET para "api/products/details/1" se asignaría al método Details. Este estilo de enrutamiento es similar a ASP.NET MVC y puede ser adecuado para una API de estilo RPC.

Puede invalidar el nombre de la acción mediante el atributo [ActionName]. En el ejemplo siguiente, hay dos acciones que se asignan a "api/products/thumbnail/id. Uno admite GET y el otro admite POST:

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

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

No acciones

Para evitar que un método se invoque como una acción, use el atributo [NonAction]. Esto indica al marco de trabajo que el método no es una acción, aunque coincida con las reglas de enrutamiento.

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

Lecturas adicionales

En este tema se proporciona una vista general del enrutamiento. Para obtener más información, vea enrutamiento y selección de acciones, que describe exactamente cómo el marco coincide exactamente con un URI en una ruta, selecciona un controlador y, a continuación, selecciona la acción que se va a invocar.