I'm new in OData
. I created simple OData
project. I have controller. It returns products from DB. To increase performance I'm loading only properties (using System.Linq.Dynamic
) when client request contains select row. Here is my controller:
MainContext Context = null;
public IHttpActionResult Get(ODataQueryOptions<Product> queryOptions, CancellationToken cancellationToken)
{
if (Context == null)
Context = MainContext.CreateInstance();
var entities = Context.GetEntities<Product>();
if (queryOptions.RawValues?.Select != null)
{
var selectedProperties = GetSelectedPropertiesFromSelectRaw(queryOptions.RawValues.Select, typeof(Product));
if (selectedProperties.Any())
{
var splittedProperties = string.Join(",", selectedProperties);
var onlyProperties = entities.Select($"new({splittedProperties})");
var dynamicInstances = GetInstancesDynamicly(onlyProperties, onlyProperties.ElementType, cancellationToken);
return Ok(dynamicInstances);
}
}
var entityInstances = CreateInstances(entities, cancellationToken);
return Ok(entityInstances);
}
List<string> GetSelectedPropertiesFromSelectRaw(string selectRaw, Type entityType)
{
var properties = selectRaw.Split(',').Select(s => s.Trim())
.Where(s => s != "" && entityType.GetProperties().Any(p => p.Name == s));
return properties.ToList();
}
private List<Product> CreateInstances(IQueryable<Product> entities, CancellationToken cancellationToken)
{
var list = new List<Product>();
foreach (Product entity in entities)
{
cancellationToken.ThrowIfCancellationRequested();
list.Add(entity);
}
return list;
}
IList GetInstancesDynamicly<T>(IQueryable entities, T type, CancellationToken cancellationToken) where T : Type
{
Type genericListType = typeof(List<>).MakeGenericType(type);
var list = (IList)Activator.CreateInstance(genericListType);
foreach (var entity in entities)
{
cancellationToken.ThrowIfCancellationRequested();
list.Add(entity);
}
return list;
}
When I request https://localhost:44326/Products it returns products:
But when I request https://localhost:44326/Products?$select=Id,Name
it is not returning anything. I putted breakpoint before return Ok(dynamicInstances);
dynamicInstances
contains items:
EDIT: My OData
model registration:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: builder.GetEdmModel());
}
Why it isn't loading anything ?