Overview
OData
Integrazione OData nel framework per route metadata-driven, con fallback controllato su provider alternativi. Supporto completo read + CRUD + $expand + $count=true wrapper.
Scope
- Uso di endpoint OData come sorgente dati di
wuic-data-source. - Allineamento con metadata tabella/colonna per rendering UI e comportamento runtime.
- Relazione con flusso di scaffolding iniziale e bootstrap progetto.
- Navigation properties auto-generate da colonne
lookupByIDper abilitare$expandnativo.
Esempi
- Pattern 3c — OData Cities grid (read + CRUD + `$expand` + lookup puro-OData) — esempio completo con
$top/$skip/$filter/$orderby/$expand/$count=truecontro/odata/Citiese/odata/Stateprovinces.
Riferimenti Metadata
- Il routing e la configurazione base restano guidati dai metadati (
md_route_name, colonne, filtri, sort, paging). - In
md_props_bagpuoi forzare il provider tramiteendpoint(esempio:{"endpoint":{"type":"odata","uri":"/odata/Orders"}}). - Anche le colonne lookup possono puntare a un endpoint OData custom via
mc_props_bag.lookup.endpoint(vedi Widget Lookup). - Il datasource continua a usare
filterInfo,sortInfo,pageInfo; lato provider OData avviene la traduzione in query OData. - Per i dettagli metadata trasversali vedi Metadata.
Navigation properties auto-generate (lookupByID → $expand)
Il generatore EF dinamico (MetadataModelGenerator) emette automaticamente una navigation property su ogni colonna con mc_ui_column_type = 'lookupByID' e mc_ui_lookup_entity_name che punta a una route esposta in WebAPI. Convenzione di naming: strip del suffisso Id / ID dal nome FK → nome nav property (es. stateProvinceID → StateProvince). Con EnableLowerCamelCase() attivo l'EDM espone la nav in camelCase (stateProvince).
Effetti pratici:
- il
$metadatacontiene<NavigationProperty Name="stateProvince" Type="...Stateprovinces" />sull'entityCities; GET /odata/Cities?$expand=stateProvincerestituisce ogni riga con l'oggetto correlato inline ({... "stateProvince": { "stateProvinceID": 1, "stateProvinceName": "Alabama" }});- il controller
EntitiesController.Gettraduce$expand=navPropin.Include(navProp)EF Core (LEFT JOIN SQL).
Limiti attuali: solo $expand top-level (niente nested $expand=a($expand=b)); sub-options OData dopo la nav name (es. $expand=stateProvince($select=...)) vengono ignorate — .Include include l'intera entita' correlata.
Response shape e $count=true wrapper
- Default (senza
$count): endpoint ritorna un plain JSON array ([{...}, {...}]) per compatibilita' con i consumer legacy del framework (DataProviderOdataService.select,DataProviderWebserviceService, ecc.) che leggonoresponse as any[]. - Opt-in OData v4 (
$count=truenella query): endpoint ritorna il wrapper standard{ "value": [...], "@odata.count": N }doveNe' il totale calcolato dopo$filter/$orderbyma prima di$skip/$top. Usare quando serve il totale paginato (es. pager UI).
CRUD completo via EntitiesController
L'endpoint OData generico espone l'intera suite RESTful su /odata/{EntitySet}:
GET /odata/{EntitySet}— list con$top/$skip/$filter/$orderby/$select/$expand/$count=true.POST /odata/{EntitySet}— insert, body JSON con le colonne (le colonnenullnel payload vengono skippate cosi' SQL applica ilDEFAULTlato DB, supportando PK IDENTITY/SEQUENCE/GUID automaticamente e colonne con default temporali/audit).PATCH /odata/{EntitySet}({key})— update parziale, body JSON con subset colonne; la PK in path.DELETE /odata/{EntitySet}({key})— delete per chiave singola.
Gating lato metadata (riga _metadati__tabelle):
mdexposeinwebapi = 1(obbligatorio per qualsiasi CUD, altrimenti 403).mdserviceenableinsert,mdserviceenableedit,mdserviceenabledelete= 1 per le rispettive operazioni.- Vedi anche tab metadata "Servizio web" nel metadata-editor.
Metadati Tab "Servizio web" (OData/API)
Nel metadata editor tabella, il tab Servizio web governa l'esposizione API e i gate operativi lato servizio.
md_expose_in_webapi: espone la route nei servizi Web API/OData.md_service_apply_default_filter: applica anche lato servizio ilmd_default_filter.md_service_enable_delete: abilita delete da endpoint servizio.md_service_enable_edit: abilita update/edit da endpoint servizio.md_service_enable_insert: abilita insert da endpoint servizio.md_service_enable_detail: abilita endpoint dettaglio record.md_service_enable_clone: abilita clone record lato servizio.md_service_enable_logging: abilita logging operazioni lato servizio.md_service_page_size: page size lato servizio (Pagesizenel tab UI).
Snippet inline consigliato:
md_expose_in_webapi=true,md_service_enable_insert=true,md_service_enable_edit=true,md_service_enable_delete=true,md_service_page_size=100.
Nota pratica:
md_pagesizeregola il paging UI standard;md_service_page_sizeregola il paging lato endpoint servizio.- Per OData conviene tenere allineati i flag servizio con le reali capability del backend (read-only vs read/write).
Riferimenti Scaffolding
- Il bootstrap (
firstRun) prepara contesto applicativo e connessioni iniziali; dopo scaffolding puoi agganciare route a endpoint OData. - Nel setup iniziale conviene validare subito route, metadati tabella/colonne e mappature minime per evitare mismatch OData/metadata.
- Riferimento operativo: Scaffolding iniziale.
Flusso Operativo Consigliato
1. Definisci/valida route metadata e colonne minime.
2. Configura provider endpoint OData in md_props_bag.endpoint.
3. Verifica lettura lista con filtro/sort/paging dalla UI.
4. Se usi auth OData, allinea le chiavi appsettings (enableODATAAuthentication e policy correlate).
Note pratiche
- OData e metadata non sono alternativi: il metadata resta la sorgente di comportamento UI, OData la sorgente dati.
- In caso di differenze schema, aggiorna prima metadati colonna (
mc_*) e poi rifinisci endpoint/query OData.