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.

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (1)

Collapse
 
rmaurodev profile image
Ricardo

I didn`t know that too. great article

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay