0

I'm trying to return a Tuple in a minimal API, it boils down to this:

app.MapPost("/colorkeyrect", () => server.ColorkeyRect());

public (int x, int y, int w, int h) ColorkeyRect()
{
  return (10, 10, 10, 10);
}

But the data that is sent over the wire is an empty json:

content = await response.Content.ReadAsStringAsync();

'{}'

var obj = JsonConvert.DeserializeObject<(int, int, int, int)>(content);

So this becomes (0, 0, 0, 0) instead of (10, 10, 10, 10).

Is it even possible to return a Tuple in a Minimal API app? What to do to get a valid object returned when only relying on primitive types?

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
Serve Laurijssen
  • 9,266
  • 5
  • 45
  • 98
  • 2
    The default json serialiser ignores fields, and only serialises properties. You could probably return an anonymous type instead, since tuples don't really have property names.. – Jeremy Lakeman May 10 '23 at 06:23
  • 2
    What would be the benefit of a `Tuple` over an actual DTO? – Fildor May 10 '23 at 06:26
  • 2
    To me, it sounds like you should return an actual DTO. This helps with readability and can help avoid confusion. I had to think for at least 10s to figure out that your object is a rectangle and not something else. – JonasH May 10 '23 at 06:31
  • the benefit is that a client does not need more classes and only relies on primitive types – Serve Laurijssen May 10 '23 at 07:49
  • @Fildor `ValueTuple<...>`, not `Tuple<...>` =) – Guru Stron May 10 '23 at 13:53
  • 1
    @GuruStron Ok, "anything _but_ a DTO over a DTO"? :D – Fildor May 10 '23 at 13:56
  • 1
    @ServeLaurijssen I would argue that there is no much benefit here. If client does not want to deserialize to some class - `Dictionary` always can be used. – Guru Stron May 10 '23 at 13:59

1 Answers1

2

Yes, it is possible. By default System.Text.Json does not serialize fields, and value tuple elements are fields (ValueTuple), so you need to configure JsonOptions (be sure to use "correct" ones - for Minimal APIs from Microsoft.AspNetCore.Http.Json namespace):

builder.Services.Configure<JsonOptions>(options => options.SerializerOptions.IncludeFields = true);

But I would argue that it is a bit useless, value tuple names is a piece of information which is not represented at runtime so you will get response like:

{"item1":1,"item2":2}

I would recommend to use either anonymous type or just create a record (record struct if really needed), it is very easy to create a new DTO type nowadays. And with target-typed new expressions it is not a big change in the method also:

record Responce(int X, int Y, int W, int H); // or record struct Responce ...

public Responce ColorkeyRect()
{
    return new (10, 10, 10, 10);
}
Guru Stron
  • 102,774
  • 10
  • 95
  • 132