Routing Variations in WEB API

Routing variations in ASP.NET Web API refer to different ways you can define and customize routes to match specific URL patterns and parameter constraints. In this comprehensive lesson, we’ll explore various routing variations with code examples to demonstrate their usage.

Basic Routing

Code Example: Default Route

// Default route defined in WebApiConfig.cs
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

In this default route, the URL pattern includes placeholders for the controller name and an optional “id” parameter. It allows you to access controller actions like api/products and api/products/123, where “products” is the controller name, and “123” is an optional ID.

Attribute Routing

Code Example: Attribute Routing

[RoutePrefix("api/products")]
public class ProductsController : ApiController
{
    [HttpGet]
    [Route("")]
    public IHttpActionResult GetAllProducts()
    {
        // Handle GET request for all products
        // ...
    }

    [HttpGet]
    [Route("{id:int}")]
    public IHttpActionResult GetProductById(int id)
    {
        // Handle GET request for a specific product by ID
        // ...
    }
}

Attribute routing allows you to define routes directly on controller actions and provides more control over route templates and constraints. In this example, we use [RoutePrefix] to specify a common prefix for all actions within the controller and [Route] attributes to define individual routes.

Route Constraints

Code Example: Route Constraints

[RoutePrefix("api/orders")]
public class OrdersController : ApiController
{
    [HttpGet]
    [Route("{id:int}")]
    public IHttpActionResult GetOrderById(int id)
    {
        // Handle GET request for a specific order by ID
        // ...
    }

    [HttpGet]
    [Route("customer/{customerId:int:min(1)}")]
    public IHttpActionResult GetOrdersByCustomer(int customerId)
    {
        // Handle GET request for orders by customer ID
        // ...
    }
}

Route constraints allow you to specify validation rules for route parameters. In the above example, {id:int} enforces that the “id” parameter must be an integer, and {customerId:int:min(1)} specifies that “customerId” must be an integer greater than or equal to 1.

Route Defaults

Code Example: Route Defaults

[RoutePrefix("api/customers")]
public class CustomersController : ApiController
{
    [HttpGet]
    [Route("{id:int=1}")]
    public IHttpActionResult GetCustomerById(int id)
    {
        // Handle GET request for a specific customer by ID (defaulting to 1 if not provided)
        // ...
    }
}

Route defaults allow you to specify default values for route parameters. In the example, {id:int=1} sets the default value of “id” to 1 if not provided in the URL.

Route Order

Code Example: Route Order

[RoutePrefix("api/orders")]
public class OrdersController : ApiController
{
    [HttpGet]
    [Route("{id:int}", Order = 2)]
    public IHttpActionResult GetOrderById(int id)
    {
        // Handle GET request for a specific order by ID
        // ...
    }

    [HttpGet]
    [Route("customer/{customerId:int}", Order = 1)]
    public IHttpActionResult GetOrdersByCustomer(int customerId)
    {
        // Handle GET request for orders by customer ID
        // ...
    }
}

Route order determines the precedence of routes when multiple routes match a request. In this example, we use the Order property to specify the order in which routes should be evaluated. The higher the order, the higher the precedence.

Custom Route Constraints

Code Example: Custom Route Constraint

public class EvenIdConstraint : IHttpRouteConstraint
{
    public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection)
    {
        if (values.TryGetValue(parameterName, out var value) && value != null)
        {
            if (int.TryParse(value.ToString(), out int intValue))
            {
                return intValue % 2 == 0;
            }
        }
        return false;
    }
}

[RoutePrefix("api/products")]
public class ProductsController : ApiController
{
    [HttpGet]
    [Route("even/{id:evenId}")]
    public IHttpActionResult GetProductById(int id)
    {
        // Handle GET request for a product with an even ID
        // ...
    }
}

Custom route constraints allow you to define your own validation logic for route parameters. In this example, we create an EvenIdConstraint that ensures the “id” parameter must be an even number.

Conclusion

Routing variations in ASP.NET Web API provide powerful ways to define and customize your API routes, constraints, defaults, and order. By leveraging these features, you can create well-structured, flexible, and expressive API endpoints that suit your application’s needs.