Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
oleh Mike Wasson
Tutorial ini menunjukkan cara memanggil layanan OData dari aplikasi klien C#.
Versi perangkat lunak yang digunakan dalam tutorial
- Visual Studio 2013 (berfungsi dengan Visual Studio 2012)
- Pustaka Klien WCF Data Services
- WEB API 2. (Contoh layanan OData dibangun menggunakan Web API 2, tetapi aplikasi klien tidak bergantung pada WEB API.)
Dalam tutorial ini, saya akan berjalan melalui pembuatan aplikasi klien yang memanggil layanan OData. Layanan OData mengekspos entitas berikut:
Product
Supplier
ProductRating
Artikel berikut menjelaskan cara mengimplementasikan layanan OData di Web API. (Namun, Anda tidak perlu membacanya untuk memahami tutorial ini.)
- Membuat Titik Akhir OData di Web API 2
- Hubungan Entitas OData di Web API 2
- Tindakan OData di Web API 2
Membuat Proksi Layanan
Langkah pertama adalah membuat proksi layanan. Proksi layanan adalah kelas .NET yang menentukan metode untuk mengakses layanan OData. Proksi menerjemahkan panggilan metode ke dalam permintaan HTTP.
Mulailah dengan membuka proyek layanan OData di Visual Studio. Tekan CTRL+F5 untuk menjalankan layanan secara lokal di IIS Express. Perhatikan alamat lokal, termasuk nomor port yang ditetapkan Visual Studio. Anda akan memerlukan alamat ini saat membuat proksi.
Selanjutnya, buka instans Visual Studio lain dan buat proyek aplikasi konsol. Aplikasi konsol akan menjadi aplikasi klien OData kami. (Anda juga dapat menambahkan proyek ke solusi yang sama dengan layanan.)
Catatan
Langkah-langkah yang tersisa merujuk ke proyek konsol.
Di Penjelajah Solusi, klik kanan Referensi dan pilih Tambahkan Referensi Layanan.
Dalam dialog Tambahkan Referensi Layanan , ketik alamat layanan OData:
http://localhost:port/odata
di mana port adalah nomor port.
Untuk Namespace, ketik "ProductService". Opsi ini menentukan namespace kelas proksi.
Klik Buka. Visual Studio membaca dokumen metadata OData untuk menemukan entitas dalam layanan.
Klik OK untuk menambahkan kelas proksi ke proyek Anda.
Membuat Instans Kelas Proksi Layanan
Di dalam metode Anda Main
, buat instans baru kelas proksi, sebagai berikut:
using System;
using System.Data.Services.Client;
using System.Linq;
namespace Client
{
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:1234/odata/");
var container = new ProductService.Container(uri);
// ...
}
}
}
Sekali lagi, gunakan nomor port aktual tempat layanan Anda berjalan. Saat Anda menyebarkan layanan, Anda akan menggunakan URI layanan langsung. Anda tidak perlu memperbarui proksi.
Kode berikut menambahkan penanganan aktivitas yang mencetak URI permintaan ke jendela konsol. Langkah ini tidak diperlukan, tetapi menarik untuk melihat URI untuk setiap kueri.
container.SendingRequest2 += (s, e) =>
{
Console.WriteLine("{0} {1}", e.RequestMessage.Method, e.RequestMessage.Url);
};
Mengkueri Layanan
Kode berikut mendapatkan daftar produk dari layanan OData.
class Program
{
static void DisplayProduct(ProductService.Product product)
{
Console.WriteLine("{0} {1} {2}", product.Name, product.Price, product.Category);
}
// Get an entire entity set.
static void ListAllProducts(ProductService.Container container)
{
foreach (var p in container.Products)
{
DisplayProduct(p);
}
}
static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:18285/odata/");
var container = new ProductService.Container(uri);
container.SendingRequest2 += (s, e) =>
{
Console.WriteLine("{0} {1}", e.RequestMessage.Method, e.RequestMessage.Url);
};
// Get the list of products
ListAllProducts(container);
}
}
Perhatikan bahwa Anda tidak perlu menulis kode apa pun untuk mengirim permintaan HTTP atau mengurai respons. Kelas proksi melakukan ini secara otomatis ketika Anda menghitung Container.Products
koleksi dalam perulangan foreach .
Saat Anda menjalankan aplikasi, output akan terlihat seperti berikut:
GET http://localhost:60868/odata/Products
Hat 15.00 Apparel
Scarf 12.00 Apparel
Socks 5.00 Apparel
Yo-yo 4.95 Toys
Puzzle 8.00 Toys
Untuk mendapatkan entitas menurut ID, gunakan klausul where
.
// Get a single entity.
static void ListProductById(ProductService.Container container, int id)
{
var product = container.Products.Where(p => p.ID == id).SingleOrDefault();
if (product != null)
{
DisplayProduct(product);
}
}
Untuk topik lainnya, saya tidak akan menampilkan seluruh Main
fungsi, hanya kode yang diperlukan untuk memanggil layanan.
Terapkan Opsi Kueri
OData menentukan opsi kueri yang dapat digunakan untuk memfilter, mengurutkan, data halaman, dan sebagainya. Di proksi layanan, Anda dapat menerapkan opsi ini dengan menggunakan berbagai ekspresi LINQ.
Di bagian ini, saya akan menampilkan contoh singkat. Untuk detail selengkapnya, lihat topik Pertimbangan LINQ (WCF Data Services) di MSDN.
Pemfilteran ($filter)
Untuk memfilter, gunakan where
klausul . Contoh berikut memfilter menurut kategori produk.
// Use the $filter option.
static void ListProductsInCategory(ProductService.Container container, string category)
{
var products =
from p in container.Products
where p.Category == category
select p;
foreach (var p in products)
{
DisplayProduct(p);
}
}
Kode ini sesuai dengan kueri OData berikut.
GET http://localhost/odata/Products()?$filter=Category eq 'apparel'
Perhatikan bahwa proksi mengonversi klausul where
menjadi ekspresi OData $filter
.
Pengurutan ($orderby)
Untuk mengurutkan, gunakan klausul orderby
. Contoh berikut mengurutkan menurut harga, dari tertinggi hingga terendah.
// Use the $orderby option
static void ListProductsSorted(ProductService.Container container)
{
// Sort by price, highest to lowest.
var products =
from p in container.Products
orderby p.Price descending
select p;
foreach (var p in products)
{
DisplayProduct(p);
}
}
Berikut adalah permintaan OData yang sesuai.
GET http://localhost/odata/Products()?$orderby=Price desc
halaman Client-Side ($skip dan $top)
Untuk set entitas besar, klien mungkin ingin membatasi jumlah hasil. Misalnya, klien mungkin menampilkan 10 entri dalam satu waktu. Ini disebut halaman sisi klien. (Ada juga penomoran sisi server, di mana server membatasi jumlah hasil.) Untuk melakukan halaman sisi klien, gunakan metode LINQ Lewati dan Ambil . Contoh berikut melompati 40 hasil pertama dan mengambil 10 hasil berikutnya.
// Use $skip and $top options.
static void ListProductsPaged(ProductService.Container container)
{
var products =
(from p in container.Products
orderby p.Price descending
select p).Skip(40).Take(10);
foreach (var p in products)
{
DisplayProduct(p);
}
}
Berikut adalah permintaan OData yang sesuai:
GET http://localhost/odata/Products()?$orderby=Price desc&$skip=40&$top=10
Pilih ($select) dan Perluas ($expand)
Untuk menyertakan entitas terkait, gunakan metode .DataServiceQuery<t>.Expand
Misalnya, untuk menyertakan Supplier
untuk masing-masing Product
:
// Use the $expand option.
static void ListProductsAndSupplier(ProductService.Container container)
{
var products = container.Products.Expand(p => p.Supplier);
foreach (var p in products)
{
Console.WriteLine("{0}\t{1}\t{2}", p.Name, p.Price, p.Supplier.Name);
}
}
Berikut adalah permintaan OData yang sesuai:
GET http://localhost/odata/Products()?$expand=Supplier
Untuk mengubah bentuk respons, gunakan klausa pilih LINQ. Contoh berikut hanya mendapatkan nama setiap produk, tanpa properti lain.
// Use the $select option.
static void ListProductNames(ProductService.Container container)
{
var products = from p in container.Products select new { Name = p.Name };
foreach (var p in products)
{
Console.WriteLine(p.Name);
}
}
Berikut adalah permintaan OData yang sesuai:
GET http://localhost/odata/Products()?$select=Name
Klausa pilih dapat menyertakan entitas terkait. Dalam hal ini, jangan panggil Perluas; proksi secara otomatis menyertakan ekspansi dalam kasus ini. Contoh berikut mendapatkan nama dan pemasok dari setiap produk.
// Use $expand and $select options
static void ListProductNameSupplier(ProductService.Container container)
{
var products =
from p in container.Products
select new
{
Name = p.Name,
Supplier = p.Supplier.Name
};
foreach (var p in products)
{
Console.WriteLine("{0}\t{1}", p.Name, p.Supplier);
}
}
Berikut adalah permintaan OData yang sesuai. Perhatikan bahwa itu termasuk opsi $expand .
GET http://localhost/odata/Products()?$expand=Supplier&$select=Name,Supplier/Name
Untuk informasi selengkapnya tentang $select dan $expand, lihat Menggunakan $select, $expand, dan $value di Web API 2.
Tambahkan Entitas Baru
Untuk menambahkan entitas baru ke set entitas, panggil AddToEntitySet
, di mana EntitySet adalah nama kumpulan entitas. Misalnya, AddToProducts
menambahkan baru Product
ke Products
kumpulan entitas. Saat Anda membuat proksi, WCF Data Services secara otomatis membuat metode AddTo yang sangat diketik ini.
// Add an entity.
static void AddProduct(ProductService.Container container, ProductService.Product product)
{
container.AddToProducts(product);
var serviceResponse = container.SaveChanges();
foreach (var operationResponse in serviceResponse)
{
Console.WriteLine(operationResponse.StatusCode);
}
}
Untuk menambahkan tautan antara dua entitas, gunakan metode AddLink dan SetLink . Kode berikut menambahkan pemasok baru dan produk baru, lalu membuat tautan di antaranya.
// Add entities with links.
static void AddProductWithSupplier(ProductService.Container container,
ProductService.Product product, ProductService.Supplier supplier)
{
container.AddToSuppliers(supplier);
container.AddToProducts(product);
container.AddLink(supplier, "Products", product);
container.SetLink(product, "Supplier", supplier);
var serviceResponse = container.SaveChanges();
foreach (var operationResponse in serviceResponse)
{
Console.WriteLine(operationResponse.StatusCode);
}
}
Gunakan AddLink saat properti navigasi adalah koleksi. Dalam contoh ini, kami menambahkan produk ke Products
koleksi pada pemasok.
Gunakan SetLink saat properti navigasi adalah entitas tunggal. Dalam contoh ini, kami mengatur Supplier
properti pada produk.
Perbarui / Patch
Untuk memperbarui entitas, panggil metode UpdateObject .
static void UpdatePrice(ProductService.Container container, int id, decimal price)
{
var product = container.Products.Where(p => p.ID == id).SingleOrDefault();
if (product != null)
{
product.Price = price;
container.UpdateObject(product);
container.SaveChanges(SaveChangesOptions.PatchOnUpdate);
}
}
Pembaruan dilakukan saat Anda memanggil SaveChanges. Secara default, WCF mengirimkan permintaan HTTP MERGE. Opsi PatchOnUpdate memberi tahu WCF untuk mengirim PATCH HTTP sebagai gantinya.
Catatan
Mengapa PATCH versus MERGE? Spesifikasi HTTP 1.1 asli (RCF 2616) tidak menentukan metode HTTP apa pun dengan semantik "pembaruan parsial". Untuk mendukung pembaruan parsial, spesifikasi OData menentukan metode MERGE. Pada tahun 2010, RFC 5789 mendefinisikan metode PATCH untuk pembaruan parsial. Anda dapat membaca beberapa riwayat dalam posting blog ini di Blog Layanan Data WCF. Saat ini, PATCH lebih disukai daripada MERGE. Pengontrol OData yang dibuat oleh perancah API Web mendukung kedua metode.
Jika Anda ingin mengganti seluruh entitas (put semantics), tentukan opsi ReplaceOnUpdate . Ini menyebabkan WCF mengirim permintaan HTTP PUT.
container.SaveChanges(SaveChangesOptions.ReplaceOnUpdate);
Menghapus Entitas
Untuk menghapus entitas, panggil DeleteObject.
static void DeleteProduct(ProductService.Container container, int id)
{
var product = container.Products.Where(p => p.ID == id).SingleOrDefault();
if (product != null)
{
container.DeleteObject(product);
container.SaveChanges();
}
}
Memanggil Tindakan OData
Di OData, tindakan adalah cara untuk menambahkan perilaku sisi server yang tidak mudah didefinisikan sebagai operasi CRUD pada entitas.
Meskipun dokumen metadata OData menjelaskan tindakan, kelas proksi tidak membuat metode yang ditik dengan kuat untuk mereka. Anda masih dapat memanggil tindakan OData dengan menggunakan metode Execute generik. Namun, Anda harus mengetahui jenis data parameter dan nilai yang dikembalikan.
Misalnya, RateProduct
tindakan mengambil parameter bernama "Peringkat" dari jenis Int32
dan mengembalikan double
. Kode berikut menunjukkan cara memanggil tindakan ini.
int rating = 2;
Uri actionUri = new Uri(uri, "Products(5)/RateProduct");
var averageRating = container.Execute<double>(
actionUri, "POST", true, new BodyOperationParameter("Rating", rating)).First();
Untuk informasi selengkapnya, lihatMemanggil Operasi dan Tindakan Layanan.
Salah satu opsinya adalah memperluas kelas Kontainer untuk menyediakan metode yang sangat diketik yang memanggil tindakan:
namespace ProductServiceClient.ProductService
{
public partial class Container
{
public double RateProduct(int productID, int rating)
{
Uri actionUri = new Uri(this.BaseUri,
String.Format("Products({0})/RateProduct", productID)
);
return this.Execute<double>(actionUri,
"POST", true, new BodyOperationParameter("Rating", rating)).First();
}
}
}