skip to Main Content

I wrote an endpoint which accepts MediaParams object which extends another param class and together they act like a wrapper for parameters and look like this:

public class MediaParams : PaginationParams
    {
        public string OrderBy { get; set; } = "title";
        public string SearchTerm { get; set; } = string.Empty;
        public string Genres { get; set; } = string.Empty;
    }
    public class PaginationParams
    {
        private const int MaxPageSize = 50;
        public int PageNumber { get; set; } = 1;
        private int _pageSize = 6;

        public int PageSize
        {
            get => _pageSize;
            set => _pageSize = value > MaxPageSize ? MaxPageSize : value;
        }
    }

As you may notice I also assigned a default values for each property as I want to make them optional, my endpoint

app.MapGet("/media/getby", async (
    [AsParameters] MediaParams pa,
    IMediator mediator,
    HttpContext context) =>
{
    var mediaListDto = await mediator.Send(new GetMediaByParamsQuery(pa));

    if (mediaListDto is not { Count: > 0 })
    {
        return Results.NotFound("No media was found by these params.");
    }
    context.Response.Headers.Add("Pagination", JsonSerializer.Serialize(mediaListDto.MetaData));
    return Results.Ok(mediaListDto);
});

Now it works ok, but only if I specify every single property in my uri like this:

serveraddress/media/getby?OrderBy=rating&SearchTerm=pal&Genres=Drama&PageNumber=1&PageSize=10

Could someone help me to rewrite the logic so I could use these params individually to override default values, or not use at all to keep default values? Thanks.

2

Answers


  1. Chosen as BEST ANSWER

    I've created a class that reads the request and "assembles" a parameters object or keeps default values, I also removed default values from Parameter classes like MediaParams and PaginationParams, and also removed the nullability from properties of these classes

    public static class QueryHelper
    {
        private const string OrderByDefaultValue = "title";
        private const string SearchTermDefaultValue = "";
        private const int PageNumberDefaultValue = 1;
        private const int PageSizeDefaultValue = 6;
    
    
        public static MediaParams GetMediaParams(HttpContext context)
        {
            var mediaParams = new MediaParams
            {
                OrderBy = OrderByDefaultValue,
                SearchTerm = SearchTermDefaultValue,
                Genres = null,
                PageNumber = PageNumberDefaultValue,
                PageSize = PageSizeDefaultValue
            };
            //other parameters
            return mediaParams;
        }
    }
    

    In endpoint I am calling this class like this

    var pa = QueryHelper.GetMediaParams(context); 
    

  2. It seems that AsParameter by default requires all properties and when it deserialises it skips the default values because it uses FormatterServices.GetUninitializedObject that instantiates an object but without invocation of its constructor and field initializers (because of performance purposes as this class & method should be used for serialisation/deserialisation).

    When I changed your models to the following code, it started doing its job:

    public class MediaParams : PaginationParams
        {
            [DefaultValue("title")]
            public string? OrderBy { get; set; }
    
            [DefaultValue(" ")]
            public string? SearchTerm { get; set; }
    
            [DefaultValue(" ")]
            public string? Genres { get; set; }
        }
    
        public class PaginationParams
        {
            private const int MaxPageSize = 50;
    
            [DefaultValue(1)]
            public int? PageNumber { get; set; }
            
            [DefaultValue(6)]
            public int? PageSize { get; set; }
        }
    

    Sadly, when DefaultValue has a value of "" (string.Empty) passed, it converts it to null. If you play around with setters and logic there to prevent assigning nulls, this should do the work for you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search