Udostępnij za pośrednictwem


Otwieranie typów w usłudze OData w wersji 4 za pomocą interfejsu API sieci Web ASP.NET

autor: Microsoft

W usłudze OData w wersji 4 typ otwierania jest typem ustrukturyzowanym, który zawiera właściwości dynamiczne, oprócz wszystkich właściwości zadeklarowanych w definicji typu. Otwarte typy umożliwiają dodawanie elastyczności do modeli danych. W tym samouczku pokazano, jak używać typów otwartych w usłudze OData interfejsu API sieci Web ASP.NET.

W tym samouczku założono, że wiesz już, jak utworzyć punkt końcowy OData w interfejsie API sieci Web ASP.NET. Jeśli nie, najpierw przeczytaj artykuł Create an OData v4 Endpoint (Utwórz punkt końcowy OData w wersji 4 ).

Wersje oprogramowania używane w samouczku

  • Internetowy interfejs API OData 5.3
  • OData 4

Najpierw niektóre terminy OData:

  • Typ jednostki: typ ustrukturyzowany z kluczem.
  • Typ złożony: typ ustrukturyzowany bez klucza.
  • Typ otwierania: typ z właściwościami dynamicznymi. Zarówno typy jednostek, jak i typy złożone mogą być otwarte.

Wartość właściwości dynamicznej może być typem pierwotnym, typem złożonym lub typem wyliczenia; lub kolekcja dowolnego z tych typów. Aby uzyskać więcej informacji na temat typów otwartych, zobacz specyfikację OData v4.

Instalowanie bibliotek OData sieci Web

Użyj Menedżera pakietów NuGet, aby zainstalować najnowsze biblioteki OData interfejsu API sieci Web. W oknie Konsola Menedżera pakietów:

Install-Package Microsoft.AspNet.OData
Install-Package Microsoft.AspNet.WebApi.OData

Definiowanie typów CLR

Zacznij od zdefiniowania modeli EDM jako typów CLR.

public enum Category
{
    Book,
    Magazine,
    EBook
}

public class Address
{
    public string City { get; set; }
    public string Street { get; set; }
}

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Address Address { get; set; }
}

public class Press
{
    public string Name { get; set; }
    public string Email { get; set; }
    public Category Category { get; set; }
    public IDictionary<string, object> DynamicProperties { get; set; }
}

public class Book
{
    [Key]
    public string ISBN { get; set; }
    public string Title { get; set; }
    public Press Press { get; set; }
    public IDictionary<string, object> Properties { get; set; }
}

Po utworzeniu modelu danych jednostki (EDM)

  • Category jest typem wyliczenia.
  • Address jest typem złożonym. (Nie ma klucza, więc nie jest to typ jednostki).
  • Customer jest typem jednostki. (Ma klucz).
  • Press jest otwartym typem złożonym.
  • Book jest typem otwartej jednostki.

Aby utworzyć typ otwierania, typ CLR musi mieć właściwość typu IDictionary<string, object>, która zawiera właściwości dynamiczne.

Tworzenie modelu EDM

Jeśli do utworzenia EDM jest używany program ODataConventionModelBuilder i PressBook są automatycznie dodawane jako typy otwarte na podstawie obecności IDictionary<string, object> właściwości.

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<Book>("Books");
        builder.EntitySet<Customer>("Customers");
        var model = builder.GetEdmModel();

        config.MapODataServiceRoute(
            routeName: "ODataRoute",
            routePrefix: null,
            model: model);

    }
}

Można również jawnie skompilować EDM przy użyciu narzędzia ODataModelBuilder.

ODataModelBuilder builder = new ODataModelBuilder();

ComplexTypeConfiguration<Press> pressType = builder.ComplexType<Press>();
pressType.Property(c => c.Name);
// ...
pressType.HasDynamicProperties(c => c.DynamicProperties);

EntityTypeConfiguration<Book> bookType = builder.EntityType<Book>();
bookType.HasKey(c => c.ISBN);
bookType.Property(c => c.Title);
// ...
bookType.ComplexProperty(c => c.Press);
bookType.HasDynamicProperties(c => c.Properties);

// ...
builder.EntitySet<Book>("Books");
IEdmModel model = builder.GetEdmModel();

Dodawanie kontrolera OData

Następnie dodaj kontroler OData. Na potrzeby tego samouczka użyjemy uproszczonego kontrolera, który obsługuje tylko żądania GET i POST oraz używa listy w pamięci do przechowywania jednostek.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.OData;

namespace MyApp.Controllers
{
    public class BooksController : ODataController
    {
        private IList<Book> _books = new List<Book>
        {
            new Book
            {
                ISBN = "978-0-7356-8383-9",
                Title = "SignalR Programming in Microsoft ASP.NET",
                Press = new Press
                {
                    Name = "Microsoft Press",
                    Category = Category.Book
                }
            },

            new Book
            {
                ISBN = "978-0-7356-7942-9",
                Title = "Microsoft Azure SQL Database Step by Step",
                Press = new Press
                {
                    Name = "Microsoft Press",
                    Category = Category.EBook,
                    DynamicProperties = new Dictionary<string, object>
                    {
                        { "Blog", "https://blogs.msdn.com/b/microsoft_press/" },
                        { "Address", new Address { 
                              City = "Redmond", Street = "One Microsoft Way" }
                        }
                    }
                },
                Properties = new Dictionary<string, object>
                {
                    { "Published", new DateTimeOffset(2014, 7, 3, 0, 0, 0, 0, new TimeSpan(0))},
                    { "Authors", new [] { "Leonard G. Lobel", "Eric D. Boyd" }},
                    { "OtherCategories", new [] {Category.Book, Category.Magazine}}
                }
            }
        };

