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 Press
Book
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 iPress
wartość atrybutuOpenType
ma wartość true. TypyCustomer
iAddress
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
.