2 May 2018
Routing in .NET Core Web API is a powerful mechanism that allows you to map HTTP requests to controllers and actions in a structured way. While basic routing is quite straightforward, advanced routing techniques offer more flexibility, allowing you to create complex and maintainable routing patterns.
In this post, we’ll explore advanced routing techniques in .NET Core Web API, focusing on route templates, route constraints, and how to customize action results like Ok()
, NotFound()
, and BadRequest()
to make your APIs more robust.
Advanced Routing Techniques in .NET Core Web API
When building RESTful Web APIs, it’s crucial to design your routes efficiently. By default, .NET Core uses attribute routing and conventional routing, which gives you flexibility in defining how URLs map to controllers and actions.
Let’s explore a few advanced routing concepts.
1. Route Templates and Parameters
Route templates help define the structure of your route and allow you to pass parameters. In .NET Core, you can specify route parameters using curly braces {}
.
Example:
[Route("api/products/{id}")]
public IActionResult GetProductById(int id)
{
// Your logic to get the product by id
}
In this example, the route api/products/{id}
maps to the GetProductById
action method. The {id}
in the URL is a placeholder for a parameter that the action method will use.
2. Optional Route Parameters
Sometimes you want a route parameter to be optional. In .NET Core, you can make route parameters optional by using a ?
after the parameter name.
Example:
[Route("api/products/{category?}")]
public IActionResult GetProductsByCategory(string category)
{
if (string.IsNullOrEmpty(category))
{
return Ok(_productService.GetAllProducts());
}
return Ok(_productService.GetProductsByCategory(category));
}
In this example, the category
parameter is optional. If no category is provided, the method will return all products. If a category is provided, it will return products for that category.
3. Route Constraints
Route constraints allow you to restrict the type of parameter that can be passed to an action. This ensures that only valid data types are passed to your actions.
Example:
[Route("api/products/{id:int}")]
public IActionResult GetProductById(int id)
{
// This route only matches if 'id' is an integer
}
In this example, the route api/products/{id:int}
only matches requests where id
is an integer. If the parameter does not match the specified type, .NET Core will return a 404 Not Found
response.
4. Multiple Route Templates
You can define multiple route templates for a single action method, which allows the same method to be accessed via different routes.
Example:
[Route("api/products/{id}")]
[Route("api/items/{id}")]
public IActionResult GetProductOrItemById(int id)
{
// Retrieve product or item by id
}
In this example, the same action method can be accessed via two different routes: api/products/{id}
and api/items/{id}
. This can be useful when you want to support multiple route patterns for the same functionality.
Customizing Action Results in .NET Core
.NET Core Web API provides several helper methods for returning standard HTTP responses, such as Ok()
, BadRequest()
, and NotFound()
. These methods are part of the ControllerBase
class and are often used to return different status codes along with data or error messages.
Let’s look at how to use these action result methods.
1. Ok() – 200 OK Response
The Ok()
method returns a 200 OK
response along with an optional object.
Example:
public IActionResult GetProduct(int id)
{
var product = _productService.GetProductById(id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
In this example, if the product is found, an Ok()
response is returned along with the product data. The Ok()
method can also accept an object, which will be serialized to JSON.
2. NotFound() – 404 Not Found Response
The NotFound()
method is used to return a 404 Not Found
response when the requested resource is not found.
Example:
public IActionResult GetProduct(int id)
{
var product = _productService.GetProductById(id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
If the product
is null
, we return a 404 Not Found
response.
3. BadRequest() – 400 Bad Request Response
The BadRequest()
method is used when the client sends a request that the server cannot process due to bad input, such as invalid data or missing parameters.
Example:
public IActionResult CreateProduct(Product product)
{
if (product == null || string.IsNullOrEmpty(product.Name))
{
return BadRequest("Invalid product data.");
}
_productService.AddProduct(product);
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
If the product data is invalid (e.g., the product name is missing), the BadRequest()
method returns a 400 Bad Request
response with a message.
4. CreatedAtAction() – 201 Created Response
The CreatedAtAction()
method returns a 201 Created
response, typically used when a new resource has been successfully created. This method includes the URI of the newly created resource.
Example:
public IActionResult CreateProduct(Product product)
{
if (product == null)
{
return BadRequest("Invalid product data.");
}
_productService.AddProduct(product);
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
}
In this example, the CreatedAtAction()
method is used to return a 201 Created
response and the location of the newly created product resource.
Conclusion
Advanced routing and customizing action results are key techniques for building robust and flexible APIs in .NET Core. By understanding how to design efficient routes with route templates, constraints, and multiple templates, you can create maintainable and clean routes. Similarly, customizing action results like Ok()
, NotFound()
, and BadRequest()
ensures that your API returns the appropriate HTTP responses, making it more intuitive for clients to consume.
In this post, we covered:
- Advanced routing techniques, including templates, constraints, and multiple routes
- How to use and customize action results (
Ok()
,NotFound()
,BadRequest()
,CreatedAtAction()
)
In the next post, we’ll continue exploring more advanced topics in .NET Core Web API development. Stay tuned!