Buongiorno,
ho creato una WebApi che utilizza EF su DB SQLServer. Per l'API mi è stato chiesto di utilizzare OData vers 4.0.
Ho dovuto espandere il model di EF per le relazioni tra le entità, in quanto non presenti su DB, nel seguente modo:
- ho l’entità Orologi e l’entità Interfacce (1 Interfaccia - N Orologi)
- Ho esteso il model nel seguente modo (altro file, non ho modificato il model generato da EF):
codice:
public partial class Orologi
{
/*
OData vuole questo campo, non modificato manualmente il model creato da EF (update from model…) creo una proprietà che mappa l’IDOrologio presente su DB mettendoci il decorator [Key]
*/
[Key]
public int ID
{
get { return this.IDOrologio; }
set { this.IDOrologio = value; }
}
public Interfaccia
{
get
{
using (EF.DBOrologiContainer db = new EF.DBOrologiContainer())
{
return db.Interfacce.Where(x => x.ID == this.IDInterfaccia).FirstOrDefault();
}
}
set { throw new NotImplementedException(); }
}
- Ho creato un nuovo controller usando OData 4 scaffolding, quindi controller con OData 4 su entità del model EF.
Ho ora nel codice i metodi crud.
Il metodo GET, che ritorna un IQueryable, è semplice, applica la query odata che viene passata su querystring nel seguente modo:
codice:
[EnableQuery]
public IQueryable<Orologi> GetOrologi(ODataQueryOptions<Orologi> queryOptions)
{
return db.Orologi;
}
- Su global.asax, oltre al register standard WebApi, in cui si settano le regole di routing etc, ho aggiunto anche un register custom per le regole di OData:
Global.asax:
codice:
[…]
GlobalConfiguration.Configure(config =>
{
ODataConfig.Register(config); //this has to be before WebApi
WebApiConfig.Register(config);
});
[…]
ODataConfig:
codice:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes(); //This has to be called before the following OData mapping, so also before WebApi mapping
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Orologi>("Orologi");
config.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
}
Bene arriviamo all’errore…
Da postman, facendo il GET semplice, tutto funziona:
http://localhost:51432/odata/Orologi
Ho la lista degli orologi con le proprietà di ‘primo livello’, quindi non c’è Interfaccia. Da standard OData, per navigare nelle ‘navigation properties’ bisogna usare il comando $expand:
http://localhost:51432/odata/Orologi?$expand=Interfaccia
Qui mi viene tornato il seguente errore:
[…]
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; odata.metadata=minimal'.",
[…]
The specified type member 'Interfaccia' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.",
[…]
La cosa strana è però la seguente: se faccio un get di singolo elemento il comando $expand funziona correttamente:
http://localhost:51432/odata/Orologi(2)?$expand=Interfaccia
Mi sto perdendo nei troppi risultati di stackoverflow, tutti che sembrano più o meno tentativi ma che non mi hanno dato successo.
Voi avete qualche idea sul perché di quell’errore?
grazie.