Freigeben über


Erstellen eines OData v3-Endpunkts mit Web-API 2

von Mike Wasson

Abgeschlossenes Projekt herunterladen

Das Open Data Protocol (OData) ist ein Datenzugriffsprotokoll für das Web. OData bietet eine einheitliche Möglichkeit zum Strukturieren von Daten, Abfragen und Bearbeiten des Datasets über CRUD-Vorgänge (Erstellen, Lesen, Aktualisieren und Löschen). OData unterstützt sowohl AtomPub (XML) als auch JSON-Formate. OData definiert auch eine Möglichkeit, Metadaten zu den Daten verfügbar zu machen. Clients können die Metadaten verwenden, um die Typinformationen und Beziehungen für die Datenmenge zu ermitteln.

ASP.NET Web-API erleichtert das Erstellen eines OData-Endpunkts für einen Datensatz. Sie können genau steuern, welche OData-Vorgänge der Endpunkt unterstützt. Sie können mehrere OData-Endpunkte zusammen mit Nicht-OData-Endpunkten hosten. Sie haben voll kontrolle über Ihr Datenmodell, Ihre Back-End-Geschäftslogik und datenebene.

Im Lernprogramm verwendete Softwareversionen

Die Web-API-OData-Unterstützung wurde in ASP.NET- und Webtools 2012.2 Update hinzugefügt. Dieses Lernprogramm verwendet jedoch Gerüste, die in Visual Studio 2013 hinzugefügt wurden.

In diesem Lernprogramm erstellen Sie einen einfachen OData-Endpunkt, den Clients abfragen können. Sie erstellen auch einen C#-Client für den Endpunkt. Nachdem Sie dieses Lernprogramm abgeschlossen haben, zeigen die nächsten Lernprogramme, wie Sie weitere Funktionen hinzufügen, einschließlich Entitätsbeziehungen, Aktionen und $expand/$select.

Erstellen des Visual Studio-Projekts

In diesem Lernprogramm erstellen Sie einen OData-Endpunkt, der grundlegende CRUD-Vorgänge unterstützt. Der Endpunkt macht eine einzelne Ressource verfügbar, eine Liste von Produkten. In späteren Lernprogrammen werden weitere Features hinzugefügt.

Starten Sie Visual Studio, und wählen Sie auf der Startseite " Neues Projekt" aus. Oder wählen Sie im Menü "Datei " die Option "Neu " und dann "Projekt" aus.

Wählen Sie im Bereich "Vorlagen " die Option "Installierte Vorlagen " aus, und erweitern Sie den Knoten "Visual C#". Wählen Sie unter Visual C#"Web" aus. Wählen Sie die Vorlage ASP.NET Webanwendung aus.

Screenshot des neuen Projektfensters mit dem Pfad zum Vorlagenbereich und Anzeigen hervorgehobener Wegbeschreibungen zum Auswählen der Option

Wählen Sie im Dialogfeld "Neues ASP.NET Projekt " die Vorlage "Leer " aus. Überprüfen Sie unter "Ordner und Kernverweise hinzufügen für..." die Web-API. Klicke auf OK.

Screenshot des Dialogfelds

Hinzufügen eines Entitätsmodells

Ein Modell ist ein Objekt, das die Daten in Ihrer Anwendung darstellt. Für dieses Lernprogramm benötigen wir ein Modell, das ein Produkt darstellt. Das Modell entspricht unserem OData-Entitätstyp.

Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner "Modelle". Wählen Sie im Kontextmenü "Hinzufügen" und dann "Klasse" aus.

Screenshot des Dialogfelds

Nennen Sie im Dialogfeld " Neues Element hinzufügen " die Klasse "Product".

Screenshot des Fensters

Hinweis

Modellklassen werden in der Konvention im Ordner "Modelle" platziert. Sie müssen diese Konvention nicht in Ihren eigenen Projekten befolgen, aber wir verwenden es für dieses Lernprogramm.

Fügen Sie in der datei Product.cs die folgende Klassendefinition hinzu:

