My question is very similar to this one: How do I map an OData query against a DTO to an EF entity? I have a simple setup to test the ASP.NET Web API OData V4 $filter functi
I found a solution without using AutoMapper.
The ProductsController now looks like this:
public class ProductsController : ApiController
{
public IEnumerable Get(ODataQueryOptions q)
{
IQueryable products = this._products.AsQueryable();
IEdmModel model = GetModel();
IEdmType type = model.FindDeclaredType("TestAPI.Models.Product");
IEdmNavigationSource source = model.FindDeclaredEntitySet("Products");
ODataQueryOptionParser parser = new ODataQueryOptionParser(model, type, source, new Dictionary { { "$filter", q.Filter.RawValue } });
ODataQueryContext context = new ODataQueryContext(model, typeof(Product), q.Context.Path);
FilterQueryOption filter = new FilterQueryOption(q.Filter.RawValue, context, parser);
if (filter != null) products = filter.ApplyTo(products, new ODataQuerySettings()) as IQueryable;
return products.Select(p => new ProductDTO(p));
}
}
The WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
…
IEdmModel model = GetModel();
config.MapODataServiceRoute("*", "*", model);
}
private static IEdmModel GetModel()
{
ODataModelBuilder builder = new ODataConventionModelBuilder();
EntitySetConfiguration product = builder.EntitySet("Products");
product.EntityType.Name = "Product";
product.EntityType.Namespace = "TestAPI.Models";
product.EntityType.Property(p => p.Name).Name = "DisplayName";
product.EntityType.Property(p => p.Level).Name = "DisplayLevel";
return builder.GetEdmModel();
}
}