DEV Community

Cover image for How to Access Query Strings in Minimal APIs
Shawn Wildermuth
Shawn Wildermuth

Posted on • Originally published at wildermuth.com on

2

How to Access Query Strings in Minimal APIs

I love that this job allows me to learn new stuff every day. In this case, I was building a simple API to use for some upcoming Pluralsight courses. I wanted to use Minimal APIs to expose some data for an old dataset from FiveThirtyEight on Bechdel Tests for Films. While I was adding paging, I got confused.

So, I started with a minimal API for getting all the films like so:

app.MapGet("api/films", async (BechdelDataService ds) =>
{

  if (ds is null) return Results.BadRequest();
  FilmResult data = await ds.LoadAllFilmsAsync();
  if (data.Results is null) return Results.NotFound();

  return Results.Ok(data);

}).WithTags("By Film").Produces(200).ProducesProblem(404);

Enter fullscreen mode Exit fullscreen mode

Pretty simple Minimal API to get some data (my BechdelDataService is just a repository-like class). When I added paging, I wanted to use the typical Web API trick of using optional parameters:

app.MapGet("api/films", async (BechdelDataService ds, 
  int page = 1, 
  int pageSize = 50) =>
{
...
}).WithTags("By Film").Produces(200).ProducesProblem(404);

Enter fullscreen mode Exit fullscreen mode

To my surprise this didn’t work. What I expected was that if I used a query string, it would bind to the extra parameters by name:

/api/films?page=1
/api/films

Enter fullscreen mode Exit fullscreen mode

In this case, these should be the same. What is going on. At first I dove into seeing why Minimal APIs didn’t support this. I didn’t see much about it, I saw options to read the query strings manually:

app.MapGet("api/films", async (
    HttpRequest request, 
    BechdelDataService ds) =>
{
  var page = request.Query["page"] ?? 1;
  var size = request.Query["pageSize"] ?? 50;

...


}).WithTags("By Film").Produces(200).ProducesProblem(404);

Enter fullscreen mode Exit fullscreen mode

This works, but I found it clunky. I wanted binding to work. I saw some examples that broke out the lambda to a method:

app.MapGet("api/films", GetAllFilms);

async Task<IResult> GetAllFilms(BechdelDataService ds, 
  int page = 1, 
  int pageSize = 50)
{
    ...
}

Enter fullscreen mode Exit fullscreen mode

This works, so the problem wasn’t with Minimal APIs, the problem is that Lambdas do not support default values (since you’re passing in a lambda, the spec assumes that you’ll supply all values).

So this is a fix? I don’t like the messiness of breaking it out into separate methods. So how do we fix it? Let’s use nullable values:

app.MapGet("api/films", async (BechdelDataService ds, 
  int? page, 
  int? pageSize) =>
{
  if (ds is null) return Results.BadRequest();
  int pageNumber = page ?? 1;
  int pagerTake = pageSize ?? 50;

  FilmResult data = await ds.LoadAllFilmsAsync(pageNumber, pagerTake);
  if (data.Results is null) return Results.NotFound();

  return Results.Ok(data);


}).WithTags("By Film").Produces(200).ProducesProblem(404);

Enter fullscreen mode Exit fullscreen mode

By supplying the values as nullable types (int?), we have to do our own defaulting, but I think it’s acceptable. One note here, is that I’m defining the types to non-nullable types to make my calls to the data service easier, but this isn’t necessary.

So, was I the only one who didn’t know that default values weren’t supported in lambda’s?

Creative Commons License

This work by Shawn Wildermuth is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

Based on a work at wildermuth.com.


If you liked this article, see Shawn's courses on Pluralsight.

Heroku

Deliver your unique apps, your own way.

Heroku tackles the toil — patching and upgrading, 24/7 ops and security, build systems, failovers, and more. Stay focused on building great data-driven applications.

Learn More

Top comments (1)

Collapse
 
rmaurodev profile image
Ricardo

I didn`t know that too. great article

AWS Industries LIVE! Stream

Watch AWS Industries LIVE!

New tech. Real solutions. See what’s possible on Industries LIVE! with AWS and AWS Partners.

Learn More

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay