Tworzenie punktu końcowego OData w wersji 3 przy użyciu internetowego interfejsu API 2

Autor: Mike Wasson

Pobieranie ukończonego projektu

Protokół OData ( Open Data Protocol ) to protokół dostępu do danych dla sieci Web. OData zapewnia jednolity sposób struktury danych, wykonywania zapytań względem danych i manipulowania zestawem danych za pomocą operacji CRUD (tworzenie, odczytywanie, aktualizowanie i usuwanie). OData obsługuje formaty AtomPub (XML) i JSON. OData definiuje również sposób uwidaczniania metadanych dotyczących danych. Klienci mogą używać metadanych do odnajdywania informacji o typie i relacji dla zestawu danych.

ASP.NET internetowy interfejs API ułatwia tworzenie punktu końcowego OData dla zestawu danych. Możesz kontrolować dokładnie, które operacje OData obsługuje punkt końcowy. Wiele punktów końcowych OData można hostować obok punktów końcowych innych niż OData. Masz pełną kontrolę nad modelem danych, logiką biznesową zaplecza i warstwą danych.

Wersje oprogramowania używane w samouczku

Dodano obsługę OData interfejsu API sieci Web w aktualizacji ASP.NET and Web Tools 2012.2. Jednak w tym samouczku użyto szkieletu dodanego w Visual Studio 2013.

W tym samouczku utworzysz prosty punkt końcowy OData, który klienci mogą wykonywać zapytania. Utworzysz również klienta języka C# dla punktu końcowego. Po ukończeniu tego samouczka następny zestaw samouczków pokazuje, jak dodać więcej funkcji, w tym relacje jednostek, akcje i $expand/$select.

Tworzenie projektu programu Visual Studio

W tym samouczku utworzysz punkt końcowy OData, który obsługuje podstawowe operacje CRUD. Punkt końcowy uwidacznia pojedynczy zasób— listę produktów. W kolejnych samouczkach dodasz więcej funkcji.

Uruchom program Visual Studio i wybierz pozycję Nowy projekt na stronie Start. Ewentualnie w menu Plik wybierz pozycję Nowy , a następnie pozycję Projekt.

W okienku Szablony wybierz pozycję Zainstalowane szablony i rozwiń węzeł Visual C#. W obszarze Visual C# wybierz pozycję Sieć Web. Wybierz szablon aplikacji internetowej ASP.NET .

Zrzut ekranu przedstawiający okno nowego projektu z wyświetloną ścieżką do okienka szablonu i wyświetlanie wyróżnionych wskazówek w celu wybrania opcji Aplikacja internetowa S P dot NET.

W oknie dialogowym Nowy projekt ASP.NET wybierz szablon Pusty . W obszarze "Dodaj foldery i odwołania podstawowe dla...", sprawdź internetowy interfejs API. Kliknij przycisk OK.

Zrzut ekranu przedstawiający okno dialogowe projektu S P dot NET z wyświetlonymi polami opcji szablonu i wyróżnioną opcją

Dodawanie modelu jednostki

Model to obiekt reprezentujący dane w aplikacji. Na potrzeby tego samouczka potrzebujemy modelu reprezentującego produkt. Model odpowiada naszemu typowi jednostki OData.

W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder Models. Z menu kontekstowego wybierz pozycję Dodaj , a następnie wybierz pozycję Klasa.

Zrzut ekranu przedstawiający okno dialogowe Eksploratora rozwiązań z wyświetloną listą menu dla każdego zaznaczenia, ponieważ wyróżnia każdą z nich, prowadząc opcję klasy.

W oknie dialogowym Dodawanie nowego elementu nadaj klasie nazwę "Product".

Zrzut ekranu przedstawiający okno

Uwaga

Zgodnie z konwencją klasy modeli są umieszczane w folderze Models. Nie musisz przestrzegać tej konwencji we własnych projektach, ale użyjemy jej do tego samouczka.

W pliku Product.cs dodaj następującą definicję klasy:

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

Właściwość ID będzie kluczem jednostki. Klienci mogą wykonywać zapytania dotyczące produktów według identyfikatora. To pole będzie również kluczem podstawowym w bazie danych zaplecza.

Skompiluj projekt teraz. W następnym kroku użyjemy szkieletu programu Visual Studio, który używa odbicia w celu znalezienia typu produktu.

Dodawanie kontrolera OData

Kontroler to klasa, która obsługuje żądania HTTP. Definiujesz oddzielny kontroler dla każdej jednostki ustawionej w usłudze OData. W tym samouczku utworzymy pojedynczy kontroler.

W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder Controllers. Wybierz pozycję Dodaj , a następnie wybierz pozycję Kontroler.

Zrzut ekranu przedstawiający okno Eksploratora rozwiązań, które wyróżnia opcję kontrolera, a następnie wyświetla menu umożliwiające dodanie kontrolera danych O.

W oknie dialogowym Dodawanie szkieletu wybierz pozycję "Kontroler OData interfejsu API sieci Web 2 z akcjami przy użyciu platformy Entity Framework".

