I'm looking to convert our current API architecture to a more generic query-able structure that doesn't require us to hard card each possible parameter and build up a custom query. Here is an example of what our current architecture looks like,
[HttpGet]
[Route("Companies/{id:int}/Implementations/Tasks")]
public async Task<IApiResponse<List<CompanyIPTDTO>>> GetCompanyIPTs(int? id = null,
int? taskId = null, int? completedById = null, DateTime? dateCompletedStart = null,
DateTime? dateCompletedEnd = null, int page = 1, int? pageSize = null)
{
// Instantiate generic query
Expression<Func<CompanyIPT, bool>> query = null;
// Check parameters and build the lambda query
// Check if the parameter is given and if the query field is already filled so as to either set or add a query
if (id != null && query != null) query = query.And(t => t.CompanyID == id);
else if (id != null && query == null) query = t => t.CompanyID == id;
if (taskId != null && query != null) query = query.And(t => t.ProcessTaskID == taskId);
else if (taskId != null && query == null) query = t => t.ProcessTaskID == taskId;
if (completedById != null && query != null) query = query.And(t => t.CompletedByID == completedById);
else if (completedById != null && query == null) query = t => t.CompletedByID == completedById;
if ((dateCompletedStart != null && dateCompletedEnd != null) && query != null) query = query.And(a => a.DateCompleted >= dateCompletedStart && a.DateCompleted <= dateCompletedEnd);
else if ((dateCompletedStart != null && dateCompletedEnd != null) && query == null) query = a => a.DateCompleted >= dateCompletedStart && a.DateCompleted <= dateCompletedEnd;
// Execute the GET with the appended query and paging information
var result = _uow.CompanyIPTRepository.List(filter: query, page: page, pageSize: pageSize);
int totalPossibleRecords = _uow.CompanyIPTRepository.GetTotalRecords(filter: query);
return new ApiSuccessResponse<List<CompanyIPTDTO>>(HttpStatusCode.OK, result.Select(x => Mapper.Map<CompanyIPTDTO>(x)).ToList(), result.Count(), Request.RequestUri, totalPossibleRecords, pageSize);
}
And as you can see this gets very cumbersome for a large API on every get request to have to customize the query checks. I assume there must be some way to do this generically based on a query string parameter that comes in. For example in this case I would love to see a request come in that looks like,
https://www.example.com/api/Companies/15/Implementations/Tasks?q=[completedById=5,dateCompletedStart=1/15/18,dateCompletedEnd=1/17/18]
And after coming in like this I assume we could build something that uses Reflection to look at the object and verify these fields exist and build up a generic query to hit our DB?
Anyone know where to point us in the right direction?