Search code examples
c#asp.net-coregetquery-string

Is there any way to get complex object from query string in ASP.NET Core 8?


I'm trying to get a complex object from query string, object has some primitive types and 2 arrays of classes for filtering and sorting, but when I get the object from query string these 2 arrays are empty.

I was trying to ask Chat-GPT about it, googled this problem and have not found anything that can help me.

This is my DTO:

public record GetItemsSortedDto(
    int ParentId,
    SortingFieldDto[]? SortFields,
    Filter[]? Filters,
    int Page = 1,
    int PageSize = 10,
    string OrderColumn = "Number",
    bool IsSortedAsc = true)
    : IStandardForTypesOfConstructionDto;

public class SortingFieldDto
{
    public string Field { get; set; } = "Number";
    public object RangeStart { get; set; } = null!;
    public object RangeEnd { get; set; } = null!;
}

public class Filter
{
    public string Id { get; set; } = "TypeOfConstruction";
    [FromQuery(Name = "Value")]
    public string[] Values { get; set; } = null!;
}

And here is my controller method

[HttpGet("ItemsSorted")]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult> GetItemsSorted([FromQuery] GetItemsSortedDto getDto)
{
      var query = _mapper.Map<GetItemsByParentSortedQuery>(getDto);

      var result = await Mediator.Send(query);
      return Ok(query);
}  

I was trying to use model binding, but there was no success. In the DTO, I need to store arrays of sorting and filtering, so I can sort and filter more than 1 column simultaneously.


Solution

  • Update: Above solution should help for binding objects with [fromBody] attribute, but unfortunately (same documentation):

    "Route data and query string values are used only for simple types."

    So you cannot bind a complex object from just the query string.

    Original: From the Microsoft Documentation for Model Binding (https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-8.0#complex-types)

    "A complex type must have a public default constructor and public writable properties to bind".

    Your Dto class uses the new constructor model (which shouldn't be a problem), but it only has fields and no properties.

    I would try refactoring the fields to actual properties.