WINDOWS COMMUNICATION FOUNDATION (WCF)
WCF, temel olarak COM+, .Net Remoting, XML Web Servisleri, MSMQ gibi
Servislerin yeteneklerini bünyesinde barındıran ve tam SOA (Service Oriented Architecture – Servis Yönelimli Mimari) desteği sağlayan güçlü bir Framework API si olarak tanımlanabilir
WCF ABC si
Address:Servisimiz internet/intranet vs… hangi adreste bulunmakta
- Bilgisayarın adı,
- Site adı,
- Network adı,
- İletişim portu adı,
- Pipe adı,
- Queue adı,
- Belirli bir path bilgisi,
- URI adı
Binding:Protokoller(Servisimizle hangi protokolle veri işlemleri yapılacak)
- HTTP,
- TCP,
- P2P (Peer To Peer),
- IPC (Inter-Process Communication),
- MSMQ (Microsoft Message Queuing),
Binding Tipi | Konfigurasyon Elementi |
Taşıma Çeşidi (Transport Type) |
Veri Çözümlemesi (Data Encoding) |
Platform Desteği (Inter operability) |
BasicHttpBinding | <basicHttpBinding> | HTTP / HTTPS | Text | Var |
NetTcpBinding | <netTcpBinding> | TCP | Binary | Yok |
NetPeerTcpBinding | <netPeerTcpBinding> | P2P | Binary | Yok |
NetNamedPipeBinding | <netNamedPipeBinding> | IPC | Binary | Yok |
WSHttpBinding | <wsHttpBinding> | HTTP/HTTPS | Text/MTOM | Var |
WSFederationBinding | <wsFederationHttpBinding> | HTTP/HTTPS | Text/MTOM | Var |
NetMsmqBinding | <netMsmqBinding> | MSMQ | Binary | Yok |
MsmqIntegrationBinding | <msmqIntegrationBinding> | MSMQ | Binary | Var |
WSDualHttpBinding | <wsDualHttpBinding> | HTTP | Text/MTOM | Var |
MTOM: (Message Transimision Optimization Mechanism)
istemci(Client) ve servisler(Service) arasında resim, ses, video gibi yüksek boyutlu içeriklere sahip olabilecek verilerin taşınması amacıyla çoğunlukla MTOM(Message Transimision Optimization Mechanism) standardını kullanırlar. WC3 tarafından kabul edilmiş bu standarda göre ikili(binary) formattaki verilerin aktarılması daha performanslıdır
Detaylı kullanımı: http://www.buraksenyurt.com/2007/11/default.asp
BasicHttpBinding:http protokolunu kullanır.SOAP 1.1
Örnek adresi: http://localhost:8000/DMSServices/FaturaService
http://msdn.microsoft.com/en-us/library/ms731361.aspx
NetTcpBinding:Genelde intranet kullanımları için uygun mesajlar tcp protokolü üstünden gidiyor
Örnek adresi:net.tcp://localhost:8080/DMSServices/FaturaService
http://msdn.microsoft.com/en-us/library/ms731343.aspx
WSHttpBinding:BasicHttpBinding benzer ama transaction,WS-Addressing,Güvenli mesajlaşma gibi özellikleride var.Http protokolünü kullanır.SOAP 1.2 desteği.BasicHttpBinding daha hızlı ama daha az güvenli
BasicHttpBinding transport sevisiyesinde sadece ssl güvenliği
WSHttpBinding:SSL ve WS Security
WS –Addressing ve WS-Security belli standartlar ve specifikasyonlar(end pointler arası mesajların güvenlik vs için)
Contract:Servisin ne iş yaptığını belirtir(Kısaca neyi nasıl vereceksin neyi nasıl alacaksın)
- Service Contract:Servis Üzerinden hangi işlemler yapılabilir
- Data Contract: Servislerden istemcilere giden ve istemcilerden servise gelen veri tiplerini tanımlayan sözleşme çeşididir
- Fault Contract: Servis tarafından hangi hataların fırlatılabileceğini ve bunların istemciye nasıl aktarılacağını tanımlayan sözleşme çeşididir
WCF İçin Hosting Şekilleri
IIS Hosting:WCF Servisleri web üzerinden hizmet verebilir
Self Hosting
- Windows Activation Service:Vistadan itibaren var,http desteği olmayan host uygulamaları için iis benzeri yapı
- Windows Application
- Console Application
- Windows Service
WCF için Projemizi Create Edelim
1-)Öncelikle Hangi Verilerimizi vereceğimizi ve ve bu verilerimizin modellemesini yapalım
Bunun için projemize Yeni bir ClassLibrary ekleyerek ,referanslardan system.runtime.serialization namespaceini ekliyoruz(DataContract attribute kullanabilmek için).Bu Library aşağıdaki gibi bir class ekleyelim
DataContract:Service ile Client arasında gidip gelecek dataların tanımlanmasıdır
DataContract Attribute hangi veri modelimiz serviste kullanılacaksa bu model classın üstüne eklenmeli
DataMember ise o veri model classında bulunan propertilerimizden hangileri servise açık olacak bunu belirtiyoruz.Data Member Attribute unu field ve propertlerin üstlerine eklememiz gerekiyor
namespace EntityClasses
{
[DataContract]
public class PersonEntity
{
[DataMember]
public int PersonID { get; set;}
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
}
}
Not:
Bu tarz nesne modellemesi yaparken POCO mantığında yapmak faydalı olabilir.POCO (Plain Old CLR Object):Yani kısaca bu mantıktaki nesneler herhangi bir sınıftan türemeyen,herhangi bir interface implemente etmeden verileri olabildiğince en sade halde tutmaktır.Yani orm vs… oluşturulan classlardan ziyade daha basit bir model oluşturmak amaçtır.Tabi internette poco modeli kullanmakla ilgili farklı görüşler var,extra bu şekil kod yazmak vs… gibi
2-)Data Sonra Servisimizde hangi metodlar dışarıya açılacak bunu belirtiyoruz
Bunun içinde projemize bir class library daha ekleyerek ismine BusinessService diyelim
1 maddedeki entity modellerimizi kullanmak için EntityClasses Library referanslardan proje referansı olarak ekliyoruz.Ayrıca ServiceContract Attribute kullanabilmek içinde System.ServiceModel dll projeye referans olarak eklenmesi gerekiyor.
Service Contract sınıfımız servis sözleşmesinde olacağı
Operation Contract ile de hangi metodlarımızın servis sözleşmesinde kullanılabileceğini belirtiyoruz.GetPersonByID metodu OperationContract ile tanımlanmadığı için Clientlar bu metodu kullanamayacaklardır.
[ServiceContract]
interface IPersonService
{
[OperationContract]
List<PersonEntity> GetAllPerson();
[OperationContract]
List<PersonEntity> GetPersonByAge(int Age);
List<PersonEntity> GetPersonByID(int ID);
}
Ben database bağlantısı yapmayacağım için kodda PersonPool diye bir class atıp aşağıdaki gibi bir liste oluşturdum
public List<PersonEntity> Persons()
{
PersonEntity Person1 = new PersonEntity { PersonID = 1, Name = “Bilgehan Yıldız”, Age = 24 };
PersonEntity Person2 = new PersonEntity { PersonID = 2, Name = “Tahir Çakmak”, Age = 24 };
PersonEntity Person3 = new PersonEntity { PersonID = 3, Name = “Tayfun Taşkın”, Age = 25 };
PersonEntity Person4 = new PersonEntity { PersonID = 4, Name = “Yasin Türk”, Age = 21 };
List<PersonEntity> PersonList = new List<PersonEntity>();
PersonList.Add(Person1);
PersonList.Add(Person2);
PersonList.Add(Person3);
PersonList.Add(Person4);
return PersonList;
}
Yukarıda yazılan interfacemizi kullanacak bir tane PersonService oluşturuyoruz.
public class PersonService:IPersonService
{
#region IPersonService Members
PersonPool plist = new PersonPool();
public List<EntityClasses.PersonEntity> GetAllPerson()
{
return plist.Persons();
}
public List<EntityClasses.PersonEntity> GetPersonByAge(int Age)
{
return plist.Persons().Where(c => c.Age == Age).ToList<PersonEntity>();
}
public List<EntityClasses.PersonEntity> GetPersonByID(int ID)
{
return plist.Persons().Where(c => c.PersonID == ID).ToList<PersonEntity>();
}
#endregion
}
3-)Hangi verilerimizi ve hangi metotlarla verceğimizi belirttik artık servisimizi host etmek için bir tane projemize Console uygulaması ekliyoruz.
Servisimizin host ayarlarını app confige yazıyoruz servisi ilk etapta ayağa kaldırmak için aşağıdaki config dosyasında yazanlar yeterlidir.Ama güvenlik,session yönetimi,debug trace gibi işlemler için config dosyasını daha farklı tagların eklenmesi gerekiyor.
<?xml version=”1.0″ encoding=”utf-8″ ?>
<configuration>
<!–WCF konfigurasyonları için gereken ayarlar bu tag ile başlar–>
<system.serviceModel>
<!–End point ayarları bu taga yazılır–>
<behaviors>
<!– Servisimiz davranışlarını belirtiyoruz.Yani debug açık olacak mı,metadata desteği verecek mi vs..–>
<serviceBehaviors>
<behavior name=”SimpleServiceBehavior”>
<!–Http protokolü üzerinden GET yönetimi kullanılarak meta verinin sorgulanıp sorgulanamayacağını belirlemektedir. Bu davranışı eklemeniz ardından hizmetinize bağlanmak üzere vekil sınıflar üretmek isteyen bir yazılımcı hizmet adresinizin sonuna ?WSDL ekleyerek hizmet şemanıza erişebilir –>
<serviceMetadata httpGetEnabled=”True” />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<!–Service name hangi servis contractının adını alacak ise onun tam adını vermemiz gerekiyor(NameSpace.ClassName–>
<!–Behaviour Configurationa isim verip behaviour tagında eklediğimiz özellikleri alır bunu vermezsek veya boş verirsek default ayarlar geçerli olur–>
<service name=”BusinessService.PersonService” behaviorConfiguration=”SimpleServiceBehavior”>
<!–Servisin ana çağıralacağı yeri belirtir eğer end pointlere address verilmezse base address geçerli olur–>
<!–Endpointlere address verilirse baseaddressin sonuna ekleyerek servisi çağırır–>
<!–Host tagı açılmadan endpointe tam address verilerek kullanım yapılabilir ancak özellikle birden fazla endpoint kullanılacaksa bu tanımla daha uygundur–>
<host>
<baseAddresses>
<add baseAddress=”http://localhost:8000/BusinessService/PersonService”/><!–BasicHttpBinding veya WsHttpBinding için,Örnek internete açık web servisler–>
<add baseAddress=”net.tcp://localhost:8080/BusinessService/PersonService”/><!–NetTcpBinding için,Uygun address kullanımı LAN ve VPN Sistemleri için–>
</baseAddresses>
</host>
<!–Endpoint address verilmezse baseaddresi alır–>
<!–Endpointimizin binding tipini seçiyoruz.Seçtiğimiz binding tipine göre hız,güvenlik ve data encoding mantığı değişiklik gösterecektir–>
<!–contract kısmına ise bizim servis contractımızın tanımının yapıldığı interface veriyoruz–>
<endpoint address=”partner” binding=”wsHttpBinding” contract=”BusinessService.IPersonService”></endpoint>
<!–birden fazla endpoint ve base address olabilir–>
<endpoint address=”localnetwork” binding=”netTcpBinding” bindingConfiguration=”” contract=”BusinessService.IPersonService” ></endpoint>
<endpoint address=”sonkullanici” binding=”basicHttpBinding” contract=”BusinessService.IPersonService”></endpoint>
<!–<endpoint address=”mex” binding=”mexHttpBinding” contract=”IMetadataExchange” />–>
</service>
</services>
</system.serviceModel>
</configuration>
Console Uygulamamız program cs sine aşağıdaki gibi hosttumuzu oluşturuyoruz.Console uygulamamıza BusinessClass library sini ve ServiceModel dll ni referanslardan ekliyoruz.
Bu şekilde tanım yapmamız yeterli geri kalan ayarları appconfigden otomatik olarak okuyor
using(ServiceHost hosts=new ServiceHost(typeof(PersonService)))
{
Console.WriteLine(“Service açılıyor…”);
hosts.Open();
Console.WriteLine(“Service açıldı…”);
Console.ReadLine();
}
Bunuda çalıştırdıktan sonra
http://localhost:8000/BusinessService/PersonService?wsdl yazarak wsdl görebiliriz
4-)Yazdığımız Servisin metotlarını kullanmak için yeni proje açarak bir tane Console uygulaması ekliyoruz.İsminede ClientConsoleUI diyelim.Projemize Servisimizi servis referanslardan ekleyelim(Tabi daha bir yere publish edilmediği için servisi debug modda çalıştırmayı unutmayın)Programın main cs içine aşağıdaki gibi kodları yazalım ancak Client içinde gerekli app.config ayarlarımızı yapmamız lazım
//using blogunda yazılanlar using bitince dispose oluyor.Aksi dışında kalanlar program bitince
//Clientın içini boş verirsek tek end point olmalı ,birden fazla varsa binding ismini vermemiz lazım.Bizim servisimizde birden fazla protokol olduğu için basichttpbinding name verdim
using (PersonServiceClient.PersonServiceClient proxy = new PersonServiceClient.PersonServiceClient(“BasicHttpBinding_IPersonService”))
{
List<PersonServiceClient.PersonEntity> PersonalList = proxy.GetPersonByAge(24).ToList <PersonServiceClient.PersonEntity>();
foreach (PersonServiceClient.PersonEntity entity in PersonalList)
{
Console.WriteLine(entity.Name + ” ” + entity.Age);
}
}
Console.ReadLine();
Resimde de görüldüğü gibi serviste OperationContract olarak tanımlamadığımız metotlar clienta gelmiyor
Not:Servis referans verdiğimizde client app configi otomatik oluşturyor.Aşağıda sarılı ile çizili olan nokta önemli kendi bilgisayarınızda kullanırken kodda buraları değiştirmeyi unutmayın
Not:Windows 7 makinalarda servisin start olması sorun olabiliyor onun için projeyi admin modda açmanızda fayda vardır.
<client>
<endpoint address=”http://localhost:8000/BusinessService/PersonService/partner”
binding=”wsHttpBinding” bindingConfiguration=”WSHttpBinding_IPersonService”
contract=”PersonServiceClient.IPersonService” name=”WSHttpBinding_IPersonService”>
<identity>
<userPrincipalName value=”LENOVO-PC\LENOVO” />
</identity>
</endpoint>
<endpoint address=”net.tcp://localhost:8080/BusinessService/PersonService/localnetwork”
binding=”netTcpBinding” bindingConfiguration=”NetTcpBinding_IPersonService”
contract=”PersonServiceClient.IPersonService” name=”NetTcpBinding_IPersonService”>
<identity>
<userPrincipalName value=”LENOVO-PC\LENOVO” />
</identity>
</endpoint>
<endpoint address=”http://localhost:8000/BusinessService/PersonService/sonkullanici”
binding=”basicHttpBinding” bindingConfiguration=”BasicHttpBinding_IPersonService”
contract=”PersonServiceClient.IPersonService” name=”BasicHttpBinding_IPersonService” />