public class Product
{
    public int ID { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string Category { get; set; }
}

Die ID-Eigenschaft wird der Entitätsschlüssel sein. Clients können Produkte nach ID abfragen. Dieses Feld wäre auch der Primärschlüssel in der Back-End-Datenbank.

Erstellen Sie das Projekt jetzt. Im nächsten Schritt verwenden wir ein Visual Studio-Gerüst, das Spiegelung verwendet, um den Produkttyp zu finden.

Hinzufügen eines OData-Controllers

Ein Controller ist eine Klasse, die HTTP-Anforderungen verarbeitet. Sie definieren einen separaten Controller für jeden Entitätssatz im OData-Dienst. In diesem Lernprogramm erstellen wir einen einzelnen Controller.

Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner "Controller". Wählen Sie "Hinzufügen" und dann " Controller" aus.

Screenshot des Lösungs-Explorer-Fensters, in dem die Controller-Option hervorgehoben wird, die dann die Menüs zum Hinzufügen eines OData-Controllers anzeigt.

Wählen Sie im Dialogfeld " Gerüst hinzufügen " die Option "Web-API 2 OData Controller mit Aktionen mit Entity Framework" aus.

Screenshot des Bildschirms

Nennen Sie im Dialogfeld " Controller hinzufügen " den Controller "ProductsController". Aktivieren Sie das Kontrollkästchen "Asynchrone Controlleraktionen verwenden". Wählen Sie in der Dropdownliste "Modell " die Produktklasse aus.

Screenshot des Dialogfelds

Klicken Sie auf die Schaltfläche "Neuer Datenkontext". Behalten Sie den Standardnamen für den Datentyp des Datenkontexts bei, und klicken Sie auf "Hinzufügen".

Screenshot des neuen Datenkontextfensters mit einem Feld für

Klicken Sie im Dialogfeld "Controller hinzufügen" auf "Hinzufügen", um den Controller hinzuzufügen.

Screenshot des Dialogfelds

Hinweis: Wenn eine Fehlermeldung mit der Meldung "Fehler beim Abrufen des Typs" erscheint, stellen Sie sicher, dass Sie das Visual Studio-Projekt erstellt haben, nachdem Sie die Product-Klasse hinzugefügt haben. Das Gerüst verwendet Spiegelung, um die Klasse zu finden.

Screenshot von Microsoft Visual Studio mit einem roten kreisförmigen

Das Gerüst fügt dem Projekt zwei Codedateien hinzu:

  • Products.cs definiert den Web-API-Controller, der den OData-Endpunkt implementiert.
  • ProductServiceContext.cs stellt Methoden zum Abfragen der zugrunde liegenden Datenbank mithilfe von Entity Framework bereit.

Screenshot des Projektfensters, das das Produkt-Service-Menü zeigt und die beiden neu hinzugefügten Dateien unter Controllern und Modellen einkreist.

EDM und Route hinzufügen

Erweitern Sie im Projektmappen-Explorer den Ordner App_Start, und öffnen Sie die Datei mit dem Namen WebApiConfig.cs. Diese Klasse enthält Konfigurationscode für die Web-API. Ersetzen Sie diesen Code durch Folgendes:

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());
        }
    }
}

Dieser Code mach zwei Dinge:

  • Erstellt ein Entity Data Model (EDM) für den OData-Endpunkt.
  • Fügt eine Route für den Endpunkt hinzu.

Ein EDM ist ein abstraktes Modell der Daten. Das EDM wird verwendet, um das Metadatendokument zu erstellen und die URIs für den Dienst zu definieren. ODataConventionModelBuilder erstellt einen EDM mithilfe einer Reihe von Standardbenennungskonventionen EDM. Für diesen Ansatz ist der geringste Code erforderlich. Wenn Sie mehr Kontrolle über EDM wünschen, können Sie die ODataModelBuilder-Klasse verwenden, um das EDM zu erstellen, indem Sie Eigenschaften, Schlüssel und Navigationseigenschaften explizit hinzufügen.