Zrzut ekranu przedstawiający ekran

W oknie dialogowym Dodawanie kontrolera nadaj kontrolerowi nazwę "ProductsController". Zaznacz pole wyboru "Użyj akcji kontrolera asynchronicznego". Z listy rozwijanej Model wybierz klasę Product.

Zrzut ekranu przedstawiający okno dialogowe dodawanie kontrolera, wyświetlanie pól dla nazwy kontrolera, listy rozwijanej klasy modelu i klasy kontekstu danych.

Kliknij przycisk Nowy kontekst danych... Pozostaw domyślną nazwę typu kontekstu danych, a następnie kliknij przycisk Dodaj.

Zrzut ekranu przedstawiający okno nowego kontekstu danych z polem

Kliknij przycisk Dodaj w oknie dialogowym Dodawanie kontrolera, aby dodać kontroler.

Zrzut ekranu przedstawiający okno dialogowe dodawania kontrolera z różnymi wymaganiami dotyczącymi pól z polem wyboru

Uwaga: Jeśli zostanie wyświetlony komunikat o błędzie informujący o błędzie "Wystąpił błąd podczas pobierania typu...", upewnij się, że projekt programu Visual Studio został utworzony po dodaniu klasy Product. Szkielet używa odbicia w celu znalezienia klasy.

Zrzut ekranu przedstawiający program Microsoft Visual Studio z czerwonym okręgiem

Szkielet dodaje dwa pliki kodu do projektu:

  • Products.cs definiuje kontroler internetowego interfejsu API, który implementuje punkt końcowy OData.
  • ProductServiceContext.cs udostępnia metody wykonywania zapytań względem bazowej bazy danych przy użyciu programu Entity Framework.

Zrzut ekranu przedstawiający okno projektu z menu usługi produktu i krążące wokół dwóch nowo dodanych plików w ramach kontrolerów i modeli.

Dodawanie EDM i trasy

W Eksplorator rozwiązań rozwiń folder App_Start i otwórz plik o nazwie WebApiConfig.cs. Ta klasa przechowuje kod konfiguracji dla internetowego interfejsu API. Zastąp ten kod następującym:

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

Ten kod wykonuje dwie czynności:

  • Tworzy model danych jednostki (EDM) dla punktu końcowego OData.
  • Dodaje trasę dla punktu końcowego.

EDM to abstrakcyjny model danych. EDM służy do tworzenia dokumentu metadanych i definiowania identyfikatorów URI dla usługi. ODataConventionModelBuilder tworzy EDM przy użyciu zestawu domyślnych konwencji nazewnictwa EDM. Takie podejście wymaga najmniejszego kodu. Jeśli chcesz mieć większą kontrolę nad modułem EDM, możesz jawnie dodać właściwości, klucze i właściwości nawigacji za pomocą klasy ODataModelBuilder .

Metoda EntitySet dodaje jednostkę ustawioną na EDM:

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

Ciąg "Products" definiuje nazwę zestawu jednostek. Nazwa kontrolera musi być zgodna z nazwą zestawu jednostek. W tym samouczku zestaw jednostek nosi nazwę "Products", a kontroler ma nazwę ProductsController. Jeśli nazwano zestaw jednostek "ProductSet", nadasz kontrolerowi ProductSetControllernazwę . Należy pamiętać, że punkt końcowy może mieć wiele zestawów jednostek. Wywołaj metodę EntitySet<T> dla każdego zestawu jednostek, a następnie zdefiniuj odpowiedni kontroler.

Metoda MapODataRoute dodaje trasę dla punktu końcowego OData.

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

Pierwszy parametr jest przyjazną nazwą trasy. Klienci usługi nie widzą tej nazwy. Drugi parametr to prefiks identyfikatora URI punktu końcowego. Biorąc pod uwagę ten kod, identyfikator URI zestawu jednostek Products to http:// hostname/odata/Products. Aplikacja może mieć więcej niż jeden punkt końcowy OData. Dla każdego punktu końcowego wywołaj metodę MapODataRoute i podaj unikatową nazwę trasy oraz unikatowy prefiks identyfikatora URI.

Rozmieszczanie bazy danych (opcjonalnie)

W tym kroku użyjesz programu Entity Framework do rozmieszczania bazy danych z niektórymi danymi testowymi. Ten krok jest opcjonalny, ale pozwala od razu przetestować punkt końcowy OData.

W menu Narzędzia wybierz pozycję Menedżer pakietów NuGet, a następnie wybierz pozycję Konsola Menedżera pakietów. W oknie Konsola menedżera pakietów wprowadź następujące polecenie:

Enable-Migrations

Spowoduje to dodanie folderu o nazwie Migrations i pliku kodu o nazwie Configuration.cs.

Zrzut ekranu przedstawiający menu usługi produktu Eksploratora rozwiązań, krążące wokół nowo dodanego folderu o nazwie migrations i pokazującego plik w nim.

