Bagikan melalui


Buka Jenis di OData v4 dengan ASP.NET Web API

oleh Microsoft

Di OData v4, jenis terbuka adalah jenis terstruktur yang berisi properti dinamis, selain properti apa pun yang dideklarasikan dalam definisi jenis. Jenis terbuka memungkinkan Anda menambahkan fleksibilitas ke model data Anda. Tutorial ini menunjukkan cara menggunakan jenis terbuka di ASP.NET Web API OData.

Tutorial ini mengasumsikan bahwa Anda sudah tahu cara membuat titik akhir OData di ASP.NET Web API. Jika tidak, mulailah dengan membaca Buat Titik Akhir OData v4 terlebih dahulu.

Versi perangkat lunak yang digunakan dalam tutorial

  • Web API OData 5.3
  • OData v4

Pertama, beberapa terminologi OData:

  • Jenis entitas: Jenis terstruktur dengan kunci.
  • Jenis kompleks: Jenis terstruktur tanpa kunci.
  • Jenis terbuka: Jenis dengan properti dinamis. Jenis entitas dan jenis kompleks dapat terbuka.

Nilai properti dinamis dapat berupa jenis primitif, jenis kompleks, atau jenis enumerasi; atau koleksi salah satu jenis tersebut. Untuk informasi selengkapnya tentang jenis terbuka, lihat spesifikasi OData v4.

Menginstal Pustaka OData Web

Gunakan Pengelola Paket NuGet untuk menginstal pustaka OData API Web terbaru. Dari jendela Package Manager Console:

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

Tentukan Jenis CLR

Mulailah dengan mendefinisikan model EDM sebagai jenis 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; }
}

Saat Model Data Entitas (EDM) dibuat,

  • Category adalah jenis enumerasi.
  • Address adalah jenis kompleks. (Ini tidak memiliki kunci, jadi bukan jenis entitas.)
  • Customer adalah jenis entitas. (Ini memiliki kunci.)
  • Press adalah jenis kompleks terbuka.
  • Book adalah jenis entitas terbuka.

Untuk membuat jenis terbuka, jenis CLR harus memiliki properti jenis IDictionary<string, object>, yang menyimpan properti dinamis.

Membangun Model EDM

Jika Anda menggunakan ODataConventionModelBuilder untuk membuat EDM, Press dan Book secara otomatis ditambahkan sebagai jenis terbuka, berdasarkan keberadaan IDictionary<string, object> properti.

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

    }
}

Anda juga dapat membangun EDM secara eksplisit, menggunakan 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();

Menambahkan Pengontrol OData

Selanjutnya, tambahkan pengontrol OData. Untuk tutorial ini, kita akan menggunakan pengontrol yang disederhanakan yang hanya mendukung permintaan GET dan POST, dan menggunakan daftar dalam memori untuk menyimpan entitas.

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

Perhatikan bahwa instans pertama Book tidak memiliki properti dinamis. Instans kedua Book memiliki properti dinamis berikut:

  • "Diterbitkan": Jenis primitif
  • "Penulis": Kumpulan jenis primitif
  • "OtherCategories": Kumpulan jenis enumerasi.

Selain itu Press , properti instans Book tersebut memiliki properti dinamis berikut:

  • "Blog": Jenis primitif
  • "Alamat": Jenis kompleks

Mengkueri Metadata

Untuk mendapatkan dokumen metadata OData, kirim permintaan GET ke ~/$metadata. Isi respons akan terlihat mirip dengan ini:

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

Dari dokumen metadata, Anda bisa melihat bahwa:

  • Book Untuk jenis dan Press , nilai OpenType atribut adalah benar. Jenis Customer dan Address tidak memiliki atribut ini.
  • Jenis Book entitas memiliki tiga properti yang dideklarasikan: ISBN, Judul, dan Tekan. Metadata OData tidak menyertakan Book.Properties properti dari kelas CLR.
  • Demikian pula, Press jenis kompleks hanya memiliki dua properti yang dideklarasikan: Nama dan Kategori. Metadata tidak menyertakan Press.DynamicProperties properti dari kelas CLR.

Mengkueri Entitas

Untuk mendapatkan buku dengan ISBN sama dengan "978-0-7356-7942-9", kirim permintaan GET ke ~/Books('978-0-7356-7942-9'). Isi respons akan terlihat mirip dengan yang berikut ini. (Inden untuk membuatnya lebih mudah dibaca.)

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

Perhatikan bahwa properti dinamis disertakan sebaris dengan properti yang dideklarasikan.

POSTING Entitas

Untuk menambahkan entitas Buku, kirim permintaan POST ke ~/Books. Klien dapat mengatur properti dinamis dalam payload permintaan.

Berikut adalah contoh permintaan. Perhatikan properti "Harga" dan "Diterbitkan".

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

Jika Anda mengatur titik henti dalam metode pengontrol, Anda dapat melihat bahwa API Web menambahkan properti ini ke Properties kamus.

Cuplikan layar kode yang mengirim permintaan POST, menyoroti bagian 'tambahkan buku' dari kode untuk menampilkan properti yang ditambahkan oleh Web A P I.

Sumber Daya Tambahan

Sampel Tipe Terbuka OData