WebAPI supports OData, so API consumer can specify fields that he requires, and it works fine. But is there a way to use DTO objects and projections in WebAPI?
For example I have
public class WebSite
{
public string Url {get;set;}
public string Author {get;set;}
public string Technology {get;set;}
public DateTime CreatedAt {get;set;}
// 20 more different properties
}
And i also have DTO object:
public class WebSiteDTO
{
public string Url {get;set;}
public string Author {get;set;}
public bool IsDotNet {get;set;} // it should be set during mapping as webSite.Technology == ".Net";
public bool IsTrendThing {get;set;} // should be set as webSite.Technology == ".Net" and webSite.CreatedAt > new DateTime(2014,0,0);
}
And some typical WebAPI endpoint that supports OData:
[HttpGet]
[Route("Test")]
public IQueryable Test(ODataQueryOptions<WebSiteDTO> options)
{
var efDbContext = new MyDBContext();
var query = efDbContext.WebSites;
var odataQuery = options.ApplyTo(query, settings);
return odataQuery;
}
In that case WebSite object will be returned. But how to return WebSiteDTO object and still have OData support? Is it possible to do mapping by property and not by class itself? Like if Url was requested via OData, then we will load just Url from DB and map it to Url property in DTO object? I may have complicated cases when properties in DTO must be set by some custom logic like in IsDotNet sample, or it may depend on more than one property.
I suppose i can write some custom middleware that will execute original query with fields specified by OData, and then save it in Dictionary and then do something like that:
MyMapper.Map<WebSite, WebSiteDTO>().
MapProperty(o, dict => o.Url = (string)dict["Url"]).
MapProperty(o, dict => o.IsDotNet = (string)dict["Technology"] == ".Net").
MapProperty(o, dict => o.IsTrendThing = (string)dict["Technology"] == ".Net" && (DateTime)dict["CreatedAt"] > new DateTime(2014,0,0));
But it looks ugly and in that case somehow i need to specify that if IsTrendThing property was requested in OData request, then I also need to load Technology and CreatedAt fields from WebSite object, that makes things complicated.
Is there something that can be usefull in my case? Maybe someone can help me with correct direction?
Automapper has projections mapping but it doesn't work in my scenario, as it requires specific type, and in my case original type can be different because of fields specified by OData.
There is another similar question but it was about pure DTO, and in my case i want to support 'select\expand' operators from OData as my objects can have a lot of properties. And i want to not load them from DB if they weren't requested.