        [EnableQuery]
        public IQueryable<Book> Get()
        {
            return _books.AsQueryable();
        }

        public IHttpActionResult Get([FromODataUri]string key)
        {
            Book book = _books.FirstOrDefault(e => e.ISBN == key);
            if (book == null)
            {
                return NotFound();
            }

            return Ok(book);
        }

        public IHttpActionResult Post(Book book)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            } 
            // For this sample, we aren't enforcing unique keys.
            _books.Add(book);
            return Created(book);
        }
    }
}

Zwróć uwagę, że pierwsze Book wystąpienie nie ma właściwości dynamicznych. Drugie Book wystąpienie ma następujące właściwości dynamiczne:

  • "Opublikowane": Typ pierwotny
  • "Autorzy": kolekcja typów pierwotnych
  • "OtherCategories": Kolekcja typów wyliczenia.

Press Ponadto właściwość tego Book wystąpienia ma następujące właściwości dynamiczne:

  • "Blog": Typ pierwotny
  • "Adres": typ złożony

Wykonywanie zapytań dotyczących metadanych

Aby uzyskać dokument metadanych OData, wyślij żądanie GET do ~/$metadata. Treść odpowiedzi powinna wyglądać podobnie do następującej:

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
  <edmx:DataServices>
    <Schema Namespace="MyApp.Models" xmlns="http://docs.oasis-open.org/odata/ns/edm">
      <EntityType Name="Book" OpenType="true">
        <Key>
          <PropertyRef Name="ISBN" />
        </Key>
        <Property Name="ISBN" Type="Edm.String" Nullable="false" />
        <Property Name="Title" Type="Edm.String" />
        <Property Name="Press" Type="MyApp.Models.Press" />
      </EntityType>
      <EntityType Name="Customer">
        <Key>
          <PropertyRef Name="Id" />
        </Key>
        <Property Name="Id" Type="Edm.Int32" Nullable="false" />
        <Property Name="Name" Type="Edm.String" />
        <Property Name="Address" Type="MyApp.Models.Address" />
      </EntityType>
      <ComplexType Name="Press" OpenType="true">
        <Property Name="Name" Type="Edm.String" />
        <Property Name="Category" Type="MyApp.Models.Category" Nullable="false" />
      </ComplexType>
      <ComplexType Name="Address">
        <Property Name="City" Type="Edm.String" />
        <Property Name="Street" Type="Edm.String" />
      </ComplexType>
      <EnumType Name="Category">
        <Member Name="Book" Value="0" />
        <Member Name="Magazine" Value="1" />
        <Member Name="EBook" Value="2" />
      </EnumType>
    </Schema>
    <Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm">
      <EntityContainer Name="Container">
        <EntitySet Name="Books" EntityType="MyApp.Models.Book" />
        <EntitySet Name="Customers" EntityType="MyApp.Models.Customer" />
      </EntityContainer>
    </Schema>
  </edmx:DataServices>
</edmx:Edmx>

Z dokumentu metadanych można zobaczyć, że:

  • Book Dla typów i Press wartość atrybutu OpenType ma wartość true. Typy Customer i Address nie mają tego atrybutu.
  • Typ Book jednostki ma trzy zadeklarowane właściwości: ISBN, Title i Press. Metadane OData nie zawierają Book.Properties właściwości klasy CLR.
  • Press Podobnie typ złożony ma tylko dwie zadeklarowane właściwości: Nazwa i Kategoria. Metadane nie zawierają Press.DynamicProperties właściwości klasy CLR.

Wykonywanie zapytań względem jednostki

Aby uzyskać książkę z ISBN równym "978-0-7356-7942-9", wyślij żądanie GET do ~/Books('978-0-7356-7942-9'). Treść odpowiedzi powinna wyglądać podobnie do poniższej. (Wcięcie, aby było bardziej czytelne).

{
  "@odata.context":"http://localhost:37141/$metadata#Books/$entity",
    "ISBN":"978-0-7356-7942-9",
    "Title":"Microsoft Azure SQL Database Step by Step",
    "Press":{
      "Name":"Microsoft Press",
      "Category":"EBook",
      "Blog":"https://blogs.msdn.com/b/microsoft_press/",
      "Address":{
        "@odata.type":"#MyApp.Models.Address",
        "City":"Redmond",
        "Street":"One Microsoft Way"
      }
  },
  "Published":"2014-07-03T00:00:00Z",
  "Authors@odata.type":"#Collection(String)",
  "Authors":[
    "Leonard G. Lobel","Eric D. Boyd"
  ],
  "OtherCategories@odata.type":"#Collection(MyApp.Models.Category)",
  "OtherCategories":[
    "Book","Magazine"
  ]
}

Zwróć uwagę, że właściwości dynamiczne są uwzględniane w tekście z zadeklarowanymi właściwościami.

PUBLIKOWANIE jednostki

Aby dodać jednostkę Book, wyślij żądanie POST do ~/Books. Klient może ustawić właściwości dynamiczne w ładunku żądania.

Oto przykładowe żądanie. Zanotuj właściwości "Price" i "Published".

POST http://localhost:37141/Books HTTP/1.1
User-Agent: Fiddler
Host: localhost:37141
Content-Type: application/json
Content-Length: 191

{
  "ISBN":"978-0-7356-8383-9","Title":"Programming Microsoft ASP.NET MVC","Press":{
  "Name":"Microsoft Press","Category":"Book"
   }, "Price": 49.99, "Published":"2014-02-15T00:00:00Z"
}

Jeśli ustawisz punkt przerwania w metodzie kontrolera, zobaczysz, że internetowy interfejs API dodał te właściwości do słownika Properties .

Zrzut ekranu przedstawiający kod, który wysyła żądanie POST z wyróżnioną częścią

Dodatkowe zasoby

Przykład typu otwartego OData