I have a Web Api endpoint which is currently called like this:
http://api.example.com/scenes?creationDate=1440091949
I am trying to support more complex queries such as:
http://api.example.com/scenes?creationDate.lt=1440091949
Note the .lt suffix. This would let the user to list all the scenes in which creationDate is less than (lt) than 1440091949.
For this, I had to create my own mapper function which would map each query parameter to a query model's properties and store each query operation (lt, gt, eq, etc...) in a dictionary of operations:
protected QueryData MapToQueryData(IEnumerable<KeyValuePair<string, string>> queryParameters)
{
QueryData queryData = new QueryData();
foreach(var queryParam in queryParameters)
{
string[] segments = queryParam.Key.Split('.'); // ["creationDate", "lt"]
if(!segments.Any()) continue;
PropertyInfo queryProperty = _reflection.Properties.GetProperty<QueryData>(segments.First()); // "CreationDate" Property
if(queryProperty == null) continue;
object value = _reflection.Conversion.ConvertTo(queryParam.Value, property.PropertyType); // Convert 1440091949 to long
if(value == null) continue;
_reflection.Properties.SetPropertyValue(queryData, property, value); // Set queryData.CreationDate = 1440091949
if(segments.Length < 2) continue;
PropertyInfo mapProperty = _reflection.Properties.GetPropertiesWithAttribute<QueryData, OperationMapAttribute>().FirstOrDefault(); // Identify Property annotated with [OperationMap]
if(mapProperty == null) continue;
Dictionary<string, string> operationMap = _reflection.Properties.GetPropertyValue(queryData, mapProperty) as Dictionary<string, string>(); // Get dictionary from Map property
if(operationMap == null) continue;
if(!operationMap.ContainsKey(property.Name))
operationMap.Add(property.Name, segments.Last()); // "creationDate" -> "lt"
else
operationMap[property.Name] = segments.Last();
_reflection.Properties.SetPropertyValue(queryData, mapProperty, operationMap); // Set Map property of QueryData to the updated dictionary
}
return queryData;
}
I know there exists an automatic mapping provided by ASP.NET Web Api if one decides to use the [FromUri] attribute, but that would work if I had simple query parameters such as creationDate=1440091949, but will not work if I send a query parameter such as creationDate.lt=1440091949.
Is there something built in, in the Web APi engine to handle these types of query parameters? I have seen them on a lot of web services, so they are pretty common for ordering or doing complex queries.