Die EntitySet-Methode fügt dem EDM eine Entität hinzu:

modelBuilder.EntitySet<Product>("Products");

Die Zeichenfolge "Products" definiert den Namen des Entitätssatzes. Der Name des Controllers muss mit dem Namen des Entitätssatzes übereinstimmen. In diesem Lernprogramm heißt der Entitätssatz "Products", und der Controller wird benannt ProductsController. Wenn Sie den Entitätssatz "ProductSet" benannt haben, nennen Sie den Controller ProductSetController. Beachten Sie, dass ein Endpunkt mehrere Entitätssätze aufweisen kann. Rufen Sie EntitySet<T> für jeden Entitätssatz auf, und definieren Sie dann einen entsprechenden Controller.

Die MapODataRoute-Methode fügt eine Route für den OData-Endpunkt hinzu.

config.Routes.MapODataRoute("ODataRoute", "odata", model);

Der erste Parameter ist ein benutzerfreundlicher Name für die Route. Kunden Ihres Dienstes sehen diesen Namen nicht. Der zweite Parameter ist das URI-Präfix für den Endpunkt. Aufgrund dieses Codes ist der URI für den Entitätssatz "Products" http:// hostname/odata/Products. Ihre Anwendung kann mehrere OData-Endpunkte haben. Rufen Sie für jeden Endpunkt MapODataRoute auf, und geben Sie einen eindeutigen Routennamen und ein eindeutiges URI-Präfix an.

Datenbank initialisieren (Optional)

In diesem Schritt verwenden Sie Entity Framework, um die Datenbank mit einigen Testdaten zu seedieren. Dieser Schritt ist optional, ermöglicht es Ihnen jedoch, Ihren OData-Endpunkt sofort auszuprobieren.

Wählen Sie im Menü "Extras " die Option "NuGet-Paket-Manager" und dann "Paket-Manager-Konsole" aus. Geben Sie im Paket-Manager-Konsolenfenster den folgenden Befehl ein:

Enable-Migrations

Dadurch wird ein Ordner namens "Migrationen" und eine Codedatei mit dem Namen Configuration.cs hinzugefügt.

Screenshot des Produktdienstmenüs des Projektmappen-Explorers, Umkreisen des neu hinzugefügten Ordners namens Migrationen und Anzeigen der Darin enthaltenen Datei.

Öffnen Sie diese Datei, und fügen Sie der Configuration.Seed Methode den folgenden Code hinzu.

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" },
    });
}

Geben Sie im Paket-Manager-Konsolenfenster die folgenden Befehle ein:

Add-Migration Initial
Update-Database

Diese Befehle generieren Code, der die Datenbank erstellt, und führt diesen Code dann aus.

Erkunden des OData-Endpunkts

In diesem Abschnitt verwenden wir den Fiddler-Webdebuggingproxy , um Anforderungen an den Endpunkt zu senden und die Antwortnachrichten zu untersuchen. Dies hilft Ihnen, die Funktionen eines OData-Endpunkts zu verstehen.

Drücken Sie in Visual Studio F5, um das Debuggen zu starten. Standardmäßig öffnet Visual Studio Ihren Browser auf http://localhost:*port*, wobei port die in den Projekteinstellungen konfigurierte Portnummer ist.

Sie können die Portnummer in den Projekteinstellungen ändern. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie "Eigenschaften" aus. Wählen Sie im Eigenschaftenfenster "Web" aus. Geben Sie die Portnummer unter "Projekt-URL" ein.

Dienstdokument

Das Dienstdokument enthält eine Liste der Entitätssätze für den OData-Endpunkt. Um das Dienstdokument abzurufen, senden Sie eine GET-Anforderung an den Stamm-URI des Diensts.

Geben Sie mithilfe von Fiddler den folgenden URI auf der Registerkarte "Composer " ein: http://localhost:port/odata/, wobei port die Portnummer ist.

