Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
tarafından Mike Wasson
Bu öğreticide, bir C# istemci uygulamasından OData hizmetinin nasıl çağrılacakları gösterilmektedir.
Öğreticide kullanılan yazılım sürümleri
- Visual Studio 2013 (Visual Studio 2012 ile çalışır)
- WCF Veri Hizmetleri İstemci Kitaplığı
- Web API 2. (Örnek OData hizmeti Web API 2 kullanılarak oluşturulur, ancak istemci uygulaması Web API'sine bağımlı değildir.)
Bu öğreticide, OData hizmetini çağıran bir istemci uygulaması oluşturma adımlarını inceleyeceğiz. OData hizmeti aşağıdaki varlıkları kullanıma sunar:
Product
Supplier
ProductRating
Aşağıdaki makalelerde, Web API'sinde OData hizmetinin nasıl uygulandığı açıklanmaktadır. (Ancak bu öğreticiyi anlamak için bunları okumanız gerekmez.)
- Web API 2'de OData Uç Noktası Oluşturma
- Web API 2'de OData Varlık İlişkileri
- Web API 2’de OData Eylemleri
Hizmet Ara Sunucusunu Oluşturma
İlk adım bir hizmet ara sunucusu oluşturmaktır. Hizmet ara sunucusu, OData hizmetine erişme yöntemlerini tanımlayan bir .NET sınıfıdır. Proxy, yöntem çağrılarını HTTP isteklerine çevirir.
Visual Studio'da OData hizmet projesini açarak başlayın. hizmeti IIS Express yerel olarak çalıştırmak için CTRL+F5 tuşlarına basın. Visual Studio tarafından atanan bağlantı noktası numarası da dahil olmak üzere yerel adresi not edin. Ara sunucuyu oluştururken bu adrese ihtiyacınız olacaktır.
Ardından, Visual Studio'nun başka bir örneğini açın ve bir konsol uygulaması projesi oluşturun. Konsol uygulaması OData istemci uygulamamız olacaktır. (Projeyi hizmetle aynı çözüme de ekleyebilirsiniz.)
Not
Kalan adımlar konsol projesine başvurur.
Çözüm Gezgini'da Başvurular'a sağ tıklayın ve Hizmet Başvurusu Ekle'yi seçin.
Hizmet Başvurusu Ekle iletişim kutusunda OData hizmetinin adresini yazın:
http://localhost:port/odata
burada bağlantı noktası , bağlantı noktası numarasıdır.
Ad alanı için "ProductService" yazın. Bu seçenek proxy sınıfının ad alanını tanımlar.
Git'e tıklayın. Visual Studio, hizmetteki varlıkları bulmak için OData meta veri belgesini okur.
Proxy sınıfını projenize eklemek için Tamam'a tıklayın.
Hizmet Ara Sunucusu Sınıfının Bir Örneğini Oluşturma
Yönteminizin Main
içinde aşağıdaki gibi proxy sınıfının yeni bir örneğini oluşturun:
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);
// ...
}
}
}
Yeniden, hizmetinizin çalıştığı gerçek bağlantı noktası numarasını kullanın. Hizmetinizi dağıtırken canlı hizmetin URI'sini kullanacaksınız. Proxy'yi güncelleştirmeniz gerekmez.
Aşağıdaki kod, konsol penceresine istek URI'lerini yazdıran bir olay işleyicisi ekler. Bu adım gerekli değildir, ancak her sorgunun URI'lerini görmek ilginçtir.
container.SendingRequest2 += (s, e) =>
{
Console.WriteLine("{0} {1}", e.RequestMessage.Method, e.RequestMessage.Url);
};
Hizmeti Sorgulama
Aşağıdaki kod, OData hizmetinden ürünlerin listesini alır.
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);
}
}
HTTP isteğini göndermek veya yanıtı ayrıştırmak için herhangi bir kod yazmanıza gerek olmadığını fark edin.
Foreach döngüsünde koleksiyonu numaralandırdığınızda Container.Products
proxy sınıfı bunu otomatik olarak yapar.
Uygulamayı çalıştırdığınızda çıkış aşağıdaki gibi görünmelidir:
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
Kimliğine göre varlık almak için yan where
tümcesi kullanın.
// 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);
}
}
Bu konunun geri kalanında yalnızca hizmeti çağırmak için gereken kodun tamamını Main
göstermeyeceğim.
Sorgu Seçeneklerini Uygula
OData, verileri filtrelemek, sıralamak, sayfaya eklemek vb. için kullanılabilecek sorgu seçeneklerini tanımlar. Hizmet proxy'sinde, çeşitli LINQ ifadelerini kullanarak bu seçenekleri uygulayabilirsiniz.
Bu bölümde kısa örnekler göstereceğim. Daha fazla ayrıntı için MSDN'de LINQ Ile İlgili Önemli Noktalar (WCF Veri Hizmetleri) konusuna bakın.
Filtreleme ($filter)
Filtrelemek için bir where
yan tümce kullanın. Aşağıdaki örnek, ürün kategorisine göre filtreler.
// 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);
}
}
Bu kod aşağıdaki OData sorgusuna karşılık gelir.
GET http://localhost/odata/Products()?$filter=Category eq 'apparel'
Proxy'nin yan tümcesini where
bir OData $filter
ifadesine dönüştürdüğüne dikkat edin.
Sıralama ($orderby)
Sıralamak için bir orderby
yan tümce kullanın. Aşağıdaki örnek, en yüksekten en düşüğe kadar fiyata göre sıralanır.
// 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);
}
}
İlgili OData isteği aşağıdadır.
GET http://localhost/odata/Products()?$orderby=Price desc
Client-Side Disk Belleği ($skip ve $top)
Büyük varlık kümeleri için istemci sonuç sayısını sınırlamak isteyebilir. Örneğin, bir istemci aynı anda 10 giriş gösterebilir. Buna istemci tarafı disk belleği adı verilir. (Sunucunun sonuç sayısını sınırladığı sunucu tarafı sayfalama da vardır.) İstemci tarafı disk belleği gerçekleştirmek için LINQ Skip ve Take yöntemlerini kullanın. Aşağıdaki örnek, ilk 40 sonucu atlar ve sonraki 10 sonucu alır.
// 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);
}
}
İlgili OData isteği aşağıdadır:
GET http://localhost/odata/Products()?$orderby=Price desc&$skip=40&$top=10
Seçin ($select) ve Genişlet ($expand)
İlgili varlıkları eklemek için yöntemini kullanın DataServiceQuery<t>.Expand
. Örneğin, her Product
için öğesini Supplier
eklemek için:
// 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);
}
}
İlgili OData isteği aşağıdadır:
GET http://localhost/odata/Products()?$expand=Supplier
Yanıtın şeklini değiştirmek için LINQ select yan tümcesini kullanın. Aşağıdaki örnek, diğer özellikler olmadan yalnızca her ürünün adını alır.
// 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);
}
}
İlgili OData isteği aşağıdadır:
GET http://localhost/odata/Products()?$select=Name
Select yan tümcesi ilgili varlıkları içerebilir. Bu durumda Genişlet'i çağırmayın; ara sunucu, bu durumda genişletmeyi otomatik olarak içerir. Aşağıdaki örnek, her ürünün adını ve sağlayıcısını alır.
// 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);
}
}
İlgili OData isteği aşağıdadır. $expand seçeneğini içerdiğine dikkat edin.
GET http://localhost/odata/Products()?$expand=Supplier&$select=Name,Supplier/Name
$select ve $expand hakkında daha fazla bilgi için bkz. Web API 2'de $select, $expand ve $value kullanma.
Yeni Varlık Ekle
Varlık kümesine yeni bir varlık eklemek için öğesini çağırın AddToEntitySet
. Burada EntitySet , varlık kümesinin adıdır. Örneğin, AddToProducts
varlık kümesine Products
yeni Product
bir ekler. Ara sunucuyu oluşturduğunuzda, WCF Veri Hizmetleri bu kesin türdeki AddTo yöntemlerini otomatik olarak oluşturur.
// 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);
}
}
İki varlık arasına bağlantı eklemek için AddLink ve SetLink yöntemlerini kullanın. Aşağıdaki kod yeni bir sağlayıcı ve yeni bir ürün ekler ve bunlar arasında bağlantılar oluşturur.
// 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);
}
}
Gezinti özelliği bir koleksiyon olduğunda AddLink kullanın. Bu örnekte, tedarikçideki Products
koleksiyona bir ürün ekliyoruz.
Gezinti özelliği tek bir varlık olduğunda SetLink kullanın. Bu örnekte, üründe Supplier
özelliğini ayarlıyoruz.
Güncelleştirme / Düzeltme Eki
Bir varlığı güncelleştirmek için UpdateObject yöntemini çağırın.
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);
}
}
Güncelleştirme , SaveChanges çağrısı yaptığınızda gerçekleştirilir. Varsayılan olarak, WCF bir HTTP MERGE isteği gönderir. PatchOnUpdate seçeneği WCF'ye bunun yerine HTTP PATCH göndermesini söyler.
Not
PATCH ve MERGE neden karşı karşıya? Özgün HTTP 1.1 belirtimi (RCF 2616), "kısmi güncelleştirme" semantiği ile hiçbir HTTP yöntemi tanımlamadı. Kısmi güncelleştirmeleri desteklemek için OData belirtimi MERGE yöntemini tanımlamıştı. 2010'da RFC 5789 , kısmi güncelleştirmeler için PATCH yöntemini tanımlamıştı. Bu blog gönderisindeki geçmişin bazılarını WCF Veri Hizmetleri Blog'da okuyabilirsiniz. Bugün, MERGE yerine PATCH tercih edilir. Web API iskelesi tarafından oluşturulan OData denetleyicisi her iki yöntemi de destekler.
Varlığın tamamını değiştirmek istiyorsanız (PUT semantiği), ReplaceOnUpdate seçeneğini belirtin. Bu, WCF'nin http PUT isteği göndermesine neden olur.
container.SaveChanges(SaveChangesOptions.ReplaceOnUpdate);
Varlığı Silme
Bir varlığı silmek için DeleteObject çağrısında bulunabilirsiniz.
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();
}
}
OData Eylemi Çağırma
OData'da eylemler , varlıklarda CRUD işlemleri olarak kolayca tanımlanmayan sunucu tarafı davranışları eklemenin bir yoludur.
OData meta veri belgesinde eylemler açıklansa da, ara sunucu sınıfı bunlar için kesin olarak türlenmiş yöntemler oluşturmaz. Yine de genel Execute yöntemini kullanarak bir OData eylemi çağırabilirsiniz. Ancak, parametrelerin veri türlerini ve dönüş değerini bilmeniz gerekir.
Örneğin, RateProduct
eylem türündeki Int32
"Derecelendirme" adlı parametreyi alır ve bir double
döndürür. Aşağıdaki kodda bu eylemin nasıl çağrıldığı gösterilmektedir.
int rating = 2;
Uri actionUri = new Uri(uri, "Products(5)/RateProduct");
var averageRating = container.Execute<double>(
actionUri, "POST", true, new BodyOperationParameter("Rating", rating)).First();
Daha fazla bilgi için bkz. Hizmet İşlemlerini ve Eylemlerini Çağırma.
Bir seçenek , Eylemi çağıran kesin olarak belirlenmiş bir yöntem sağlamak için Container sınıfını genişletmektir:
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();
}
}
}