ASP.NET Web API'siyle OData v4'te Açık Türler

Microsoft tarafından

OData v4'te , açık tür , tür tanımında bildirilen özelliklere ek olarak dinamik özellikler içeren yapılandırılmış bir türdür. Açık türler, veri modellerinize esneklik eklemenize olanak tanır. Bu öğreticide, ASP.NET Web API OData'da açık türlerin nasıl kullanılacağı gösterilmektedir.

Bu öğreticide, ASP.NET Web API'sinde OData uç noktası oluşturmayı zaten bildiğiniz varsayılır. Aksi takdirde, önce OData v4 Uç Noktası Oluşturma'yı okuyarak başlayın.

Öğreticide kullanılan yazılım sürümleri

  • Web API OData 5.3
  • OData v4

İlk olarak, bazı OData terminolojisi:

  • Varlık türü: Anahtar içeren yapılandırılmış bir tür.
  • Karmaşık tür: Anahtar içermeyen yapılandırılmış bir tür.
  • Açık tür: Dinamik özelliklere sahip bir tür. Hem varlık türleri hem de karmaşık türler açık olabilir.

Dinamik özelliğin değeri ilkel bir tür, karmaşık tür veya numaralandırma türü olabilir; veya bu türlerden herhangi birinin koleksiyonu. Açık türler hakkında daha fazla bilgi için bkz. OData v4 belirtimi.

Web OData Kitaplıklarını Yükleme

En son Web API'si OData kitaplıklarını yüklemek için NuGet Paket Yöneticisi'ni kullanın. Paket Yöneticisi Konsolu penceresinden:

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

CLR Türlerini Tanımlama

EDM modellerini CLR türleri olarak tanımlayarak başlayın.

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

Varlık Veri Modeli (EDM) oluşturulduğunda,

  • Category bir numaralandırma türüdür.
  • Address karmaşık bir türdür. (Anahtarı olmadığından varlık türü değildir.)
  • Customer bir varlık türüdür. (Anahtarı vardır.)
  • Press açık bir karmaşık türdür.
  • Book açık bir varlık türüdür.

Açık bir tür oluşturmak için CLR türünün, dinamik özellikleri tutan türünde IDictionary<string, object>bir özelliği olmalıdır.

EDM Modelini Oluşturma

EDM'yi Press oluşturmak için ODataConventionModelBuilder kullanıyorsanız ve Book bir IDictionary<string, object> özelliğin varlığına bağlı olarak otomatik olarak açık türler olarak eklenirse.

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

    }
}

ODataModelBuilder kullanarak EDM'yi açıkça da oluşturabilirsiniz.

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

OData Denetleyicisi Ekleme

Ardından bir OData denetleyicisi ekleyin. Bu öğreticide, yalnızca GET ve POST isteklerini destekleyen ve varlıkları depolamak için bellek içi bir liste kullanan basitleştirilmiş bir denetleyici kullanacağız.

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

İlk Book örneğin dinamik özellikleri olmadığına dikkat edin. İkinci Book örnek aşağıdaki dinamik özelliklere sahiptir:

  • "Yayımlandı": Temel tür
  • "Yazarlar": İlkel türlerin koleksiyonu
  • "Diğer Kategoriler": Numaralandırma türleri koleksiyonu.

Ayrıca, Press bu Book örneğin özelliği aşağıdaki dinamik özelliklere sahiptir:

  • "Blog": Temel tür
  • "Adres": Karmaşık tür

Meta Verileri Sorgulama

OData meta veri belgesini almak için adresine bir GET isteği ~/$metadatagönderin. Yanıt gövdesi şuna benzer olmalıdır:

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

Meta veri belgesinde şunları görebilirsiniz:

  • Book ve Press türleri için özniteliğinin OpenType değeri true değeridir. Customer ve Address türleri bu özniteliğe sahip değildir.
  • Varlık Book türünün bildirilen üç özelliği vardır: ISBN, Title ve Press. OData meta verileri CLR sınıfından Book.Properties özelliğini içermez.
  • Benzer şekilde, karmaşık türün Press yalnızca iki bildirilen özelliği vardır: Ad ve Kategori. Meta veriler CLR sınıfından özelliğini içermez Press.DynamicProperties .

Varlığı Sorgulama

ISBN değeri "978-0-7356-7942-9" olan kitabı almak için ~/Books('978-0-7356-7942-9')adresine bir GET isteği gönderin. Yanıt gövdesi aşağıdakine benzer görünmelidir. (Daha okunabilir hale getirmek için girintili.)

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

Dinamik özelliklerin bildirilen özelliklerle birlikte satır içinde yer aldığına dikkat edin.

POST an Entity

Kitap varlığı eklemek için adresine bir POST isteği ~/Booksgönderin. İstemci, istek yükünde dinamik özellikler ayarlayabilir.

Örnek bir istek aşağıda verilmiştir. "Fiyat" ve "Yayımlanan" özelliklerine dikkat edin.

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

Denetleyici yönteminde bir kesme noktası ayarlarsanız, Web API'sinin Properties sözlüğe bu özellikleri eklediğini görebilirsiniz.

Web A P I tarafından eklenen özellikleri göstermek için kodun 'kitap ekle' bölümünü vurgulayarak POST isteği gönderen kodun ekran görüntüsü.

Ek Kaynaklar

OData Açık Tür Örneği