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.