WebAPI поддържа OData, така че потребителят на API може да посочи полета, които изисква, и работи добре. Но има ли начин да се използват DTO обекти и проекции в WebAPI?
Аз например имам
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
}
И аз също имам DTO обект:
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);
}
И някои типични крайни точки на WebAPI, които поддържат 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;
}
В този случай обектът WebSite ще бъде върнат. Но как да върна WebSiteDTO обект и все пак да има поддръжка на OData? Възможно ли е да се направи картографиране по свойство, а не по самия клас? Например, ако Url е поискан чрез OData, тогава ще заредим само Url от DB и ще го съпоставим със свойство Url в DTO обект? Може да имам сложни случаи, когато свойствата в DTO трябва да бъдат зададени от някаква персонализирана логика, като в примера на IsDotNet, или може да зависи от повече от едно свойство.
Предполагам, че мога да напиша някакъв персонализиран междинен софтуер, който ще изпълни оригинална заявка с полета, посочени от OData, и след това да го запиша в речника и след това да направя нещо подобно:
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));
Но изглежда грозно и в този случай по някакъв начин трябва да уточня, че ако свойството IsTrendThing е поискано в заявка за OData, тогава трябва също да заредя полета Technology и CreatedAt от обект WebSite, което прави нещата сложни.
Има ли нещо, което може да бъде полезно в моя случай? Може би някой може да ми помогне с правилната посока?
Automapper има картографиране на проекции, но не работи в моя сценарий, тъй като изисква специфични тип, а в моя случай оригиналният тип може да е различен поради полета, посочени от OData.
Има друг подобен въпрос, но той беше за чисто DTO и в в моя случай искам да поддържам оператори 'select\expand' от OData, тъй като моите обекти могат да имат много свойства. И искам да не ги зареждам от DB, ако не са били поискани.