#csharp #dotnet #backend

Day 13: Routing & Parsing Parameters

Welcome to Day 13. Yesterday we built flat endpoints like /users. But what if a client wants a specific user? Or what if they want to filter users by age?

We use Route Parameters and Query Strings.

Route Parameters

Route parameters are variables embedded directly into the URL path. They are ideal for identifying specific resources (like IDs).

You wrap the parameter in curly braces {} inside the route string, and provide a matching parameter name in the delegate method.

// Path: GET /users/42
app.MapGet("/users/{id}", (int id) => 
{
    return $"You requested user ID: {id}";
});

Because we typed (int id), ASP.NET Core will automatically cast the URL string into an integer. If the user hits /users/abc, the server will cleanly return a 400 Bad Request!

Route Constraints

You can also enforce the type natively in the route string constraint:

// Only matches if 'id' is a valid integer. 
app.MapGet("/products/{id:int}", (int id) => ...);

// Must be an int, and must be greater than 0
app.MapGet("/orders/{id:int:min(1)}", (int id) => ...);

// A GUID
app.MapGet("/tokens/{token:guid}", (Guid token) => ...);

Query Strings

Query strings are the key/value pairs at the end of a URL after the ? mark. Example: /search?query=shoes&page=2. They are amazing for filtering, searching, and pagination.

If you add parameters to your delegate definition that are not defined in the Route template ({}), ASP.NET Core assumes they are coming from the Query String!

// The route path is just "/search"
app.MapGet("/search", (string searchTerm, int page) => 
{
    return $"Searching for '{searchTerm}' on page {page}";
});

To trigger this endpoint, the client must navigate to /search?searchTerm=coffee&page=1.

Using Special Attributes [From...]

Sometimes Minimal APIs get confused about where a parameter is coming from (Is it JSON body? Query String? Header?). We can be explicit using attributes:

using Microsoft.AspNetCore.Mvc; 

app.MapGet("/secure", (
    [FromQuery] string apikey,    // From ?apikey=123
    [FromHeader] string userAgent // From HTTP Headers
) => 
{
    return "Secure data accessed via " + userAgent;
});

Challenge for Day 13

Create an endpoint /weather/{city}. Add an optional query parameter days (default it to 3 in the method signature). Return a string specifying what city the weather is for and how many days of forecast you are returning. Hit it via browser!

Tomorrow: IResult and Status Codes.