I recently found myself in this situation when I wanted to use Dapper with OData, but I did not want to use Entity Framework for SQLite.
My solution was to create an extension method for ODataQueryOptions, so my controllers would look like this:
public IHttpActionResult GetDevices(ODataQueryOptions<User> queryOptions) { var usersQuery = new UserQuery(page, perPage); var users = usersQuery.Search(queryOptions.WhereClause(), queryOptions.OrderByClause()); return Ok<IEnumerable<User>>(users); }
It looks simple, and it still works for me, so I stick with that. I just had to limit what users can filter as far as odata is concerned p>
protected ODataValidationSettings _validationSettings = new ODataValidationSettings { // These validation settings prevent anything except: (equals, and, or) filter and sorting AllowedFunctions = AllowedFunctions.None, AllowedLogicalOperators = AllowedLogicalOperators.Equal | AllowedLogicalOperators.And | AllowedLogicalOperators.Or | AllowedLogicalOperators.NotEqual, AllowedArithmeticOperators = AllowedArithmeticOperators.None, AllowedQueryOptions = AllowedQueryOptions.Filter | AllowedQueryOptions.OrderBy };
And here is the extension method
public static string WhereClause(this ODataQueryOptions options) { string s = ""; if (options.Filter != null && options.Filter.FilterClause != null) { var node = options.Filter.FilterClause.Expression as BinaryOperatorNode; s = getWhereClause(node); } return s; } private static string getWhereClause(BinaryOperatorNode node) { // PARSE FILTER CLAUSE // Parsing a filter, eg /Users?$filter=Id eq '1' or Id eq '100' var s = ""; if (node.Left is SingleValuePropertyAccessNode && node.Right is ConstantNode) { var property = node.Left as SingleValuePropertyAccessNode ?? node.Right as SingleValuePropertyAccessNode; var constant = node.Left as ConstantNode ?? node.Right as ConstantNode; if (property != null && property.Property != null && constant != null && constant.Value != null) { s += $" {property.Property.Name} {getStringValue(node.OperatorKind)} '{constant.Value}' "; } } else { if (node.Left is BinaryOperatorNode) s += getWhereClause(node.Left as BinaryOperatorNode); if (node.Right is BinaryOperatorNode) { s += $" {getStringValue(node.OperatorKind)} "; s += getWhereClause(node.Right as BinaryOperatorNode); } } return s; }
jokab source share