We are wanting to add: result limits, pagination, sorting and filtering to certain API’s in our services. And looking for a design pattern that can work for each API that wants to support these options.
Lets say I have a request DTO like this:
public class ListBananas
{
public SearchOptions Options { get; set; }
}
where SearchOptions
is a DTO like this:
public class SearchOptions
{
public int Limit { get; set; }
public int Offset { get; set; }
public Sorting Sort { get; set; }
public Filtering Filter { get; set; }
}
public class Sorting
{
public string By { get; set; }
public SortDirection Direction { get; set; }
}
public enum SortDirection
{
Ascending = 0,
Descending = 1
}
public class Filtering
{
public List<string> Fields { get; set; }
}
As you can see, we have decided to make SearchOptions
a hierarchical POCO, instead of adding a bunch of top level properties to our request DTO. Just a design decision.
We did that because we (a) wanted to keep this data together to pass through to our other layers within the service and i.e. a data store layer, (b) because we wanted to avoid inheritance in our DTO’s.
Now arguably however, we could define a IHasSearchOptions
interface and have ‘ListBananas’ inherit from that, that puts the properties directly in the request DTO, and have some component derive the hierarchical POCO for us to pass through the layers of our service.
public interface IHasSearchOptions
{
public int Limit { get; set;}
public int Offset { get; set;}
public string Sort { get; set;}
public string Filters { get; set;}
}
Now, it would be very nice to have fields (i.e. limit, offset, sort, filter) directly in the QueryString of the API call for convenience of the caller, but primarily for caching the responses as they will vary.
For example: GET /bananas?limit=50&sort=peeled
If we didn’t do IHasSearchOptions
approach, and stuck with SearchOptions
in the request DTO, is there a clever way, perhaps with RequestFilters or another mechanism, that for request DTO’s that have ‘SearchOptions’ we can effectively ‘extract’ fields like: limit, offset, sort and filter form the request QueryString? and internally construct the SearchOptions
and pass it to the Service Operation in a generic way?