Screenshot des Dienstdokumentfensters, in dem die verschiedenen Registerkarten mit ausgewählter Registerkarte

Klicken Sie auf die Schaltfläche "Ausführen ". Fiddler sendet eine HTTP GET-Anforderung an Ihre Anwendung. Die Antwort sollte in der Liste "Websitzungen" angezeigt werden. Wenn alles funktioniert, lautet der Statuscode 200.

Screenshot der Websitzungsliste mit dem H T T P-Protokoll mit der Ergebnisnummer 200 und der U R L-Adresse und dem Host.

Doppelklicken Sie in der Liste "Websitzungen" auf die Antwort, um die Details der Antwortnachricht auf der Registerkarte "Inspektoren" anzuzeigen.

Screenshot der Registerkarte 'Inspektor' der Websitzungsliste mit der Anforderungsheader-Antwort und den XML-Informationen.

Die unformatierte HTTP-Antwortnachricht sollte etwa wie folgt aussehen:

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>

Standardmäßig gibt die Web-API das Dienstdokument im AtomPub-Format zurück. Um JSON anzufordern, fügen Sie der HTTP-Anforderung den folgenden Header hinzu:

Accept: application/json

Screenshot des Websitzungsfensters mit der Antwort von der API im Abschnitt

Jetzt enthält die HTTP-Antwort eine JSON-Nutzlast:

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"
    }
  ]
}

Dienstmetadatendokument

Das Dienstmetadatendokument beschreibt das Datenmodell des Diensts mithilfe einer XML-Sprache, die als Konzeptschemadefinitionssprache (Conceptual Schema Definition Language, CSDL) bezeichnet wird. Das Metadatendokument zeigt die Struktur der Daten im Dienst und kann zum Generieren von Clientcode verwendet werden.

Um das Metadatendokument abzurufen, senden Sie eine GET-Anforderung an http://localhost:port/odata/$metadata. Hier sind die Metadaten für den Endpunkt, der in diesem Lernprogramm gezeigt wird.

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>

Entitätssatz

Um den Entitätssatz "Products" abzurufen, senden Sie eine GET-Anforderung an 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ät

Um ein einzelnes Produkt zu erhalten, senden Sie eine GET-Anforderung an http://localhost:port/odata/Products(1), wobei "1" die Produkt-ID ist.

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"
}

OData-Serialisierungsformate

OData unterstützt mehrere Serialisierungsformate:

  • Atom Pub (XML)
  • JSON "light" (eingeführt in OData v3)
  • JSON "Verbose" (OData v2)

Standardmäßig verwendet die Web-API das AtomPubJSON-Format "light".

Um das AtomPub-Format abzurufen, legen Sie den Accept-Header auf "application/atom+xml" fest. Hier ist ein Beispiel für den Antworttext:

<?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>

Ein offensichtlicher Nachteil des Atom-Formats ist, dass es viel ausführlicher ist als JSON Light. Wenn Sie jedoch über einen Client verfügen, der AtomPub versteht, bevorzugt der Client dieses Format möglicherweise über JSON.

Dies ist die JSON-Light-Version derselben Entität:

{
  "odata.metadata":"http://localhost:60868/odata/$metadata#Products/@Element",
  "ID":1,
  "Name":"Hat",
  "Price":"15.00",
  "Category":"Apparel"
}

Das JSON-Light-Format wurde in Version 3 des OData-Protokolls eingeführt. Aus Gründen der Abwärtskompatibilität kann ein Client das ältere "verbose"-JSON-Format anfordern. Um detaillierte JSON anzufordern, legen Sie den Accept-Header auf application/json;odata=verbose. Hier ist die ausführliche Version:

{
  "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"
  }
}

Dieses Format vermittelt mehr Metadaten im Antworttext, wodurch ein erheblicher Aufwand für eine gesamte Sitzung entstehen kann. Außerdem wird eine Indirektionsebene hinzugefügt, indem das Objekt in eine Eigenschaft mit dem Namen "d" eingebettet wird.

Nächste Schritte