Tworzenie punktu końcowego OData V3 przy użyciu interfejsu Web API 2

według Jan Wasson

Pobierz ukończony projekt

Protokół Open Data Protocol (OData) to protokół dostępu do danych dla sieci Web. Usługa OData zapewnia jednolity sposób tworzenia struktur danych, wykonywania zapytań dotyczących danych i manipulowania danymi za pomocą operacji CRUD (tworzenie, odczytywanie, aktualizowanie i usuwanie). Usługa OData obsługuje zarówno formaty AtomPub (XML), jak i JSON. Usługa OData definiuje również sposób ujawniania metadanych dotyczących danych. Klienci mogą używać metadanych do wykrywania informacji o typie i relacji dla zestawu danych.

Interfejs API sieci Web ASP.NET ułatwia tworzenie punktu końcowego OData dla zestawu danych. Można kontrolować dokładne operacje OData obsługiwane przez punkt końcowy. Można hostować wiele punktów końcowych OData, obok punktów końcowych innych niż OData. Masz pełną kontrolę nad modelem danych, logiką biznesową i warstwą danych.

Wersje oprogramowania używane w samouczku

Obsługa protokołu OData interfejsu API sieci Web została dodana w ASP.NET and Web Tools 2012,2 Update. Jednak w tym samouczku użyto szkieletu, który został dodany w Visual Studio 2013.

W tym samouczku utworzysz prosty punkt końcowy OData, który mogą wykonywać zapytania na klientach. Zostanie również utworzony C# klient dla punktu końcowego. Po ukończeniu tego samouczka następny zestaw samouczków pokazuje, jak dodać więcej funkcji, w tym relacje między jednostkami, 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 zostanie dodana większa funkcja.

Uruchom program Visual Studio i wybierz pozycję Nowy projekt na stronie startowej. Lub w menu plik wybierz polecenie Nowy , a następnie pozycję projekt.

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

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

Dodaj model jednostki

Model to obiekt, który reprezentuje dane w aplikacji. W tym samouczku potrzebny jest model, który reprezentuje produkt. Model odpowiada typowi obiektu OData.

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

W oknie dialogowym Dodaj nowy element nazwij klasę ""produktu.

Note

Według Konwencji klasy modelu są umieszczane w folderze models. Nie musisz stosować tej Konwencji we własnych projektach, ale użyjemy jej w tym samouczku.

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ą badać produkty według identyfikatora. To pole będzie również kluczem podstawowym w bazie danych zaplecza.

Kompiluj projekt teraz. W następnym kroku użyjemy szkieletu programu Visual Studio, który używa odbicia, aby znaleźć typ produktu.

Dodawanie kontrolera OData

Kontroler jest klasą, która obsługuje żądania HTTP. Należy zdefiniować osobny kontroler dla każdego zestawu jednostek w usłudze OData. W tym samouczku utworzymy jeden kontroler.

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

W oknie dialogowym Dodawanie szkieletu wybierz kontroler "Web API 2 OData z akcjami, używając Entity Framework".

W oknie dialogowym Dodawanie kontrolera Nazwij kontroler "ProductsController". Zaznacz pole wyboru "Użyj akcji kontrolera asynchronicznego". Z listy rozwijanej model wybierz klasę Product (produkt).

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

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

Uwaga: Jeśli pojawi się komunikat o błędzie z informacją "Wystąpił błąd podczas pobierania typu...", upewnij się, że projekt programu Visual Studio został skompilowany po dodaniu klasy Product. Szkielet używa odbicia, aby znaleźć klasę.

Tworzenie szkieletu powoduje dodanie dwóch plików kodu do projektu:

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

Dodawanie modelu EDM i trasy

W Eksplorator rozwiązań rozwiń węzeł aplikacja_folder Start i Otwórz plik o nazwie WebApiConfig.cs. Ta klasa zawiera kod konfiguracyjny 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 Entity Data Model (EDM) dla punktu końcowego OData.
  • Dodaje trasę dla punktu końcowego.

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

Metoda EntitySet dodaje jednostkę ustawioną do modelu 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 ma nazwę "produkty", a kontroler ma nazwę ProductsController. Jeśli nazwa zestawu jednostek to "ProductSet", należy nazwać kontroler ProductSetController. Należy pamiętać, że punkt końcowy może mieć wiele zestawów jednostek. Wywołaj element EntitySet<t> dla każdego zestawu jednostek, a następnie zdefiniuj odpowiedni kontroler.

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

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

Pierwszy parametr jest przyjazną nazwą dla trasy. Klienci usługi nie widzą tej nazwy. Drugi parametr jest prefiksem identyfikatora URI dla punktu końcowego. Mając ten kod, identyfikator URI dla 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 MapODataRoute i podaj unikatową nazwę trasy i unikatowy prefiks identyfikatora URI.

Wypełnianie bazy danych (opcjonalnie)

W tym kroku będziesz używać Entity Framework do wypełniania bazy danych niektórymi danymi testowymi. Ten krok jest opcjonalny, ale pozwala na natychmiastowe przetestowanie punktu końcowego 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.

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

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 Konsola 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 sieci Web programu Fiddler do wysyłania żądań do punktu końcowego i badania komunikatów 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ę w celu 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 polu 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.

Korzystając z programu Fiddler, wprowadź następujący identyfikator URI na karcie układacz : http://localhost:port/odata/, gdzie port jest numerem portu.

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

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

Nieprzetworzony komunikat odpowiedzi HTTP powinien wyglądać podobnie do poniższego:

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 interfejs API sieci Web zwraca dokument usługi w formacie AtomPub. Aby poprosić o dane JSON, Dodaj następujący nagłówek do żądania HTTP:

Accept: application/json

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

W dokumencie metadanych usługi opisano model danych usługi przy użyciu języka XML o nazwie język definicji schematu koncepcyjnego (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 dla punktu końcowego wyświetlanego 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ć indywidualny 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

Usługa OData obsługuje kilka formatów serializacji:

  • Atom pub (XML)
  • Notacja JSON "Light" (wprowadzona w protokole OData V3)
  • JSON "verbose" (OData v2)

Domyślnie interfejs API sieci Web używa formatu AtomPubJSON "Light".

Aby uzyskać format AtomPub, należy ustawić nagłówek Accept na wartość "Application/Atom + XML". Oto przykład treści 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>

Można zobaczyć jedną z oczywistych niekorzystnych niedogodności w formacie Atom: jest to znacznie bardziej szczegółowe niż oświetlenie JSON. Jeśli jednak klient ma świadomość AtomPub, klient może preferować ten format w formacie JSON.

Oto wersja uproszczona JSON tej samej jednostki:

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

Format oświetlenia 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 "verbose". Aby zażądać pełnego kodu JSON, ustaw nagłówek Accept na application/json;odata=verbose. Oto pełna wersja:

{
  "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 umożliwia przekazanie większej liczby metadanych w treści odpowiedzi, co może zwiększyć znaczne obciążenie całej sesji. Ponadto dodaje poziom pośredni przez Zawijanie obiektu we właściwości o nazwie "d".

Następne kroki