Otwórz ten plik i dodaj następujący kod do Configuration.Seed metody .

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

W oknie Konsoli Menedżera pakietów wprowadź następujące polecenia:

Add-Migration Initial
Update-Database

Te polecenia generują kod, który tworzy bazę danych, a następnie wykonuje ten kod.

Eksplorowanie punktu końcowego OData

W tej sekcji użyjemy serwera proxy debugowania internetowego programu Fiddler , aby wysyłać żądania do punktu końcowego i badać komunikaty odpowiedzi. Pomoże to zrozumieć możliwości punktu końcowego OData.

W programie Visual Studio naciśnij klawisz F5, aby rozpocząć debugowanie. Domyślnie program Visual Studio otwiera przeglądarkę na http://localhost:*port*, gdzie port jest numerem portu skonfigurowanym w ustawieniach projektu.

Numer portu można zmienić w ustawieniach projektu. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie Właściwości. W oknie właściwości wybierz pozycję Sieć Web. Wprowadź numer portu w obszarze Adres URL projektu.

Dokument usługi

Dokument usługi zawiera listę zestawów jednostek dla punktu końcowego OData. Aby uzyskać dokument usługi, wyślij żądanie GET do głównego identyfikatora URI usługi.

Za pomocą programu Fiddler wprowadź następujący identyfikator URI na karcie Kompozytor : http://localhost:port/odata/, gdzie port jest numerem portu.

Zrzut ekranu przedstawiający okno dokumentu usługi, na którym są wyświetlane różne karty z wybraną kartą

Kliknij przycisk Wykonaj. Program Fiddler wysyła żądanie HTTP GET do aplikacji. Powinna zostać wyświetlona odpowiedź na liście Sesje sieci Web. Jeśli wszystko działa, kod stanu będzie 200.

Zrzut ekranu przedstawiający listę sesji internetowych z protokołem H T T P z numerem wyniku 200 oraz adresem U R L i hostem.

Kliknij dwukrotnie odpowiedź na liście Sesje sieci Web, aby wyświetlić szczegóły komunikatu odpowiedzi na karcie Inspektorzy.

Zrzut ekranu przedstawiający kartę inspektora listy sesji internetowych, wyświetlając odpowiedź Nagłówki żądań i informacje X M L.

Nieprzetworzona odpowiedź HTTP powinna wyglądać podobnie do następującego:

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>

Domyślnie internetowy interfejs API zwraca dokument usługi w formacie AtomPub. Aby zażądać kodu JSON, dodaj następujący nagłówek do żądania HTTP:

Accept: application/json

Zrzut ekranu przedstawiający okno sesji internetowych z odpowiedzią z sekcji A P I w sekcji Nagłówki żądań i krążąc, gdzie można napisać żądanie syna j.

Teraz odpowiedź HTTP zawiera ładunek 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"
    }
  ]
}

Dokument metadanych usługi

Dokument metadanych usługi opisuje model danych usługi przy użyciu języka XML o nazwie Koncepcyjny Język definicji schematu (CSDL). Dokument metadanych przedstawia strukturę danych w usłudze i może służyć do generowania kodu klienta.

Aby uzyskać dokument metadanych, wyślij żądanie GET do http://localhost:port/odata/$metadata. Oto metadane punktu końcowego pokazanego w tym samouczku.

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>

Zestaw jednostek

Aby uzyskać zestaw jednostek Products, wyślij żądanie GET do 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"
    }
  ]
}

Jednostka

Aby uzyskać pojedynczy produkt, wyślij żądanie GET do http://localhost:port/odata/Products(1), gdzie "1" jest identyfikatorem produktu.

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

Formaty serializacji OData

Funkcja OData obsługuje kilka formatów serializacji:

  • Atom Pub (XML)
  • Kod JSON "light" (wprowadzony w usłudze OData v3)
  • JSON "verbose" (OData v2)

Domyślnie internetowy interfejs API używa formatu AtomPubJSON "light".

Aby uzyskać format AtomPub, ustaw nagłówek Accept na "application/atom+xml". Oto przykładowa treść odpowiedzi:

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

Widać jedną oczywistą wadę formatu Atom: Jest to o wiele bardziej pełne niż światło JSON. Jeśli jednak masz klienta, który rozumie AtomPub, klient może preferować ten format za pośrednictwem formatu JSON.

Oto jasna wersja JSON tej samej jednostki:

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

Format światła JSON został wprowadzony w wersji 3 protokołu OData. W celu zapewnienia zgodności z poprzednimi wersjami klient może zażądać starszego formatu JSON "pełnej". Aby zażądać pełnej wartości JSON, ustaw nagłówek Accept na application/json;odata=verbose. Oto wersja szczegółowa:

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

Ten format przekazuje więcej metadanych w treści odpowiedzi, co może zwiększyć obciążenie całej sesji. Ponadto dodaje poziom pośredni poprzez zawijanie obiektu we właściwości o nazwie "d".

Następne kroki