Routing in ASP.NET Web API - ASP.NET Web API 2: Beginner Guide (2015)

ASP.NET Web API 2: Beginner Guide (2015)

Routing in ASP.NET Web API

Web API uses routing to match uniform resource identifiers (URIs) to various actions. The WebApiConfig file, located inside the App_Start node in Solution Explorer, defines the default routing mechanism used by Web API. The mechanism is based on a combination of HTTP method, action, and attribute. However, we can define our own routing mechanism to support meaningful URIs.

For example, in our sample Web API project, we use /api/Products to retrieve product details. However, we can instead use api/Products/GetAllProducts by modifying the default routing logic to include {action} as part of the URI, as shown in the following code snippet:

config.Routes.MapHttpRoute(

name: "DefaultApi",

routeTemplate: "api/{controller}/{action}/{id}",

defaults: new { id = RouteParameter.Optional }

);

After we update the route, we can use the ActionName attribute in our Web API method to specify the action name, as the follow snippet shows:

[ActionName("GetAllProducts")]

public IEnumerable<Product> GetAllProducts()

{……………………………..}

NOTE: Use the [NonAction] attribute to indicate that the Web API method is not an API action method.

We can also use an HTTP method or Acceptverbs attribute to specify the HTTP action required to access the Web API method. For example, the following snippet uses the HttpGet and HttpPost methods:

[HttpGet]

public IEnumerable<Product> GetProducts(int selectedId)

{………….. }

[HttpPost]

public void AddProduct(Product p)

{………….. }

For multiple methods, use the Acceptsverbs attribute, as shown in the following snippet:

[AcceptVerbs("GET","PUT")]

public IEnumerable<Product> GetProducts(int selectedId)

{………….. }

Attribute Routing

Web API 2 introduced the attribute routing. Earlier versions support the conventional routing mechanism discussed in last section. This approach is good for maintaining the routing logic in one place and apply consistently across the application. But, this approach lack the flexibility of defining the routing for objects with sub groups like Products may have different categories, books will have authors, and so on. Attribute routing address this issue and provides the flexibility to define the routing in granular levels.

Enable the routing

For enabling the attribute routing in Web API, call the MapHttpAttributeRoutes during the configuration. Open the WebApiConfig file, located inside the App_Start node in Solution Explorer. Following entry define the attribute routing capability.

// Web API routes

config.MapHttpAttributeRoutes();

This entry will be available in ASP.NET MVC 5 based project; if not available add the above statement to enable the attribute routing.

Add Route

Add the route attribute to the Web API method to define attribute routing for specific Web API methods

[Route("ProductDetail/{selectedId}")]

public IEnumerable<Product> GetProducts(int selectedId)

{………………………..}

Above method can be accessed now using http://localhost:59509/ProductDetail/2. Notice that the new URL not even have the api or controller names.

Route Prefix

Most of the time the controller will have the same format for the routes for all the methods.

public class ProductsController : ApiController

{

[Route("api/products")]

public IEnumerable<Product> GetProducts() { ... }

[Route("api/products/{id}")]

public Product GetProduct(int id) { ... }

}

We can use a RoutePrefix to avoid the duplicate entry of prefixes for the web API method Route attributes.

[RoutePrefix("api/products")]

public class ProductsController : ApiController

{

[Route("")]

public IEnumerable<Product> GetProducts() { ... }

[Route("{id}")]

public Product GetProduct(int id) { ... }

}

RoutePrefix will be applied in controller level.

Route Constraint

Route constraints help us to restrict the parameter processing. Consider the about attribute routing where we have defined a parameter ‘id’, without any constraint. Even if the client send a string value, the routing will try to match the parameter and throw an exception due to type mismatch. To avoid such runtime exceptions, we can define a constraint for the route parameters.

Route constraint will be defined as

{parameter: constraint}

Eg:-

Integer constraint - {id:int}

Integer with maximum value as 25 – {id:max(25)}

Datetime constraint – {startDate: datetime}

Guid constraint – {id:guid}

We can apply multiple constraints to a parameter by separating each constraint using a colon.

{id:int:min(1)} – indicate an integer with a minimum value of 1.