https://www.buraksenyurt.com/Burak Selim Şenyurt - XML Web Services2023-04-06T12:24:43+00:00Matematik Mühendisi Bir Bilgisayar Programcısının NotlarıBurak Selim SenyurtBlogEngine.Net Syndication Generatorhttps://www.buraksenyurt.com/opml.axdBurak Selim SenyurtMatematik Mühendisi Bir Bilgisayar Programcısının Notlarıtr-TRBurak Selim Şenyurt0.0000000.000000https://www.buraksenyurt.com/post/bir-soap-web-servisini-proxy-olmadan-webclient-ile-cagirmakBir SOAP Web Servisini Proxy Olmadan WebClient ile Çağırmak2017-05-22T13:13:00+00:00bsenyurt<p>Merhaba Arkadaşlar,</p>
<p>Geçtiğimiz günlerde şirket dışı bir kurumun web servislerini çağırma ihtiyacımız oldu. Lakin Header bilgisinde bir OAuth Token değeri de göndermemiz gerekiyordu. Bu Header bilgisini SOAP bazlı Web servisine nasıl ekleyeceğimizi düşünürken WebClient sınıfı ile de bu işi yapabileceğimizi öğrendik. Üstelik çağrılacak servisin WSDL üretimi referansını projeye eklemeye gerek kalmadan. Bu kısa ipucunda WebClient sınıfının bu amaçla nasıl kullanıldığını incelemeye çalışacağız. Öncelikle eski nesil bir Asp.Net Web Service geliştirdiğimizi düşünelim. İçinde iki değerin toplamını hesap eden basit bir metod yer alacak. Servis kodunu aşağıdaki gibi geliştirebiliriz.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System.Web.Services;
namespace CalculateService
{
[WebService(Namespace = "http://azon.com/services/math")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Common
: System.Web.Services.WebService
{
[WebMethod]
public double Sum(double x,double y)
{
return x+y;
}
}
}</pre>
<p>Önemli olan nokta bu servis operasyonunu çağırmak için göndereceğimiz SOAP Header ve Body içerikleri. Yazılan servisin ilgili operasyonunu herhangibir tarayıcıdan çağırırsak bu içerikleri görebiliriz.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2017/02/wslook.gif" alt="" /></p>
<blockquote>
<p>Olur da kurumun web servisilerinin yardımcı bir ekran sayfası yoktur<em>(JAVA servisleri gibi)</em> ve sadece WSDL içeriğini görebiliyorsunuzdur, bu durumda SOAP UI gibi bir araçtan yararlaranak ilgili servisi çağırmak için kullanılacak SOAP Body ve Header içeriklerinin otomatik olarak üretilmesini sağlayabilir ve oradan destek alabilirsiniz. Dikkat edilmesi gereken nokta SOAPAction değeridir.</p>
</blockquote>
<p>Header bilgisinde servis operasyonunun adını<em>(SOAPAction bilgisi)</em>, HTTP'nin hangi metodu ile çağırım yapılması gerektiğini<em>(bu örnekte POST)</em>, kullanılması gereken SOAP versiyonunu<em>(bu örnekte 1.1)</em> gönderilecek içeriğin tipini<em>(text/xml; charset=utf-8)</em> bulabiliriz. Body kısmında yer alan string içeriği aynen kullanabiliriz. Sadece x ve y için gerekli sayısal değerleri vermemiz yeterlidir. Kodu basit bir Console uygulamasında aşağıdaki gibi deneyebiliriz.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Net;
using System.Text;
namespace CallWSWithWebClient
{
class Program
{
static void Main(string[] args)
{
string content = @"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope
xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body>
<Sum xmlns=""http://azon.com/services/math"">
<x>4</x>
<y>5</y>
</Sum>
</soap:Body>
</soap:Envelope>";
try
{
using (WebClient wClient = new WebClient())
{
wClient.Headers.Add("Content-Type", "text/xml; charset=utf-8");
wClient.Headers.Add("SOAPAction", "\"http://azon.com/services/math/Sum\"");
var result = wClient.UploadData("http://localhost:52523/Common.asmx"
, "POST"
, Encoding.UTF8.GetBytes(content));
var response = System.Text.Encoding.Default.GetString(result);
Console.WriteLine(response);
}
}
catch(WebException excp)
{
Console.WriteLine(excp.Message);
}
}
}
}</pre>
<p>WebClient sınıfını oluşturduktan sonra Content-Type ve SOAPAction bilgilerini Headers isimli WebHeaderCollection nesnesine eklemekteyiz. UploadData metodu ile Common.asmx servisine POST tekniğini kullanarak son parametre ile geçilen byte[] içeriğini yolluyoruz. Bu içerik aslında content ile belirtilen XML bilgisi. Bu noktada WebClient metodu hangi EndPoint'e hangi HTTP metodu ve içerik tipi ile veri göndereceğini biliyor. Eğer WebException üretilmesine neden olacak bir sorun yoksa gelen byte[] dizisi şeklindeki cevap ekrana basılıyor. Burada string olarak bir veri alımı söz konusu olsada gelen içerik aslında XML tabanlı. Yani XDocument<em>(XmlDocument) </em>gibi tipler yardımıyla daha kolay kullanılabilir. Nitekim daha fazla değer döndürecek sonuç kümelerinde string ile çağırmak çok da mantıklı değil<em>(Tabii içerik JSON dönüyorsa çok daha güzel olur)</em> Kodun çalışma zamanı çıktısı aşağıdaki gibidir.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2017/02/wsresult.gif" alt="" /></p>
<p>Gördülüğü gibi başarılı bir sonuç aldık. WebClient sınıfını ağırlıklı olarak REST tabanlı servisleri çağırmak için kullansak da örnekte görüldüğü gibi SOAP tabanlı servisler için de ele alabiliriz. Tekrar hatırlatmakta fayda var ki referans eklemeden bunu yapmamız mümkün. Eğer servis JSON içerik dönüyorsa sonuçları NewtonSoft'un JsonConvert sınıfından yararlanarak JObject olarak deserialize edebilir, servisin ihtiyaçlarına göre ekstra Header bilgilerini<em>(OAuth Token vb)</em> kolaylıkla gönderebiliriz. Böylece geldik ihtiyaç sonrası ortaya çıkan bir yazının daha sonuna. Tekrardan görüşünceye dek hepinize mutlu günler dilerim.</p>2017-05-22T13:13:00+00:00xml web servicessoap based web servicesoapsimple object access protocolWebClientposthttp postwebmethodsoapactionsoap headersbsenyurtGeçtiğimiz günlerde şirket dışı bir kurumun web servislerini çağırma ihtiyacımız oldu. Lakin Header bilgisinde bir OAuth Token değeri de geçmemiz gerekiyordu. Bu Header bilgisini SOAP bazlı Web servisine nasıl ekleyeceğimizi düşünürken WebClient sınıfı ile SOAP bazlı servisleri de çağırabileceğimizi öğrendim.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=2ffb0b94-2483-4210-9968-756013ed1dee4https://www.buraksenyurt.com/trackback.axd?id=2ffb0b94-2483-4210-9968-756013ed1deehttps://www.buraksenyurt.com/post/bir-soap-web-servisini-proxy-olmadan-webclient-ile-cagirmak#commenthttps://www.buraksenyurt.com/syndication.axd?post=2ffb0b94-2483-4210-9968-756013ed1deehttps://www.buraksenyurt.com/post/xml-web-service-paketlerini-yakalamakXML Web Service Paketlerini Yakalamak2016-03-30T23:00:00+00:00bsenyurt<p><img style="float: right;" src="https://www.buraksenyurt.com/image.axd?picture=/2016/04/wslog_0.gif" alt="" />Merhaba Arkadaşlar,</p>
<p>Yine karşımıza çıkan bir problem çözümü ile birlikteyiz. Öncelikle senaryomuzu anlatarak işe başlayalım. Şirket içerisinde kullanılan bir <strong>XML Web Service</strong>'in <strong>Oracle</strong> tarafındaki bir <strong>Stored Procedure</strong> içerisinden çağırılması gerekiyordu. Burada kullanılacak teknikten ziyade <strong>XML Web Service</strong>' e gidecek olan <strong>SOAP</strong> mesajının içeriği daha önemliydi. Nitekim giden örnek bir mesaj elimizde olduğu takdirde <strong>Stored Procedure</strong> tarafındaki <strong>string</strong> içeriğin<em>(SOAP XML yapısını ifade eden)</em> oluşturulması daha kolay olacaktı. Haliyle bizim <strong>XML Web Service</strong>'e istemci tarafından gönderilen mesaj içeriklerine ait örneklere ihtiyacımız vardı. Bunun için <strong>Fiddler</strong> gibi araçları da kullanabilirdik. Ama bilin bakalım ne var? Şirketteki bilgisayarlara bu tip araçları indirip kurmamız mümkün değil. Dolayısıyla kendi kodumuzu yazarak servise giden paketlerin içeriğini görmemiz gerekiyor. </p>
<p>Bir <strong>XML Web Service</strong>'e giden ve dönen <strong>SOAP</strong> içeriklerini görmek için kullanılabilecek bir kaç yol var. Bunlardan birisi de konfigurasyon tabanlı. Nasıl yapacağımızı basit bir örnek üzerinden inceleyelim. Öncelikle bir <strong>XML Web Service</strong>' e ihtiyacımız var. Boş bir<strong> Asp.Net</strong> uygulaması oluşturduktan sonra<em>(CommonWebService isimli bir uygulama olabilir)</em> <strong>Operations.asmx</strong> isimli bir <strong>Web Service</strong> ekleyerek devam edelim. </p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using System;
using System.Web.Services;
namespace CommonWebService
{
[WebService(Namespace = "http://www.buraksenyurt.com/services/common/road/operations")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Operations :
WebService
{
[WebMethod]
public double FindOptimalDuration(Location[] locations)
{
//Do Something
Random rnd=new Random();
return rnd.Next(1, 60);
}
}
}</pre>
<p>ve içeride kullandığımız <strong>Location</strong> tipi.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">namespace CommonWebService
{
public class Location
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
}
}</pre>
<p>Servisimiz içerisinde anlamsız bir operasyon var aslına bakarsanız. <strong>Location</strong> tipinden diziyi parametre olarak alan FindOptimalDuration metodu geriye güya en optimal yol süresini döndürüyor. Tabii bizim için önemli olan içerik alıp veren bir servis olması. </p>
<p>Çalışmamızın ikinci aşamasında ise bir istemciye ihtiyacımız var. Basit bir <strong>Console</strong> uygulaması bu aşamada işimizi görecektir. Kullandığımız servis eski stilde bir <strong>XML Web Service</strong>. Dolayısıyla istemci tarafına <strong>Add Service Reference</strong> seçeneği ile eklenirken aslında <strong>Add Web Reference</strong> kısmında ilerlememiz gerektiğini unutmamalıyız. Çünkü bir <strong>WCF Service söz</strong> konusu değil.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2016/04/wslog_1.gif" alt="" /></p>
<p>Sonrasında aynı <strong>Solution</strong> içerisindeki servisimizi ekleyerek ilerleyebiliriz.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2016/04/wslog_2.gif" alt="" /></p>
<p>İstemci tarafındaki kodlarımızı aşağıdaki şekilde yazmamız şu an için yeterli.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">using CommonWebClient.localhost;
using System;
namespace CommonWebClient
{
class Program
{
static void Main(string[] args)
{
Operations proxy = new Operations();
Location[] locations = new Location[3];
locations[0] = new Location { X = 10, Y = 10, Z = 10 };
locations[0] = new Location { X = 20, Y = 5, Z = 40 };
locations[0] = new Location { X = 30, Y = -10, Z = 50 };
var result=proxy.FindOptimalDuration(locations);
Console.WriteLine(result.ToString());
}
}
}</pre>
<p>İstemci tarafında servise bir çağrı gönderiyor ve sonucu ekrana basıyoruz. Yazının can alıcı kısmı ise <strong>app.config</strong> dosyasının içeriği. </p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="CommonWebClient.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<applicationSettings>
<CommonWebClient.Properties.Settings>
<setting name="CommonWebClient_localhost_Operations" serializeAs="String">
<value>http://localhost:51499/Operations.asmx</value>
</setting>
</CommonWebClient.Properties.Settings>
</applicationSettings>
<system.diagnostics>
<trace autoflush="true"/>
<sources>
<source name="System.Net">
<listeners>
<add name="TraceFile"/>
</listeners>
</source>
<source name="System.Net.Sockets">
<listeners>
<add name="TraceFile"/>
</listeners>
</source>
</sources>
<sharedListeners>
<add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener"
initializeData="service.log"/>
</sharedListeners>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.Sockets" value="Verbose"/>
</switches>
</system.diagnostics>
</configuration></pre>
<p>Önemli olan kısım <strong>system.diagnostics</strong> sekmesinin içeriği. Burada servis tarafı ile ilgili mesajlaşma trafiğini dinleyeceğimizi belirtiyoruz. Aslında soket haberleşmesini yakaladığımızı ifade edebiliriz. <strong>initilalizeData</strong> niteliğinin değerine göre istemci uygulama çalıştırıldığında exe'nin olduğu klasörde <strong>service.log</strong> isimli bir dosya oluşacaktır.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2016/04/wslog_3.gif" alt="" /></p>
<p>Dosya içeriğine baktığımızda ise soket giriş ve çıkışlarının olduğu gibi indirildiğini görebiliriz.</p>
<p><img src="https://www.buraksenyurt.com/image.axd?picture=/2016/04/wslog_5.gif" alt="" /></p>
<p>Burada <strong>XML</strong> mesajlarını okumak biraz zahmetli olabilir ancak sonuç itibariyle istediğimiz <strong>XML</strong> paketlerini yakalamış bulunuyoruz. Gidip gelen XML içerikleri aşağıdakine benzer olacaktır.</p>
<p>İstemciden çıkan SOAP içeriği</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<FindOptimalDuration xmlns="http://www.buraksenyurt.com/services/common/road/operations">
<locations>
<Location>
<X>10</X>
<Y>10</Y>
<Z>10</Z>
</Location>
<Location>
<X>20</X>
<Y>5</Y>
<Z>40</Z>
</Location>
<Location>
<X>30</X>
<Y>-10</Y>
<Z>50</Z>
</Location>
</locations>
</FindOptimalDuration>
</soap:Body>
</soap:Envelope></pre>
<p>Servisten istemciye gelen <strong>SOAP</strong> içeriği ise aşağıdaki gibidir.</p>
<pre class="brush:xml;auto-links:false;toolbar:false" contenteditable="false"><?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<FindOptimalDurationResponse xmlns="http://www.buraksenyurt.com/services/common/road/operations">
<FindOptimalDurationResult>52</FindOptimalDurationResult>
</FindOptimalDurationResponse>
</soap:Body>
</soap:Envelope></pre>
<p>Bu adımdan sonra artık elimizde <strong>Oracle</strong> tarafı için gerekli örnek bir <strong>SOAP</strong> içeriğinin oluştuğunu ifade edebiliriz. Dilerseniz üretilen <strong>log</strong> dosyasının daha insancıl okunabilmesi amacıyla bir kod parçası geliştirmeyi deneyebilirsiniz. Bu mümkün. Araştırın ve deneyin. Böylece geldik bir yazımızın daha sonuna. Tekardan görüşünceye dek hepinize mutlu günler dilerim.</p>2016-03-30T23:00:00+00:00xml web serviceloggingsoaptracec#xmlservicestackbsenyurtYine karşımıza çıkan bir problem çözümü ile birlikteyiz. Öncelikle senaryomuzu anlatarak işe başlayalım. Şirket içerisinde kullanılan bir XML Web Service'in Oracle tarafındaki bir Stored Procedure içerisinden çağırılması gerekiyordu. Burada kullanılacak teknikten ziyade XML Web Service' e gidecek olan SOAP mesajının içeriği daha önemliydi. Nitekim giden örnek bir mesaj elimizde olduğu takdirde Stored Procedure tarafındaki string içeriğin(SOAP XML yapısını ifade eden) oluşturulması daha kolay olacaktı. Haliyle bizim XML Web Service'e istemci tarafından gönderilen mesaj içeriklerine ait örneklere ihtiyacımız vardı. Bunun için Fiddler gibi araçları da kullanabilirdik. Ama bilin bakalım ne var? Şirketteki bilgisayarlara bu tip araçları indirip kurmamız mümkün değil. Dolayısıyla kendi kodumuzu yazarak servise giden paketlerin içeriğini görmemiz gerekiyor.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=41a82c2a-56a3-4500-aa9a-40469ac2df700https://www.buraksenyurt.com/trackback.axd?id=41a82c2a-56a3-4500-aa9a-40469ac2df70https://www.buraksenyurt.com/post/xml-web-service-paketlerini-yakalamak#commenthttps://www.buraksenyurt.com/syndication.axd?post=41a82c2a-56a3-4500-aa9a-40469ac2df70https://www.buraksenyurt.com/post/Web-Servislerinde-SoapHeader-ile-Ozellestirilmis-Dogrulama-bsenyurt-com-danWeb Servislerinde SoapHeader ile Özelleştirilmiş Doğrulama2007-01-10T12:00:00+00:00bsenyurt<p>Değerli Okurlarım Merhabalar,</p>
<p>Web servislerinde güvenlik söz konusu olduğunda, geliştiricileri en çok zorlayan noktalardan birisi görsel bir arabirimin olmayışıdır. Bu nedenle özellikle web tabanlı uygulamalarda tercih edilen form tabanlı (form-based) veya windows tabanlı (windows based) doğrulama (authentication) sistemlerini uygulamak biraz daha farklıdır. Biz bu makalemizde form tabanlı doğrulama ve yetkilendirme sistemininin iskeletini, web servisleri üzerinde nasıl geliştirebileceğimizi incelemeye çalışacağız.</p>
<p>Konuyu daha iyi anlamak için vakkamızı analiz edelim. Web servisi tarafında yer alan bazı metodların istemciler tarafından kullanılabilmesi için ilgili kullanıcıların doğrulanması gerektiğini düşünelim. Böyle bir durumda kullanıcıların ilgili web metod çağrılarından önce web servisi tarafından doğrulanması (authenticate) gerekecektir. Sırf bu amaç için tasarlanmış bir web metodu göz önüne alınabilir. Kullanıcıların login metodu ile doğrulanmasının en büyük amacı, iş yapan web metodlarına yapılacak olan çağrılarda tekrar tekrar doğrulama yapılmasının da önüne geçmektir. Peki bu nasıl sağlanabilir?</p>
<p>Eğer kullanıcının elinde bir <strong>güven belgesi (credential) </strong>olursa bu işlevsellik çok kolay bir şekilde sağlanabilir. Login metodu içerisinde hazırlanacak olan bu güven belgesini, web servisinin kendisine bağlanan istemcileri doğrulaması halinde vereceği bir bilet olarakta düşünebiliriz. Bilet bir kere oluşturulduktan sonra istemciye gönderilecektir. Bu noktadan sonra istemci uygulama,web servisi tarafından kendisine verilen bu bilet ile web metodlarını çağıracaktır. Böylece bir kere doğrulanan kullanıcının, bu işlemden sonra yapacağı çağrılarda tekrardan doğrulanmasına gerek kalmayacaktır. Bu elbette bilet bilgisi korunduğu sürece geçerli olacaktır. Istemci uygulamanın kapatılması ve tekrar başlatılması halinde, web servisi tarafından yeni bir biletin hazırlanması ve gönderilmesi gerekebilir.</p>
<p>Burada önemli olan bir sorun vardır. İstemciler için sunucu tarafında oluşturulan biletler, istemci uygulama ve web servisi arasında nasıl taşınacaktır? İşte burada web servisleri ile istemciler arasında hareket eden verinin taşındığı <strong>Soap zarfları (Soap Envelope)</strong> devreye girmektedir. Soap zarflarının iki önemli parçası vardır. Asıl verinin taşındığı <strong>gövde (Soap Body)</strong> kısmı ve paket ile birlikte taşınabilecek ekstra bilgilerin yer aldığı <strong>başlık (Soap Header)</strong> kısmı. Soap zarfının başlığında bilet bilgisini taşıyabiliriz. Böylece kullanıcı, web servisi tarafından ilk doğrulanışından sonra Soap paketindeki başlık bilgisi ile kendisine gelen bileti alabilir. Bundan sonra yapacağı web metodu çağrılarında ise kendisine verilen bileti yine web servisine Soap başlığında gönderecektir.</p>
<p>Şimdi gelin biraz daha teknik detaya inelim ve örnek bir uygulama üzerinden hareket ederek form tabanlı doğrulama iskeletini web servisleri için oluşturmaya çalışalım. Web servisi tarafında düşünmemiz gereken ilk konu kullanıcı bilgilerini nerede saklayacağımızdır. Kullanıcıların sistem tarafından tanınması için bazı bilgilerinin herhangibir depolama alanında saklanması gerekecektir. Bu amaçla .Net 2.0 ile birlikte gelen <strong>Membership API</strong>' sini kullanabiliriz yada kendi hazırlayacağımız veri saklama ambarlarını göz önüne alabiliriz. Bu ambarlar bir Access veritabanı hatta bir Xml dosyası bile olabilir. Ancak verilerin daha tutarlı ve güvenli bir şekilde saklanması amacıyla ilişkisel veritabanı (Relational Database Management System - RDMS) sistemlerinden birisi olması çok daha ölçeklenebilir çözümler elde etmemizi sağlayacaktır. Makalemize konu olan örneğimizde bu amaçla basit bir sql veritabanı dosyası kullanıyoruz.</p>
<p><img src="/makale/images/mk187_1.gif" alt="" width="225" height="238" border="0" /></p>
<p>Azondb.mdf veritabanı dosyamızın içerisinde şu an için tek bir tablo yer almaktadır. Kullanicilar isimli tablomuzun temel amacı, doğrulaması yapılacak olan üyelere ait bazı bilgileri saklamaktır. Örneğin kullanıcıların adı, mail adresi, şifresi gibi.</p>
<p><img src="/makale/images/mk187_2.gif" alt="" width="341" height="121" border="0" /></p>
<p>Tablomuzun veri yapısını oldukça basit düşünüyoruz. Nitekim odaklanmamız gereken nokta tablo yapılarından ziyade web servisi üzerinde güvenliği form tabanlı sistem kurallarına göre tasarlamak. Ama elbetteki rol yönetimininin (role management) var olduğu, şifrelerin de şifrelenerek (en azından Hash algoritması ile karıştırılarak) tutulduğu daha güçlü bir veri saklama ortamı düşünülebilir. Var olan Membership API' si buna en güzel örnektir.</p>
<p>Gelelim web servisi tarafımıza. Az öncede bahsettiğimiz gibi, form tabanlı doğrulama sisteminde iskeleti oluşturan önemli noktalar, kullanıcının sunucu tarafından doğrulanması (authentication), bir biletin oluşturulması ve bu biletin Soap başlığında istemciye gönderilmesidir. Öncelikle kullanıcı bilgilerinden bazılarını web metodları arasında bulmamızı sağlayacak bir sınıf tasarlayarak işe başlayalım.</p>
<p><img src="/makale/images/mk187_3.gif" alt="" width="282" height="250" border="0" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">public class Kullanici
{
private string _ad;
private string _email;
private string _biletNumarasi;
public string Ad
{
get { return _ad; }
}
public string Email
{
get { return _email; }
}
public string BiletNumarasi
{
get { return _biletNumarasi; }
}
public Kullanici(string kullaniciAdi,string email)
{
_ad = kullaniciAdi;
_email = email;
_biletNumarasi = Guid.NewGuid().ToString();
}
}</pre>
<p>Kullanici isimli sınıfın en can alıcı noktası bir <strong>Global Unique Identifier</strong> (GUID) değerini sunmasıdır. Bu değer Kullanici isimli sınıfa ait bir nesne örneklendiğinde yapıcı metod içerisinde oluşturulmaktadır. GUID değerleri web servisinin çalıştığı sistemde benzersiz olarak oluşturulduklarından, her kullanıcının ayrı ayrı ele alınmasını sağlayabiliriz. Örneğimizde, Kullanici sınıfına ait nesne örneklerini <strong>Application</strong> nesnesinde taşımayı tercih edeceğiz. Application nesnesi web servisi uygulaması içerisinde heryerden erişilebilir bir nesnedir.</p>
<p>Dolayısıyla web metodlarımız içerisinden Application nesnelerine çıkıp gelen bilet numarasına ait bir Kullanici nesne örneğinin olup olmadığını kontrol edebiliriz. Yani, doğrulanan kullanıcıları web servisi tarafından Application nesnesinde tutup, istemci ile Soap başlığından gelecek olan biletin numarasına göre kontrol edebiliriz. Böylece web metodları içerisinde eğer istemcideki bilet numarasının karşılığı olan bir kullanıcı var ise işlemlerin yapılmasını sağlayabiliriz. Ama öncesinde Soap zarfının başlığında taşınacak olan sınıfın tasarlanması gerekmektedir.</p>
<p><img src="/makale/images/mk187_4.gif" alt="" width="263" height="312" border="0" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">public class Bilet:System.Web.Services.Protocols.SoapHeader
{
private string _biletNumarasi;
public string BiletNumarasi
{
get { return _biletNumarasi; }
set { _biletNumarasi = value; }
}
public Bilet(string numara)
{
_biletNumarasi = numara;
}
public Bilet()
{
}
}</pre>
<p>Soap zarflarının başlık kısmında bilgi taşıyabilmenin yolu <strong>SoapHeader</strong> tipinden türetilmiş bir sınıf yazılmasıdır. Bu türetme sayesinde Bilet isimli sınıfa ait nesne örneklerini soap paketlerinde başlık kısmında taşıyabilme imkanına sahip oluruz. Olusturulan bu sınıf, web servisini referans eden istemci uygulamalarada gönderilecektir. Aynı zamanda Soap paketi içerisine serileştirilebilir olması gerekmektedir. Bu nedenlede <strong>varsayılan</strong> <strong>yapıcı metodu (default constructor)</strong> olmak zorundadır. Dikkat ederseniz başlıkta taşınacak olan bu sınıf sadece tek bir üye sunmaktadır. BiletNumarasi. Bilet isimli sınıfın BiletNumarasi isimli özelliğinin bir set bloğuna sahip olması önemlidir. Aksi halde istemci tarafındaki uygulama sisteme login olduktan sonra yapacağı çağrılarda bu bilgiyi tekrardan set edemez ve web servisi tarafına gönderemez. Gelelim web servisimiz içerisinde neler yapacağımıza.</p>
<p><img src="/makale/images/mk187_5.gif" alt="" width="309" height="211" border="0" /></p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class UrunServisi : System.Web.Services.WebService
{
public Bilet _bilet;
[WebMethod(Description="Kullanıcı bileti oluşturulmasını sağlar")]
[SoapHeader("_bilet", Direction=SoapHeaderDirection.Out)]
public void GirisYap(string kullaniciAdi, string sifre)
{
using(SqlConnection conn=new SqlConnection(@"data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|AzonDb.mdf;User Instance=true"))
{
SqlCommand cmd = new SqlCommand("Select KullaniciAdi,PostaAdresi From Kullanicilar Where KullaniciAdi=@KullaniciAdi and Sifre=@Sifre", conn);
cmd.Parameters.AddWithValue("@KullaniciAdi", kullaniciAdi.ToString());
cmd.Parameters.AddWithValue("@Sifre", sifre.ToString());
conn.Open();
SqlDataReader dr=cmd.ExecuteReader();
if (dr.Read())
{
Kullanici kln = new Kullanici(dr["KullaniciAdi"].ToString(), dr["PostaAdresi"].ToString());
Application[kln.BiletNumarasi] = kln;
_bilet = new Bilet(kln.BiletNumarasi);
}
else
throw new Exception("Geçersiz kullanıcı");
}
}
private Kullanici KullaniciDogrula(string biletNumarasi)
{
Kullanici kln = (Kullanici)Application[biletNumarasi];
if (kln != null)
return kln;
else
throw new Exception("Geçersiz bilet numarası");
}
[WebMethod(Description="Ortalama endeks hesaplamaları yapılır.")]
[SoapHeader("_bilet",Direction=SoapHeaderDirection.In)]
public double MaliyetHesapla(double parcaNo)
{
KullaniciDogrula(_bilet.BiletNumarasi);
return parcaNo*10;
}
public UrunServisi () {
}
}</pre>
<p>Web servisimiz içerisinde GirisYap isimli bir metodumuz bulunmaktadır. Bu aslında makalemizin başından beri belirttiğimiz, kullanıcların doğrulanması sağlayan login metodudur. Parametre olarak aldığı ve istemci uygulamadan gelen kullanıcı adı ve şifre bilgilerine göre doğrulama işlemini üstlenir. Yanlız metodun yaptığı iki önemli atama vardır. Birincisinde, Kullanici sınıfına ait bir nesne örneğinin oluşturulması ve üretilen GUID değerine göre <strong>Application</strong> nesnesine atanması söz konusudur.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">Kullanici kln = new Kullanici(dr["KullaniciAdi"].ToString(), dr["PostaAdresi"].ToString());
Application[kln.BiletNumarasi] = kln;</pre>
<p>Böylece kullanıcı eğer doğrulanırsa web servisi kendisine bağlı olan istemciye ait bilgilere <strong>Application</strong> nesnesi üzerinden bilet numarasini kullanarak erişebilecektir. İkincisinde ise, üretilen bilet numarasına göre Bilet sınıfından _bilet isimli nesne örneği oluşturulur.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">_bilet = new Bilet(kln.BiletNumarasi);</pre>
<p>Dikkat ederseniz Bilet isimli sınıfa ait bu nesne örneği Soap başlığında taşınmaktadır. Ancak dikkat edilmesi gereken bir nokta vardır. GirisYap isimli metod için belirtilen <strong>SoapHeader</strong> niteliği (attribute). Bu niteliğin ilk parametresi ile, metod içerisinde oluşturulan _bilet isimli nesne örneğinin Soap başlığında taşınacağı belirtmektedir. İkinci parametre ilede, bu bilginin web servisi tarafından istemciye gidecek olan soap paketlerindeki başlık içeriğine ekleneceği belirtilmektedir. Bu yönü belirlemek için <strong>SoapHeaderDirection</strong> enum sabitinden faydalanılmaktadır.</p>
<p>KullaniciDogrula isimli metodumuz sadece bu servis sınıfı içerisinde kullanılan bir üyedir. Dışarıyla bir bağlantısı olmadığından private olarak tanımlanmıştır. Görevi, metoda parametre olarak gelen bilet numarası değerine sahip bir <strong>Application</strong> değişkeninin olup olmadığını tespit etmektir. Eğer yoksa bir istisna nesnesi ortama, daha doğrusu istemci uygulamaya fırlatılır. Metodun geriye Kullanici sınıfı tipinden bir değer döndürmesinin tek nedeni, bu metodu kullanan web metodlarından, ilgili işlemi gerçekleştiren kullanıcıya ait bazı temel bilgilere ulaşılabilmesini sağlamaktır. Bu çoğunlukla o işlemi yapan kullanıcı için loglama yapılması istendiği durumlarda yada rolüne veya yetkisine göre ilgili işlemi yapabilip yapamayacağına karar verilmesi gibi durumlarda kullanılabilir.</p>
<p>Gelelim iş yapan web metodumuza. Metodun ne iş yaptığı çok önemli değil şu aşamada. Dikkat etmemiz gereken nokta, metodun hizmeti nasıl verdiği. MaliyetHesapla isimli metodumuzun da <strong>SoapHeader</strong> niteliği (attribute) tanımlanmıştır. GirisYap metodundakine göre tek fark yönüdür. Dikkat ederseniz <strong>SoapDirection.In</strong> değeri kullanılmaktadır. Bu, ilk parametrede belirtilen _bilet isimli nesne örneğinin, istemci uygulamadan web servisine gelecek olan Soap paketi içerisindeki başlık bilgisinde yer alacağını belirtir. Eğer kullanıcı bu metodu çağırmadan önce sisteme giriş yapmışsa elinde bir bilet numarası vardır ve Soap paketi ile bunu web servisindeki ilgili metoda ulaştırabilir. Metod içerisinde KullaniciDogrula isimli metod çağırılır ve eğer Application nesnesi üzerinden gelen bilet numarasına sahip bir nesne var ise söz konusu metod yürütülür. Ama böyle bir bilet numarası yoksa zaten istemciye KullaniciDogrula metodu içerisinden bir istisna fırlatılacaktır.</p>
<p>Artık istemci tarafında bir test uygulaması yazarak sistemi sınayabiliriz. Olayı daha basit düşünebilmek için bir Console uygulaması üzerinden hareket edeceğiz. Uygulamamıza öncelikle web servisimizin referansını eklememiz gerektiğini unutmayalım.</p>
<p><img src="/makale/images/mk187_6.gif" alt="" width="161" height="119" border="0" /></p>
<p>Web referansının eklenmesi ile birlikte istemci uygulama tarafında Soap başlığında taşınabilecek olan Bilet tipine ait bir sınıfta eklenecektir.</p>
<p><img src="/makale/images/mk187_7.gif" alt="" width="434" height="469" border="0" /></p>
<p>Dikkat ederseniz Bilet sınıfına ait nesne örneğini elde etmemizi sağlayan bir özellikte (property) UrunServisi isimli proxy sınıfımıza dahil edilmiştir. BiletValue özelliği Soap başlığında taşınan Bilet nesne örneğini okuyabilmemizi hatta atama yapabilmemizi sağlar. Bu kısa bakışın hemen ardından aşağıdaki kod satırlarını Console uygulamamızın Main metodu içerisine yazarak örneğimizi geliştirmeye devam edelim.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">static void Main(string[] args)
{
try
{
UrunWebSrv.UrunServisi urnSrv = new Istemci.UrunWebSrv.UrunServisi();
urnSrv.GirisYap("bsenyurt", "1234");
Console.WriteLine("Sistem tarafından verilen unique Id \n {0}",urnSrv.BiletValue.BiletNumarasi);
double sonuc=urnSrv.MaliyetHesapla(1000);
Console.WriteLine("Maliyet "+sonuc.ToString());
}
catch(Exception err)
{
Console.WriteLine(err.Message.ToString());
}
Console.ReadLine();
}</pre>
<p>Dikkat ederseniz MaliyetHesapla isimli web metodumuzu çalıştırmadan önce sisteme giriş yapıyoruz. Bunun için GirisYap metodunu çağırıyoruz. Örnek olması açısından Kullanicilar tablosunda bsenyurt isimli bir kullanci oluşturduk ve 1234 şifresini verdik. <em>( Şifrelerin bu şekilde açık olarak gitmesi ve hatta tabloda bu şekilde açık olarak saklanması elbette doğru değil. Burada gerekirse encryption mekanizmalarında faydalanılması çok daha güvenli bir sistem oluşturulmasını sağlayacaktır. Ancak böyle bir durumda istemci tarafındaki uygulamayıda bizim geliştirmemiz gerekecektir ki bu da web servisi kullanımını anlamsız kılmaktadır. Çözüm olarak Remoting tercih edilebilir yada WSE 3.0 ile birlikte gelen güvenlik sistemleri göz önüne alınabilir.) </em>Kullanıcı eğer web servisi tarafından doğrulanırsa, üretilen bilet numarasını servise ait nesne örneğinden BiletValue isimli özellik yardımıyla elde ebiliriz. Sonrasında ise MaliyetHesapla isimli metodumuzu çağırmaktayız. Uygulamamızı test ettiğimizde aşağıdakine benzer bir ekran görüntüsü elde ederiz.</p>
<p><img src="/makale/images/mk187_8.gif" alt="" width="317" height="83" border="0" /></p>
<p>Eğer programı bir kere daha çalıştırırsak farklı bir <strong>GUID</strong> değeri ile karşılaşırız. Aşağıdaki ekran çıktısında olduğu gibi.</p>
<p><img src="/makale/images/mk187_9.gif" alt="" width="319" height="92" border="0" /></p>
<p>Bu son derece doğaldır. Çünkü uygulama her çalıştığında Login metodu devreye girmekte ve kullanıcıyı bulup yeni bir GUID ürettirmektedir. Dolayısıyla söz konusu doğrulama sistemi uygulamanın açık olması halinde, birden fazla web metodu çağırıldığında daha efektif işleyecektir. Böyle bir durumda login olunduktan sonra üretilen GUID değeri, uygulamanın devamındaki tüm web metod çağırılarında aynı kalacaktır. Elbette sisteme giriş yapamayan bir kullanıcı ile karşılaşıldığında GirisYap metodu, istemci tarafına bir istisna fırlatacaktır. Örneğin var olmayan bir kullanıcı ile console uygulamamızı denediğimizde aşağıdaki gibi bir sonuçla karşılaşabiliriz.</p>
<p><img src="/makale/images/mk187_10.gif" alt="" width="643" height="92" border="0" /></p>
<p>Tasarlanan bu sistem her ne kadar kullanışlı görünsede bazı dezavantajları vardır. Herşeyden önce web servisinin çalıştığı sunucunun çökmesi halinde tüm Application nesneleri kaybolacaktır. Hatta çökmesi haricinde, web uygulamasının herhangibir nedenle yeniden başlatılması halinde de aynı durum söz konusudur. Buna sebep olarak yeniden derlemeyi<strong> (compiling)</strong> ya da yeniden dağıtmayı<strong> (publishing)</strong> gösterebiliriz. Dolayısıyla sisteme giriş yapan kullanıcı bilgilerini daha sağlam bir yerde saklamak isteyebiliriz.</p>
<p>Bu durumda Application nesnesi yerine belki bir veritabanı tablosu göz önüne alınabilir. Ayrıca performansı arttırmak amacıyla ara bellekleme <strong>(caching)</strong> tekniklerinden de yararlanılabilir. Sonuç itibariye bu iyileştirmeler yapılsada yapılmasada iskelet aynı kalmak zorundadır. Kullanıcıyı bir şekilde doğrulamak (authenticat) ve metod çağrılarından tekrar kullanıcı bilgisi istememek için bilet kullanmak akıllıca bir yoldur. Buna birde rol tabanlı yetkilendirme gibi özellikler eklendiğinde form tabanlı doğrulama sisteminin iskeleti tamamlanmış olacaktır. Bu makalemizde web servislerinde, soap üzerinden form tabanlı doğrulama sistemini nasıl gerçekleştirebileceğimizi incelemeye çalıştık. Böylece geldik bir makalemizin daha sonuna. Bir sonraki makalemizde görüşünceye dek hepinize mutlu günler dilerim.</p>2007-01-10T12:00:00+00:00xml web servicesxmlweb servicesoapsimple object access protocolbsenyurtWeb servislerinde güvenlik söz konusu olduğunda, geliştiricileri en çok zorlayan noktalardan birisi görsel bir arabirimin olmayışıdır. Bu nedenle özellikle web tabanlı uygulamalarda tercih edilen form tabanlı (form-based) veya windows tabanlı (windows based) doğrulama (authentication) sistemlerini uygulamak biraz daha farklıdır. Biz bu makalemizde form tabanlı doğrulama ve yetkilendirme sistemininin iskeletini, web servisleri üzerinde nasıl geliştirebileceğimizi incelemeye çalışacağız.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=93aab315-0334-4cc6-a88b-42bd5f13c4471https://www.buraksenyurt.com/trackback.axd?id=93aab315-0334-4cc6-a88b-42bd5f13c447https://www.buraksenyurt.com/post/Web-Servislerinde-SoapHeader-ile-Ozellestirilmis-Dogrulama-bsenyurt-com-dan#commenthttps://www.buraksenyurt.com/syndication.axd?post=93aab315-0334-4cc6-a88b-42bd5f13c447https://www.buraksenyurt.com/post/Xml-Web-Servislerinde-Etkili-Caching-Kullanc4b1mc4b1-bsenyurt-com-danXml Web Servislerinde Etkili Caching Kullanımı2006-07-28T12:00:00+00:00bsenyurt<p>Değerli Okurlarım Merhabalar,</p>
<p>Ön-bellekleme (Caching) işlemleri web uygulamaları için ne kadar önemli ise Xml Web Servisleri içinde aynı durum geçerlidir. Ön-bellekleme sistemi sayesinde web uygulamalarının kullanıcıya cevap verme sürelerinin kısaltılması hedeflenmiştir. Bu da doğal olarak uygulamanın performansını arttırıcı bir etkendir. Kaldıki istekler önbellekten (cache) karşılandığı için, arka tarafta yapılan pek çok süreç atlanmaktadır. Dolayısıyla database işlemleri gibi maliyeti yüksek olan süreçlerin belirli kriterlere göre çalıştırılması ve kullanıcının istediği sonuçların en hızlı şekilde verilebilmesi ön-bellekleme sisteminin getirilerinden sadece birisidir. Web servisleride, web uygulamaları gibi 80 numaralı port üzerinden hizmet verdiklerinden ön-bellekleme yetilerine sahiptir. Web uygulamarında kullanılan ön-bellekleme mantığı ile web servislerinde kullanılan birbirlerine oldukça yakındır. Ancak bir takım farklılıklarda mevcuttur.</p>
<p>Bildiğiniz gibi, web uygulamalarında ön-bellekleme (caching) sistemi <strong>Output Caching</strong> ve <strong>Data Caching</strong> olmak üzere iki ana kategoriye ayırlmaktadır. Bir web uygulamasında Output Caching sayfa bazında veya user control bazında kullanılabilir. Böylece bir web sayfasının tamamının yada onun küçük bir parçasının ön-bellekte tutulması sağlanabilir. Oysaki aynı durum Web Servislerinde biraz daha farklıdır. Nitekim, web servislerinin kullanıcı ile etkileşimde olan bir arayüzü bulunmamaktadır. Buda kontrol veya sayfa bazında ön-bellekleme işleminin yapılamayacağı anlamına gelmektedir. Bir web servisi söz konusu olduğunda ön belleğe (cache) alınabilecek olan içerik bu servise ait metodların döndüreceği sonuç kümelerinden başka bir şey olmayacaktır. Dolayısıla web servislerinde metod bazında ön-belleklemenin yapılabileceğini söyleyebiliriz. Bunun dışında, web uygulamlarında sıkça kullanılan <strong>Data Caching</strong> tekniği web servisleri içinde geçerlidir. Kaldıki Data Caching tekniğinde <strong>kesin yaşam süresi (absolute expire time), hareketli yaşam süresi (floating expire time), dosya veya tablo bağımlılığı (cache dependency)</strong> gibi seçeneklerde mevcuttur. Bu seçenekler bir web servisi içerisinde etkin bir şekilde uygulandığında kullanıcılara hızlı cevap verebilmenin dışında, var olan sistem kaynaklarınıda daha etkili kullanabilme olanaklarına sahip oluruz. Bir web metodun döndüreceği sonuç kümesini ön-belleğe taşımak için yapılması gereken, WebMethod niteliğini aşağıdaki gibi <strong>CacheDuration</strong> özelliği ile kullanmaktır.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">[WebMethod(CacheDuration = 180)]</pre>
<p>Bu niteliğin uygulandığı web metodun döndüreceği sonuçlar 180 saniye (3 dakika) süreyle ön bellekte tutulacaktır. Bu oldukça kullanışlı bir özelliktir. Ancak asıl dikkat edilmesi gereken nokta, parametre bağımlı dönüşlerin söz konusu olduğu web metodlarında ortaya çıkmaktadır. Nitekim web metodlarında parametreler söz konusu olduğundan parametre değerleri için ayrı ayrı ön-bellekleme işlemleri söz konusu olmaktadır. Örneğin, Sql Server 2005 üzerinde yer alan örnek AdventureWorks veritabanındanki Product tablosunun verilerini, ProductSubCategoryID değerine göre farklı veri kümeleri şeklinde sunabilecek bir web metodumuz olduğunu düşünelim. Normal bir web uygulamasında bu tip parametrik fonksiyonellikler söz konusu olduğunda genellikle <strong>OutputCache</strong> direktifinin <strong>VaryByParam</strong> niteliğinden faydalanılır. Oysaki web servisi metodlarında bu tarz bir kullanım söz konusu değildir. Web servisleri parametre bağımlı ön-bellekleme söz konusu olduğunda daha akılcı bir yaklaşım sergilyerek, metodun parametresine (parametrelerine) göre farklı ön-bellek alanları oluşturur. Böylece <strong>CacheDuration</strong> niteliği ile belirtilen ön-bellekleme süreleri içerisinde aynı parametrik değeri talep eden kulllanıcılar için ön-bellekte tutulan o parametreye ait görüntüler cevap olarak istemcilere gönderilir. Bunu daha iyi anlayabilmek için aşağıdaki kod parçasını göz önüne alalım.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">[WebMethod(Description = "Alt kategoriye göre ürünler", CacheDuration = 180)]
public DataSet GetProductsBySubCategory(int subCatId)
{
using (SqlConnection con = new SqlConnection("data source=manchester;database=AdventureWorks;integrated security=SSPI"))
{
SqlCommand cmd=new SqlCommand("Select ProductID,Name,ListPrice,Size,StandardCost,ProductSubCategoryID From Production.Product Where ProductSubCategoryID=@SubCatId",con);
cmd.Parameters.AddWithValue("@SubCatId",subCatId);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}
}</pre>
<p>Bu örnek web metodu, parametre olarak Product tablosundaki ProductSubCategoryID alanı için kullanılacak bir parametre almaktadır. Talep edilen içeriğin ön bellekte tutulma süresi 180 saniye (3 dakika) olarak belirtilmiştir. Şimdi bu metoda belirli aralıklar ile 4 farklı talep geldiğini düşünelim. İlk ve ikinci taleplerde sırasıyla subCatId parametresine 1 ve 5 değerlerinin aktarıldığını düşünelim. Yani iki farklı kullanıcı farklı zamanlarda belirtilen kategorilerdeki ürünleri çekmek istesin. İlk talep sonrasında, yukarıdaki web metodunda yer alan kodlar 1 değeri için çalıştırılacaktır. Yani SqlConnection bağlantısı açılacak, ilgili SqlCommand oluşturulup bir SqlDataAdapter yardımıyla sonuç kümesi bir DataSet nesnesine aktarılacak ve geriye döndürülerek kullanıcıya cevap verilecektir. İşte bu andan itibaren oluşturulan sonuç kümesi ön belleğede atılır ve 180 saniye süreyle burada tutulur. Dolayısıyla aynı subCatId değeri için bu 180 saniyelik zaman dilimi içerisinde gelecek olan herhanbir talep, yukarıdaki kodlar çalıştırılmadan ön-bellekte tutulan veri içeriğinden döndürülecektir. İkinci ve farklı bir subCatId değeri için gelen talep içinde aynı süreç söz konusu olacaktır ve ön-bellekte ayrı bir alan açılarak ve CacheDuration süresi içerisinde gelen taleplerin cevapları buradan karşılanacaktır. Aşağıdaki çizelgede bir zaman dilimi içerisinde iki farklı subCatId için gelen taleplerin ön-bellekleme sistemince nasıl ele alınacağı gösterilmeye çalışılmıştır.</p>
<p><img src="http://www.buraksenyurt.com/makale/images/mk169_1.gif" alt="" width="641" height="365" border="0" /></p>
<p>Özellikle parametre bağımlı ön-bellekleme işlemlerinde web servisleri için dikkat edilmesi gereken bir nokta vardır. Web servisi isteğimiz dışında parametre bağımlı ön-bellekleme yapmaktadır. Bu otomatik gelişim zaman zaman iyi sonuçlar versede bazı durumlarda kullanılmamalıdır. Otomatik karar sistemi özellikle verinin çok yüksek boyutlara erişmediği hallerde oldukça faydalı bir yöntemdir. Ancak veri kümesinin boyutunun büyük olması, ön-bellekte tutulan veri kümelerininde, gelen sayısız talep sonucu belleği inanılmaz derecede şişireceği anlamına gelir. Bellekteki bu artış bir süre sonra her nekadar fiziki disk üzerinden karşılanabilecek olsada, performansı olumsuz etkiliyen ve sistem kaynaklarını tketen bir etkendir. Böyle bir durumda ön-bellekleme sisteminin avantajı kaybedilip dezavantaja dönüşebilir. Sonuç itibariye bir orta yolda hareket etmek çok daha mantıklı olabilir. Bu orta yol özellike web servislerinde yukarıdaki gibi parametreye bağımlı sonuç kümeleri söz konusu olduğunda ele alınan bir desen (pattern) içermektedir. Bu desene göre, parametreye bağlı sonuç kümelerinin çekildiği asıl veri seti ön-bellekte tutulur. Kullanıcının talepte bulunduğu veri içeriği ise, ön-bellekte tutulan bu ortak veri setinden ayrıştırılarak çekilir. Bu, ön-bellekleme kapasitesini daha etkin kullanabilmemizi sağlarken, kullanıcının isteklerini birazda olsa hızlı karşılayabilecek bir model oluşturabilmemizi sağlar. Aşağıdaki şekil bu modeli özetlemeye çalışmaktadır.</p>
<p><img src="http://www.buraksenyurt.com/makale/images/mk169_4.gif" alt="" width="569" height="399" border="0" /></p>
<p>Mavi çizgiler 5 numaralı ID değeri için gelen ilk talepte yapılan işlemleri göstermektedir. Tüm Products seti veritabanından çekilerek ön-belleğe atılır. Sonrasında ise ön-bellekteki veri seti içerisinden, ProductSubCategoryID değeri 5 olan satırlar ayrıştırılarak Client 1 isimli istemciye gönderilir. Aynı ProductSubCategoryID değeri için gelecek ikinci talepte ise artık ön-bellekte tutulmakta olan veri seti içerisinden ayrıştırma işlemi yapılacaktır. Database' e tekrar gidilip veri çekme işlemi gerçekleştirilmemektedir. Bu elbette veri setinin ön-bellekte tutulduğu süre içerisinde bir talep geldiğinde geçerlidir. Aksi durumda yine veritabanından ver çekme ve ön-belleğe alma işlemi gerçekleştirilecektir.</p>
<p>Sözü geçen modelde <strong>Data Caching</strong> sistemi etkin olarak kullanılmaktadır. Şimdi yukarıdaki örnek senaryomuzu bu modele göre yazmaya çalışalım. Herşeyden önce Product tablosunun içeriğini ilk gelen talepten sonra belirli bir süre ön bellekte tutacak bir metod yazmamız gerekiyor. Bu metod web servisi içerisindeki diğer metodlara hizmet vereceğinden private olarak tanımlanabilir. Metodun içerisinde, web servisindeki ilgili metoda(metodlara) gelen talepler için ön bellekte Product tablosuna ait bir DataSet nesnesinin tutulup tutulmadığına bakacağız. Bu kontrol işlemi için <strong>Cache</strong> sınıfından yararlanabiliriz. Eğer DataSet nesnemiz ön bellekte ise, web metoduna gelen parametre bağımlı talep buradan karşılanacak. Aksine ilgili veri seti ön bellekte değil ise, önce oluşturulacak ardından ön-belleğe atılacak ve son olarak yine ilgili web metoduna işlenmesi için devredilecek. Aşağıdaki metodumuz bu işlemler için tasarlanmıştır.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">private DataSet GetProducts()
{
if (Context.Cache["Products"] != null)
{
return (DataSet)Context.Cache["Products"];
}
else
{
SqlDataAdapter da = new SqlDataAdapter("Select ProductID,Name,ListPrice,Size,StandardCost,ProductSubCategoryID From Production.Product", "data source=manchester;database=AdventureWorks;integrated security=SSPI");
DataSet ds = new DataSet();
da.Fill(ds);
Context.Cache.Insert("Products", ds, null, DateTime.Now.AddMinutes(5), TimeSpan.Zero);
return ds;
}
}</pre>
<p>Burada Data Caching yaparken Absolute Time tekniğini seçtik. Yani Products isimli, DataSet taşıyan Cache nesnemiz oluşturulup ön belleğe atıldıktan sonra 5 dakika süreyle burada tutulacaktır. Elbette sahip olunan verinin içeriğinin ne kadar sık değiştiğine göre bu süre geliştirici tarafından uzatılabilir yada kısaltılabilir. Örneğin çok sık değişmeyen Ülke - Şehir - İlçe gibi bir içerik sunan verilerde Cache süresi mümkün olduğunca uzatılabilir.</p>
<p>Cache nesnesini bir web servisi metodu içerisinde kullanabilmek için güncel talepleri taşıyan http içeriğini (HttpContext) ele almamız gerekmektedir. Bu içeriği <strong>Context</strong> nesnesi yardımıyla ele alabiliriz. Products isimli, içeriğinde DataSet nesne örneği taşıyan bir Cache nesnesinin tutulup tutulmadığını kontrol etmek için ve eğer böyle bir nesne yok ise bunu oluşturdukan sonra ön-belleğe Cache sınıfı yardımıyla ekleyebilmek için Context sınıfından yararlanıyoruz. Gelelim istemcilere hizmete verecek olan parametre bağımlı metodumuza. Bu metodun içeriğinide aşağıdaki gibi tasarlayabiliriz.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">[WebMethod(Description = "Alt kategoriye göre ürünler")]
public DataSet GetProductsBySubCategory(int subCatId)
{
DataSet dsResult = GetProducts().Copy();
foreach (DataRow currRow in dsResult.Tables[0].Rows)
{
if ((currRow["ProductSubCategoryID"].ToString() == "") || (currRow["ProductSubCategoryID"] == null) || (Convert.ToInt32(currRow ["ProductSubCategoryID"]) != subCatId))
currRow.Delete();
}
dsResult.AcceptChanges();
return dsResult;
}</pre>
<p>Buradaki ana fikir ön bellekte tutulan veri seti içerisinden, kullanıcının talep ettiği parametre değerine göre oluşacak yeni bir veri setini kullanıcıya göndermektir. Bunun için, ön-bellekten gelen DataSet yapısını bozmayacak şekilde ele alınmaktadır. Bu sebeptende öncelikle ilgili DataSet' in bir kopyası Copy metodu ile çıkartılır. Sonrasında elde edilen kopya içerisinde dolaşılmakta ve ProductSubCategoryID değeri boş veya null olanlar ile gelen subCatId değerine eşit olmayanlar 0 indisli DataTable içerisinden çıkartılmaktadır. Böylece kullanıcıya istediği veri setini göndermiş oluruz. Yukarıdaki tekniği kullandığınız takdirde eğer web servisini çalıştırır ve GetProductsBySubCategory metodunu yürütürseniz, uygulamayı debug ederken metodun çalıştırılması sonrasında dönecek olan veri setinin sadece parametre olarak gelen kategori bilgilerini içerdiğini kolayca tespit edebilirsiniz.</p>
<p><img src="http://www.buraksenyurt.com/makale/images/mk169_2.gif" alt="" width="639" height="407" border="0" /></p>
<p>Peki bu işlemlerin bize kazandırdığı avantalar nelerdir? Her şeyden önce farklı parametre değerleri için ön bellekte farklı veri seti görüntüleri oluşturmaktan kurtulmuş oluyoruz. Bu sayede ön belleğin optimize edilişinde önemli bir kazancımız olmaktadır. Diğer taraftan tüm parametre bağımlı talepler ön bellekteki aynı veri setini kullandığından, veri ayrıştırma işlemi için veritabanına gidiş gelişler de azaltılmaktadır. Bu gidiş gelişlerin (round-trips) azalması, web servisinin sql sunucusunu çok fazla süre ile meşgul etmesinin önlenmesi anlamına gelmektedir. Bu makalemizde web servislerinde uygulanan ön bellekleme tekniğine farklı bir açıdan bakmaya çalıştık. Böylece geldik bir makalemizin daha sonuna. Bir sonraki makalemizde görüşünceye dek hepinize mutlu günler dilerim.</p>
<p><a href="http://www.buraksenyurt.com/makale/images/AdventureServices.rar">Örnek Uygulama İçin Tıklayın.</a></p>
<p>Burak Selim ŞENYURT<br /><a href="mailto:selim(at)buraksenyurt.com">selim(at)buraksenyurt.com</a></p>2006-07-28T12:00:00+00:00xml web servicescachecachingcontext.cachebsenyurtÖn-bellekleme (Caching) işlemleri web uygulamaları için ne kadar önemli ise Xml Web Servisleri içinde aynı durum geçerlidir. Ön-bellekleme sistemi sayesinde web uygulamalarının kullanıcıya cevap verme sürelerinin kısaltılması hedeflenmiştir. Bu da doğal olarak uygulamanın performansını arttırıcı bir etkendir. Kaldıki istekler önbellekten (cache) karşılandığı için, arka tarafta yapılan pek çok süreç atlanmaktadır.https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=fd9b2acf-6d7b-433c-9428-27cbeb92543a0https://www.buraksenyurt.com/trackback.axd?id=fd9b2acf-6d7b-433c-9428-27cbeb92543ahttps://www.buraksenyurt.com/post/Xml-Web-Servislerinde-Etkili-Caching-Kullanc4b1mc4b1-bsenyurt-com-dan#commenthttps://www.buraksenyurt.com/syndication.axd?post=fd9b2acf-6d7b-433c-9428-27cbeb92543ahttps://www.buraksenyurt.com/post/Native-Web-Services-bsenyurt-com-danNative Web Services2006-05-22T12:00:00+00:00bsenyurt<p>Değerli Okurlarım Merhabalar,</p>
<p>Sql Server 2005 ile gelen etkili özelliklerden biriside, doğal xml web servisi (native xml web services) desteğinin bulunmasıdır. Sql Server 2000 sürümünde, web servisi desteğini sunabilmek için SqlXml 3.0 ve IIS' in sunucu sistemde mutlaka yüklü olması gerekmektedir. Bununla birlikte istemciler MDAC desteğine sahip olmalıdır. Oysaki Sql Server 2005 istemcilerden Http protokolüne göre gelecek SOAP uyumlu talepleri doğrudan işletebilecek şekilde tasarlanmıştır. Sistemde yer alan Http dinleyici (Http Listener), istemcilerden gelecek olan talepleri doğrudan Sql Server 2005 üzerindeki EndPoint' lere iletmektedir. Dolayısıyla sunucu sistem üzerine IIS bulunma zorunluluğu ortadan kaldırılmıştır.</p>
<p>Sql Server 2005, saklı yordamların (stored procedures) ve kullanıcı tanımlı fonksiyonların (User-defined Functions) http üzerinden SOAP uyumlu taleplere cevap verebilecek halde sunulmasını sağlar. Bunun içinde Http veya Tcp protokolüne göre çalışan EndPoint nesnelerinden yararlanır. Sql Server 2005, http üzerinden gelecek olan talepleri yine SOAP mesajları şeklinde cevaplandırdığından, istemci her hangibir platform veya sistem olabilir. Örneğin bir Unix sistemi yada Linux sistemi de Sql Server 2005 tarafından sununlan bu servisleri kullanabilir. Biz bu makalemizde adım adım Sql Server 2005 üzerinden web servisi hizmetini nasıl verebileceğimizi incelemeye çalışacağız. Sql Server 2005 üzerinden herhangibir saklı yordamı yada kullanıcı tanımlı fonksiyonu web servisi kuralları içerisinde sunmanın ve kullanmanın yolu aşağıdaki şekilde kısaca tasvir edilmeye çalışılmaktadır.</p>
<p><img src="/makale/images/mk162_4.gif" alt="" width="633" height="44" border="0" /></p>
<p>Buna göre ilk olarak web servisi üzerinden hizmet verecek saklı yordam yada fonksiyon hazırlanır. Hazırlanan bu fonksiyonun istemcilere cevap verebilmesi ve SOAP taleplerini uygun bir biçimde ele alabilmesi için bir EndPoint nesnesi hazırlanır. Daha sonra istemci uygulama ilgili EndPoint için proxy sınıfını oluşturur. Bildiğiniz gibi .Net ile geliştirilen web servislerini, isteci tarafındaki uygulamalarda kullanmanın yollarından birisi proxy nesnelerinden faydalanmaktır. Buna göre, tüketilmek (Consume) istenen web servisinin wsdl dökümanına göre istemci tarafında bir proxy sınıfı oluşturulur. Aynı durum, Sql Server 2005 üzerinden sunulan EndPoint nesneleri içinde geçerlidir. Tabi istenirse, proxy nesnesi yardımıyla değil SOAP taleplerini doğrudan oluşturacak ve cevapları değerlendirecek şekilde kodlama teknikleride kullanılabilir. Web servisinin kullanılabilmesi için gerekli adımların tamamlanmasının ardından son olarak Sql Server 2005 tarafındaki EndPoint tüketilerek kullanılır.</p>
<p>Bu kadar teorik bilgiden sonra dilerseniz örnek bir senaryo üzerinen hareket edelim. İlk olarak işe yarar bir saklı yordam (Stored Procedure) geliştireceğiz. Örnek olarak Sql Server 2005 ile standart olarak yüklenen AdventureWorks veritabanını kullanacağız. Aşağıdaki sql script ile Production isim alanındaki Product tablosundan liste fiyatı belirli bir değerin üstünde olan ürünlerin elde edilebildiği bir saklı yordam (stored procedure) oluşturulmaktadır.</p>
<pre class="brush:sql;auto-links:false;toolbar:false" contenteditable="false">USE AdventureWorks
GO
CREATE PROCEDURE ListeFiyatinaGoreUrunler
@ListPrice float
AS
BEGIN
SELECT
ProductID
, Name
, ProductNumber
, MakeFlag
, StandardCost
, ListPrice
, SafetyStockLevel
FROM Production.Product
WHERE (ListPrice > @ListPrice)
END
GO</pre>
<p>İstemcilerin bu saklı yordama http üzerinden talepte bulunup sonuçlarını alabilmelerini sağlamak için ise Sql Server 2005 üzerinde bir EndPoint oluşturmamız gerektiğinden daha öncesinde bahsetmiştik. Bu EndPoint nesnesini aşağıdaki scriptte görüldüğü gibi oluşturabiliriz. <em>( EndPoint nesneleride diğer çoğu veritabanı nesnesi gibi Drop ve Alter gibi komutlar ile birlikte kullanılabilmektedir. )</em></p>
<pre class="brush:sql;auto-links:false;toolbar:false" contenteditable="false">USE AdventureWorks
GO
CREATE ENDPOINT ListeFiyatinaGoreUrunlerEndPoint
STATE = STARTED
AS HTTP ( path = '/sql/ListeFiyatinaGoreUrunler', AUTHENTICATION = (INTEGRATED), PORTS = (CLEAR) )
FOR SOAP(
WEBMETHOD 'ListeFiyatinaGoreUrunler' (NAME = 'AdventureWorks.dbo.ListeFiyatinaGoreUrunler',SCHEMA = STANDARD),
BATCHES = ENABLED,
WSDL = DEFAULT,
SCHEMA = STANDARD,
DATABASE = 'AdventureWorks',
NAMESPACE = 'http://tempUri.org/'
)
GO</pre>
<p>Böylece sistemde http üzerinden ListeFiyatinaGoreUrunler saklı yordamına (stored procedure) gelecek talepleri karşılayacak bir EndPoint nesnesi oluşturmuş oluyoruz. Artık istemciler bu EndPoint' i http veya tcp üzerinden çağırıp sonuçlarını alabilirler.</p>
<table id="table61" style="border-collapse: collapse; width: 100%;" border="1" cellspacing="0" cellpadding="5" bgcolor="#ffffff">
<tbody>
<tr>
<td width="53"><img src="/makale/images/dikkat.gif" alt="" width="53" height="53" border="0" /></td>
<td><em>Windows XP Service Pack 2 yüklü bir sistemde çalışıyorsanız eğer, EndPoint nesnesini oluşturbilmek için World Wide Web Publishing servisini bu işlem sırasında <span style="text-decoration: underline;">durdurmamız gerekebilir. Windows 2003 sistemlerinde ise buna gerek yoktur.</span></em></td>
</tr>
</tbody>
</table>
<p><br />Geliştirdiğimiz ListeFiyatinaGoreUrunlerEndPoint adlı nesneyi ve Sql Server 2005 üzerinde kayıtlı diğer EndPoint' leri görmek için http_endpoints tablosundan yararlanabiliriz. Bu sistem tablosu EndPoint' lere ait tüm bilgileri taşımaktadır.</p>
<p><img src="/makale/images/mk162_2.gif" alt="" width="608" height="111" border="0" /></p>
<p>EndPoint nesnesi oluşturulurken pek çok anahtar kelime kullanılmaktadır. Temel amaç EndPoint nesnesinin hangi saklı yordamı yada fonksiyonu, hangi iletişim protokolüne göre sunacağını belirlemek ve diğer konfigurasyon ayarlarını yapmaktır. Bu anahtar kelimeler hakkında birazda olsa bilgi vermekte fayda olacağı kanısındayım.</p>
<table id="table62" style="border-collapse: collapse; width: 100%;" border="1" cellpadding="5" bgcolor="#ffffff">
<tbody>
<tr>
<td style="width: 114px; background-color: #ffffff;" bgcolor="#336699" width="114"><strong> Anahtar Sözcük</strong></td>
<td style="width: 114px; background-color: #ffffff;" bgcolor="#336699"><strong> İşlevi</strong></td>
</tr>
<tr>
<td width="114">State</td>
<td>EndPoint için başlangıç durumunu belirtir. Started, Stoped veya Disabled olabilir. Eğer Stoped olarak ayarlanırsa, EndPoint' e erişmek isteyen istemciler bir çalışma zamanı istisnası alırlar. Disabled olması halinde ise EndPoint sistemde kalmaya ancak gelen taleplere cevap vermemeye başalayacaktır.</td>
</tr>
<tr>
<td width="114">Http / Tcp</td>
<td>Bu kısımda iletişim protokolü tanımlanır ve bu protokol üzerinden gerekli konfigurasyon ayarları belirlenir. Http dışında tcp üzerindende servis verilebilmektedir.</td>
</tr>
<tr>
<td width="114">Path</td>
<td>EndPoint için gerekli URL bilgisini tanımlar.</td>
</tr>
<tr>
<td width="114">Authentication</td>
<td>İstemciler için güvenlik doğrulama modelini belirler. Basic, Digets, Ntlm, Kerberos, Integrated modlarından birisi olabilir.</td>
</tr>
<tr>
<td width="114">Ports</td>
<td>Clear olması halinde http portu üzerinden hizmet verilmesini sağlar. SSL olması halinde ise https üzerinden hizmet verilir.</td>
</tr>
<tr>
<td width="114">Site</td>
<td>Servisin host edildiği bilgisayarın adıdır.</td>
</tr>
<tr>
<td width="114">Soap</td>
<td>Bu kısımda SOAP mesajına yönelik tanımlamalar yapılır ve servisin SOAP protokolünü kullanacağı belirtilir.</td>
</tr>
<tr>
<td width="114">WebMethod</td>
<td>Saklı yordamın yada kullanıcı tanımlı fonksiyonumuzun istemciler tarafından kullanılabilmesi için gerekli metod adı tanımlamasıdır.</td>
</tr>
<tr>
<td width="114">Wsdl</td>
<td>Wsdl desteğini belirtir.</td>
</tr>
<tr>
<td width="114">Database</td>
<td>EndPoint' in yer aldığı veritabanı adını belirtir.</td>
</tr>
<tr>
<td width="114">Namespace</td>
<td>SOAP mesajları için gerekli xml isim alanını (xml namespace) tanımlar.</td>
</tr>
</tbody>
</table>
<p><br />Artık EndPoint' imiz hazır olduğuna göre bunu herhangibir istemci uygulama üzerinde test edebiliriz. Ancak teste başlamadan önce basit olarak EndPoint' in çalışıp çalışmadığını kontrol edebiliriz. Yazdığımız EndPoint' in kontrol işlemi için tarayıcı penceresinde, http://localhost/sql/ListeFiyatinaGoreUrunler?wsdl bilgisini yazmamız yeterlidir. Eğer aşağıdaki ekran görüntüsünde olduğu gibi wsdl dökümanına ulaşabiliyorsak EndPoint' imiz başarılı bir şekilde çalışıyor demektir.</p>
<p><img src="/makale/images/mk162_3.gif" alt="" width="633" height="359" border="0" /></p>
<p>Şimdi bu hizmeti gerçek bir .Net uygulamasında nasıl kullanacağımızı incelemeye çalışalım. Web servisi hizmetini hangi tip istemcide sunacağımıza bakmaksızın dikkat etmemiz gereken önemli bir nokta vardır. Yukarıdaki saklı yordamda (stored procedure) olduğu gibi geriye bir sonuç kümesi dönüyorsa, EndPoint bunu bir object dizisi şeklinde döndürecektir. Bu yüzden EndPoint üzerinden gelen veriyi taşıyan DataSet nesnesini bu object dizisi içerisinde yakalayıp almamız gerekmektedir. Biz örnek olarak bir Windows Uygulamasını ele alacağız. İlk olarak servisimizi uygulamamıza Add Web Reference tekniğine göre tanıtmamız gerekiyor.</p>
<p><img src="/makale/images/mk162_5.gif" alt="" width="587" height="322" border="0" /></p>
<p>Bu işlemin ardından solution explorer' a bakacak olursak, web servisinin, proxy sınıfının ve wsdl dökümanının da eklenmiş olduğunu görürüz.</p>
<p><img src="/makale/images/mk162_6.gif" alt="" width="240" height="99" border="0" /></p>
<p>Uygulama kodumuz ise aşağıdaki gibidir.</p>
<pre class="brush:csharp;auto-links:false;toolbar:false" contenteditable="false">private void button1_Click(object sender, EventArgs e)
{
UrunServis.ListeFiyatinaGoreUrunlerEndPoint srv = new UrunServis.ListeFiyatinaGoreUrunlerEndPoint();
srv.Credentials = System.Net.CredentialCache.DefaultCredentials;
object[] sonuclar = srv.ListeFiyatinaGoreUrunler(Convert.ToDouble(txtFiyat.Text));
foreach (object guncelNesne in sonuclar)
{
if (guncelNesne.GetType().ToString() == "System.Data.DataSet")
grdUrunler.DataSource = ((DataSet)guncelNesne).Tables[0];
}
}</pre>
<p>UrunServis referansı içerisinde yer alan ListeFiyatinaGoreUrunlerEndPoint servisine erişirken istemcinin aynı domain içerisinde olduğunu düşünerekten DefaultCredential uygulanmıştır. Nitekim EndPoint tanımlamamızda, authentication modu olaraktanda integrated seçeneğini kullanmıştık. Diğer taraftan normal web servislerinin kullanımında web metodlarının dönüş tipi ne ise, proxy nesneleri üzerinden de aynı tipi alabilmekteyiz. Oysaki burada geriye object tipinden bir dizi dönmektedir. Bu dizinin elemanlarına çalışma zamanında Visualizer yardımıyla bakacak olursak aşağıdaki şekildende görebileceğiniz gibi bir DataSet nesnesinin de var olduğunu görürüz.</p>
<p><img src="/makale/images/mk162_8.gif" alt="" width="600" height="390" border="0" /></p>
<p>Dolayısıyla kodumuz içerisinde object dizisinin elemanları arasında dolaşıp tipinin string karşılığı, DataSet' in Framework içerisindeki tam adına eş düşen System.Data.DataSet ile karşılaştırılması gerekmektedir. Bu tespit yapıldıktan sonra, güncel object dizi elemanı DataSet tipine dönüştürülerek veri kaynağı olarak kullanılmış ve form üzerindeki gridView kontrolüne bu veri kümesi içerisindeki 0 indeksli DataTable bağlanmıştır. Uygulamamızı çalıştırdığımızda , Sql Server 2005 üzerinden EndPoint' imize başarılı bir şekilde erişebildiğimizi görürüz.</p>
<p><img src="/makale/images/mk162_7.gif" alt="" width="651" height="273" border="0" /></p>
<p>Görüldüğü gibi artık Sql Server 2005 üzerinde saklı yordam (stored procedure) yada kullanıcı tanımlı fonksiyonları (user defined functions), http istemcilerine hizmet verecek şekilde web servisi olarak sunmak oldukça kolaydır. Tek yapmamız gereken EndPoint nesnelerini hazırlamak ve istemcilerde tüketmek olacaktır. Böylece geldik bir makalemizin daha sonuna. Bir sonraki makalemizde görüşünceye dek hepinize mutlu günler dilerim.</p>2006-05-22T12:00:00+00:00sql 2005native web servicexml web servicebsenyurtSql Server 2005 ile gelen etkili özelliklerden biriside, doğal xml web servisi (native xml web services) desteğinin bulunmasıdır. Sql Server 2000 sürümünde, web servisi desteğini sunabilmek için SqlXml 3.0 ve IIS' in sunucu sistemde mutlaka yüklü olması gerekmektedir. Bununla birlikte istemciler MDAC desteğine sahip olmalıdır...https://www.buraksenyurt.com/pingback.axdhttps://www.buraksenyurt.com/post.aspx?id=2882a4c6-09ed-4f30-8c56-da5ad5d6af270https://www.buraksenyurt.com/trackback.axd?id=2882a4c6-09ed-4f30-8c56-da5ad5d6af27https://www.buraksenyurt.com/post/Native-Web-Services-bsenyurt-com-dan#commenthttps://www.buraksenyurt.com/syndication.axd?post=2882a4c6-09ed-4f30-8c56-da5ad5d6af27