Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
di Mike Wasson
Scaricare il progetto completato
Open Data Protocol (OData) è un protocollo di accesso ai dati per il Web. OData offre un modo uniforme per strutturare i dati, eseguire query sui dati e modificare il set di dati tramite operazioni CRUD (creazione, lettura, aggiornamento ed eliminazione). OData supporta sia i formati AtomPub (XML) che JSON. OData definisce anche un modo per esporre i metadati sui dati. I client possono usare i metadati per individuare le informazioni sul tipo e le relazioni per il set di dati.
ASP.NET'API Web semplifica la creazione di un endpoint OData per un set di dati. È possibile controllare esattamente le operazioni OData supportate dall'endpoint. È possibile ospitare più endpoint OData, insieme a endpoint non OData. Si ha il controllo completo sul modello di dati, sulla logica di business back-end e sul livello dati.
Versioni software usate nell'esercitazione
- Visual Studio 2013
- Web API 2
- OData versione 3
- Entity Framework 6
- Fiddler Web Debugging Proxy (facoltativo)
Il supporto OData dell'API Web è stato aggiunto in ASP.NET e nell'aggiornamento degli strumenti Web 2012.2. Tuttavia, questa esercitazione usa lo scaffolding aggiunto in Visual Studio 2013.
In questa esercitazione si creerà un semplice endpoint OData su cui i client possono eseguire query. Si creerà anche un client C# per l'endpoint. Dopo aver completato questa esercitazione, il set successivo di esercitazioni illustra come aggiungere altre funzionalità, tra cui relazioni di entità, azioni e $expand/$select.
- Creare il progetto di Visual Studio
- Aggiungere un modello di entità
- Aggiungere un controller OData
- Aggiungere EDM e Route
- Inizializzare il database (facoltativo)
- Esplorazione dell'endpoint OData
- Formati di serializzazione OData
Creare il progetto di Visual Studio
In questa esercitazione si creerà un endpoint OData che supporta operazioni CRUD di base. L'endpoint esporrà una singola risorsa, un elenco di prodotti. Le esercitazioni successive aggiungeranno altre funzionalità.
Avviare Visual Studio e selezionare Nuovo progetto nella pagina Iniziale. In alternativa, scegliere Nuovo dal menu File e quindi Progetto.
Nel riquadro Modelli selezionare Modelli installati ed espandere il nodo Visual C#. In Visual C# selezionare Web. Selezionare il modello di applicazione Web di ASP.NET.
Nella finestra di dialogo Nuovo progetto ASP.NET selezionare il modello Vuoto . In "Aggiungi cartelle e riferimenti di base per...", selezionare API Web. Fare clic su OK.
Aggiungere un modello di entità
Un modello è un oggetto che rappresenta i dati nell'applicazione. Per questa esercitazione è necessario un modello che rappresenta un prodotto. Il modello corrisponde al tipo di entità OData.
In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Modelli. Dal menu di scelta rapida selezionare Aggiungi e quindi selezionare Classe.
Nella finestra di dialogo Aggiungi nuovo elemento assegnare alla classe il nome "Product".
Annotazioni
Per convenzione, le classi modello vengono inserite nella cartella Models. Non è necessario seguire questa convenzione nei propri progetti, ma verrà usata per questa esercitazione.
Nel file Product.cs aggiungere la definizione di classe seguente:
public class Product
{
public int ID { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
La proprietà ID sarà la chiave di entità. I client possono eseguire query sui prodotti in base all'ID. Questo campo sarà anche la chiave primaria nel database back-end.
Compilare ora il progetto. Nella fase successiva useremo lo scaffolding di Visual Studio che utilizza la reflection per trovare il tipo di Prodotto.
Aggiungere un controller OData
Un controller è una classe che gestisce le richieste HTTP. Si definisce un controller separato per ogni set di entità nel servizio OData. In questa esercitazione verrà creato un singolo controller.
In Esplora soluzioni fare clic con il pulsante destro del mouse sulla cartella Controllers. Selezionare Aggiungi e quindi Controller.
Nella finestra di dialogo Aggiungi struttura, selezionare "Web API 2 OData Controller con azioni, utilizzando Entity Framework".
Nella finestra di dialogo Aggiungi controller assegnare al controller il nome "ProductsController". Selezionare la casella di controllo "Usa azioni del controller asincrono". Nell'elenco a discesa Modello selezionare la classe Product.
Fare clic sul pulsante Nuovo contesto dati. Lasciare il nome predefinito per il tipo di contesto dati e fare clic su Aggiungi.
Fare clic su Aggiungi nella finestra di dialogo Aggiungi controller per aggiungere il controller.
Nota: se viene visualizzato un messaggio di errore che indica "Si è verificato un errore durante il recupero del tipo...", assicurarsi di generare il progetto di Visual Studio dopo aver aggiunto la classe Product. Lo scaffolding utilizza la riflessione per trovare la classe.
Lo scaffolding aggiunge due file di codice al progetto:
- Products.cs definisce il controller API Web che implementa l'endpoint OData.
- ProductServiceContext.cs fornisce metodi per eseguire query sul database sottostante usando Entity Framework.
Aggiungere EDM e Route
In Esplora soluzioni espandere la cartella App_Start e aprire il file denominato WebApiConfig.cs. Questa classe contiene il codice di configurazione per l'API Web. Sostituire questo codice con il codice seguente:
using ProductService.Models;
using System.Web.Http;
using System.Web.Http.OData.Builder;
namespace ProductService
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
config.Routes.MapODataRoute("odata", "odata", builder.GetEdmModel());
}
}
}
Questo codice fa due cose:
- Crea un entity data model (EDM) per l'endpoint OData.
- Aggiunge una route per l'endpoint.
Un modello EDM è un modello astratto dei dati. L'EDM viene usato per creare il documento di metadati e definire gli URI per il servizio. ODataConventionModelBuilder crea un EDM usando un set di convenzioni di denominazione predefinite EDM. Questo approccio richiede il minor codice. Se si vuole un maggiore controllo sull'EDM, è possibile usare la classe ODataModelBuilder per creare EDM aggiungendo in modo esplicito proprietà, chiavi e proprietà di spostamento.
Il metodo EntitySet aggiunge un set di entità a EDM:
modelBuilder.EntitySet<Product>("Products");
La stringa "Products" definisce il nome del set di entità. Il nome del controller deve corrispondere al nome del set di entità. In questa esercitazione il set di entità è denominato "Products" e il controller è denominato ProductsController. Se denomini il set di entità "ProductSet", denomineresti il controller ProductSetController. Si noti che un endpoint può avere più set di entità. Chiamare EntitySet<T> per ogni set di entità e quindi definire un controller corrispondente.
Il metodo MapODataRoute aggiunge una route per l'endpoint OData.
config.Routes.MapODataRoute("ODataRoute", "odata", model);
Il primo parametro è un nome descrittivo per il percorso. I clienti del tuo servizio non visualizzano questo nome. Il secondo parametro è il prefisso URI per l'endpoint. Dato questo codice, l'URI per il set di entità Products è http:// hostname/odata/Products. L'applicazione può avere più di un endpoint OData. Per ogni endpoint, chiamare MapODataRoute e specificare un nome di route univoco e un prefisso URI univoco.
Inizializzare il database (facoltativo)
In questo passaggio si userà Entity Framework per eseguire il seeding del database con alcuni dati di test. Questo passaggio è facoltativo, ma consente di testare immediatamente l'endpoint OData.
Dal menu Strumenti selezionare Gestione pacchetti NuGet e quindi console di Gestione pacchetti. Nella finestra Console di Gestione pacchetti immettere il comando seguente:
Enable-Migrations
Viene aggiunta una cartella denominata Migrations e un file di codice denominato Configuration.cs.
Aprire questo file e aggiungere il codice seguente al Configuration.Seed metodo .
protected override void Seed(ProductService.Models.ProductServiceContext context)
{
// New code
context.Products.AddOrUpdate(new Product[] {
new Product() { ID = 1, Name = "Hat", Price = 15, Category = "Apparel" },
new Product() { ID = 2, Name = "Socks", Price = 5, Category = "Apparel" },
new Product() { ID = 3, Name = "Scarf", Price = 12, Category = "Apparel" },
new Product() { ID = 4, Name = "Yo-yo", Price = 4.95M, Category = "Toys" },
new Product() { ID = 5, Name = "Puzzle", Price = 8, Category = "Toys" },
});
}
Nella finestra console di Gestione pacchetti immettere i comandi seguenti:
Add-Migration Initial
Update-Database
Questi comandi generano codice che crea il database e quindi esegue tale codice.
Esplorazione dell'endpoint OData
In questa sezione utilizzeremo il Fiddler Web Debugging Proxy per inviare richieste all'endpoint ed esaminare i messaggi di risposta. Ciò consentirà di comprendere le funzionalità di un endpoint OData.
In Visual Studio premere F5 per avviare il debug. Per impostazione predefinita, Visual Studio apre il tuo browser a http://localhost:*port*, dove porta è il numero della porta configurata nelle impostazioni del progetto.
È possibile modificare il numero di porta nelle impostazioni del progetto. In Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto e scegliere Proprietà. Nella finestra delle proprietà selezionare Web. Immettere il numero di porta nella sezione Url progetto.
Documento di servizio
Il documento di servizio contiene un elenco dei set di entità per l'endpoint OData. Per ottenere il documento di servizio, inviare una richiesta GET all'URI radice del servizio.
Usando Fiddler, immettere l'URI seguente nella scheda Composer: http://localhost:port/odata/, dove porta si riferisce al numero di porta.
Fare clic sul pulsante Esegui . Fiddler invia una richiesta HTTP GET all'applicazione. La risposta dovrebbe essere visualizzata nell'elenco Sessioni Web. Se tutto funziona, il codice di stato sarà 200.
Fare doppio clic sulla risposta nell'elenco Sessioni Web per visualizzare i dettagli del messaggio di risposta nella scheda Inspectors .Double-click the response in the Web Sessions list to see the details of the response message in the Inspectors tab.
Il messaggio di risposta HTTP non elaborato dovrebbe essere simile al seguente:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/atomsvc+xml; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
DataServiceVersion: 3.0
Date: Mon, 23 Sep 2013 17:51:01 GMT
Content-Length: 364
<?xml version="1.0" encoding="utf-8"?>
<service xml:base="http://localhost:60868/odata"
xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
<workspace>
<atom:title type="text">Default</atom:title>
<collection href="Products">
<atom:title type="text">Products</atom:title>
</collection>
</workspace>
</service></pre>
Per impostazione predefinita, l'API Web restituisce il documento del servizio in formato AtomPub. Per richiedere JSON, aggiungere l'intestazione seguente alla richiesta HTTP:
Accept: application/json
La risposta HTTP contiene ora un payload JSON:
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
DataServiceVersion: 3.0
Date: Mon, 23 Sep 2013 22:59:28 GMT
Content-Length: 136
{
"odata.metadata":"http://localhost:60868/odata/$metadata","value":[
{
"name":"Products","url":"Products"
}
]
}
Documento dei metadati del servizio
Il documento dei metadati del servizio descrive il modello di dati del servizio, usando un linguaggio XML denominato CsDL (Conceptual Schema Definition Language). Il documento di metadati mostra la struttura dei dati nel servizio e può essere usato per generare codice client.
Per ottenere il documento di metadati, inviare una richiesta GET a http://localhost:port/odata/$metadata. Ecco i metadati per l'endpoint illustrato in questa esercitazione.
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/xml; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
DataServiceVersion: 3.0
Date: Mon, 23 Sep 2013 23:05:52 GMT
Content-Length: 1086
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
<edmx:DataServices m:DataServiceVersion="3.0" m:MaxDataServiceVersion="3.0"
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<Schema Namespace="ProductService.Models" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityType Name="Product">
<Key>
<PropertyRef Name="ID" />
</Key>
<Property Name="ID" Type="Edm.Int32" Nullable="false" />
<Property Name="Name" Type="Edm.String" />
<Property Name="Price" Type="Edm.Decimal" Nullable="false" />
<Property Name="Category" Type="Edm.String" />
</EntityType>
</Schema>
<Schema Namespace="Default" xmlns="http://schemas.microsoft.com/ado/2009/11/edm">
<EntityContainer Name="Container" m:IsDefaultEntityContainer="true">
<EntitySet Name="Products" EntityType="ProductService.Models.Product" />
</EntityContainer>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
Set di entità
Per ottenere il set di entità Products, inviare una richiesta GET a http://localhost:port/odata/Products.
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
DataServiceVersion: 3.0
Date: Mon, 23 Sep 2013 23:01:31 GMT
Content-Length: 459
{
"odata.metadata":"http://localhost:60868/odata/$metadata#Products","value":[
{
"ID":1,"Name":"Hat","Price":"15.00","Category":"Apparel"
},{
"ID":2,"Name":"Socks","Price":"5.00","Category":"Apparel"
},{
"ID":3,"Name":"Scarf","Price":"12.00","Category":"Apparel"
},{
"ID":4,"Name":"Yo-yo","Price":"4.95","Category":"Toys"
},{
"ID":5,"Name":"Puzzle","Price":"8.00","Category":"Toys"
}
]
}
Entità
Per ottenere un singolo prodotto, inviare una richiesta GET a http://localhost:port/odata/Products(1), dove "1" è l'ID prodotto.
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
DataServiceVersion: 3.0
Date: Mon, 23 Sep 2013 23:04:29 GMT
Content-Length: 140
{
"odata.metadata":"http://localhost:60868/odata/$metadata#Products/@Element","ID":1,
"Name":"Hat","Price":"15.00","Category":"Apparel"
}
Formati di serializzazione OData
OData supporta diversi formati di serializzazione:
- Atom Pub (XML)
- JSON "light" (introdotto in OData v3)
- JSON "verbose" (OData v2)
Per impostazione predefinita, l'API Web usa il formato "light" AtomPubJSON.
Per ottenere il formato AtomPub, impostare l'intestazione Accept su "application/atom+xml". Ecco un esempio di corpo della risposta:
<?xml version="1.0" encoding="utf-8"?>
<entry xml:base="http://localhost:60868/odata" xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml">
<id>http://localhost:60868/odata/Products(1)</id>
<category term="ProductService.Models.Product" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<link rel="edit" href="http://localhost:60868/odata/Products(1)" />
<link rel="self" href="http://localhost:60868/odata/Products(1)" />
<title />
<updated>2013-09-23T23:42:11Z</updated>
<author>
<name />
</author>
<content type="application/xml">
<m:properties>
<d:ID m:type="Edm.Int32">1</d:ID>
<d:Name>Hat</d:Name>
<d:Price m:type="Edm.Decimal">15.00</d:Price>
<d:Category>Apparel</d:Category>
</m:properties>
</content>
</entry>
È possibile vedere uno svantaggio ovvio del formato Atom: è molto più verboso rispetto al JSON leggero. Tuttavia, se si dispone di un client che riconosce AtomPub, il client potrebbe preferire tale formato rispetto a JSON.
Ecco la versione light JSON della stessa entità:
{
"odata.metadata":"http://localhost:60868/odata/$metadata#Products/@Element",
"ID":1,
"Name":"Hat",
"Price":"15.00",
"Category":"Apparel"
}
Il formato chiaro JSON è stato introdotto nella versione 3 del protocollo OData. Per garantire la compatibilità con le versioni precedenti, un client può richiedere il formato JSON "dettagliato" precedente. Per richiedere JSON dettagliato, impostare l'intestazione Accept su application/json;odata=verbose. Ecco la versione dettagliata:
{
"d":{
"__metadata":{
"id":"http://localhost:18285/odata/Products(1)",
"uri":"http://localhost:18285/odata/Products(1)",
"type":"ProductService.Models.Product"
},"ID":1,"Name":"Hat","Price":"15.00","Category":"Apparel"
}
}
Questo formato fornisce più metadati nel corpo della risposta, che può comportare un sovraccarico notevole per un'intera sessione. Aggiunge inoltre un livello di indirezione incapsulando l'oggetto in una proprietà denominata "d".