WCF Nedir?

WCF Temelleri

Windows Communication Foundation WCF, servis-yönelimli mimariyi temel alarak dağıtık-uygulamalar geliştirmek için kullanılan, dağıtık mimari modelleri ve teknolojileri tek çatı altında birleştiren ve içerisinde bir çok hazır bileşen barındıran bir Framework API‘sidir. (Bknz. Service Oriented Architecture)

Ayrıca WCF mimarisi, .NET Remoting, XML Web Servisleri, Web Service Enhancements (WSE), Enterprise Services/COM+ ve Microsoft Message Queue(MSMQ) gibi bir çok dağıtık uygulama geliştirme modelinin tek bir programlama modeli içerisinde geliştiriciye sunmaktadır.

WCF Temelleri

.Net Framework 3.0 ile hayatımıza giren WCF, istemciler ve servisler arasındaki mesajları göndermek için oluşturulan sistemleri geliştirmek için kullanılan API topluluğudur. Bu mesajlar, TCP, HTTP, MSMQ, Web Servisleri vb. gibi ortak taşıma protokolleri kullanarak Intranet ve Internet üzerinden gönderilebilir. Ayrıca mesajlar güvenli bir şekilde gönderilmekte ve dijital bütünlüğü için imzalanabilmektedir. WCF mesajlaşma işlemi için, istek/yanıt (request/response) şeklinde basit mesaj desenlerinin (message patterns) yanı sıra iki kanal üzerinden iletişim gibi daha karmaşık desenleri desteklemektedir.

Diğer önemli özelliği ise Web Service Enhancements (“WS-*”) standartlarına uyan Web Servisleri ile farklı platformlarda (interoperability) çalışabilmesidir yani WCF bu standartları uygulayarak Microsoft olmayan diğer platformlarda oluşturulmuş istemciler yada servisler ile iletişim kurabilir.

Makaleye devam etmeden WCF içerisinde sıklıkla kullanılan genel kavram ve terimleri tanıyalım ;

Message: veri parçalarının birbirinden bağımsız hali olan paketlerdir, başlık (header) ve gövde (body) dahil olmak üzere bir kaç bölümden oluşmaktadır. Bir mesajın başlık dışında, tüm parçaları şifreli ve dijital imzalanmış olabilir.

Service: bir yazılım modülü (EXE veya DLL), bu modülün n tane endpoint desteği vardır ve her endpoint n tane servis işlemi yapmamıza olanak sağlar.

Endpoint: istemciler (clients) ve host’lar arasındaki iletişimi şağlamak için kullanılan bir arayüzdür. Her endpoint’in kendi adresi vardır ve bu adresin benzersiz olması için servisin kendi ana adresine eklenmektedir. Bir WCF servisini aslında endpoint topluluğu olarak düşünebiliriz.

Binding: endpoint‘lerin dış dünya ile nasıl haberleşileceğinin tanımlandığı bir takım özellikler bütünüdür. Yani endpoint ile ilitişimin (HTTP yada TCP) nasıl yapılacağının tanımlandığı noktadır. Bir binding ile endpoint‘in kullanacağı security yada message pattern gibi detayları ayarlanabilmektedir.

System-provided bindings: Bazı senaryolar için optimize edilmiş binding topluluğudur. Örneğin, WSHttpBinding Web Servislerinin farklı platformlarda (interoperability) çalışabilmesi için çeşitli WS-* özelliklerini uygulamış hazır bir binding’tir.

Service Contract: contract servisin adını, namespace’ini ve diğer global niteliklerinin tanımlandığı bileşendir. Uygulamada bir contract, bir intarface oluşturularak bu interface’e [ServiceContract] etiketi uygulanılarak oluşturulmaktadır. Aşağıdaki Örnek 1 de IMyBasicService interface’inde uygulanış şeklini gözlemleyebilirsiniz. Asıl servis kodu ise bu interface ile genişletilmiş olan sınıftır.

Operation Contract: [ServiceContract] etiketi uygulanılarak oluşturulmuş interface’in içerisinde bulunan operasyonların (metodların) servis tarafında kullanılabilmesi için uygulanan etikettir. Interface içerisindeki metodlara [OperationContract] etiketi uygulanarak kullanılır. Aşağıdaki Örnek 1 de IMyBasicService interface’inde uygulanış şeklini gözlemleyebilirsiniz.

Data Contract: Servisi kullanan istemciler ile ortak çalışmayı sağlamak için servisin kullandığı veri nesneleri hakkında bilgi veren veriler (metadata) olarak tanımlanabilir. Bu veri türleri açıklamaları Data Contract olarak bilinir ve tipler herhangi bir mesaj (parametreleri veya dönüş türleri) içinde kullanılabilir.

Host: genelde servisin yaşam süresini kontrol etmek amacıyla kullanılan bileşendir. Host tipik olarak bir console uygulaması, bir Window Activation Service (WAS) yada Internet Information Service (IIS) üzerinde olabilir. Host eğer IIS üzerinde ise, bir virtual directory oluşturulur ve içerisine servis assembly’leri, konfigürasyon dosyası konulur. IIS üzerinde çalışan host’a istemciden bir message gelmediği sürece servis çalışıyor durumda değildir. Eğer bir istemci yada istemciler çalıştığı session’ı sonlandırırsa IIS de uygulamayı kapatıp kullanmakta olduğu sistem kaynaklarını serbest bırakır. Aşağıda bu bileşen ile ilgili console uygulamasında host edilen Program sınıfını inceleyebilirsiniz.

Behaviour: servisin çalışma zamanındaki fonksiyonelliğini zenginleştirerek gerekli parametrik ayarların yapıldığı bir tipdir. Servis behaviour’ları ilgili servis sınıfına [ServiceBehaviour] etiketi uygulanarak kullanılmaktadır ve istenilen behaviour özelliklerinin ayarlanması ile servis çeşitli fonksiyonellikler sergileyebilmektedir.

Aslında behaviour’lar, bir servis yada endpoint için çalışma zamanındaki çeşitli beklentilerimizi kontrol etmek için kullanılmaktadır. Behaviour’lar kapsamına göre gruplandırılmıştır ; ortak olarak kullanılan behaviour’lar tüm endpoint‘leri etkilemektedir, servis behaviour’ları yalnızca servisler ile ilgili özellikleri etkilemekte, endpoint behaviour’ları yalnızca ilgili endpoint özelliklerini etkilemektedir. Örneğin bir endpoint behaviour’ı ile güvenlik için kullanılan kimlik bilgilerine nereden ve nasıl erişilebileceği belirlenebilir.

Instancing: Her servisin çalışma zamanında kaç tane intance’ının çalışacağının belirlendiği bir model vardır. Bu modeller Single, PerCall, PerSession ve Shareable olmak üzere toplamda dört tanedir. Bu modellerden ilk iki tanesi .Net Remoting içerisindeki Singleton ve Singel Call SAO ile benzerlik göstermektedir.

Instance modelinin belirlenmesi işi aslında bir behaviour tanımlamaktır ve [ServiceBehaviour] etiketi ile tanımlanmaktadır. Örneğin ; [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

Client Application: bir yada birden fazla endpoint ile mesaj alışverişinde bulunan program. Tipik olarak bir client application WCF Client nesneleri oluşturarak proxy üzerinden bu nesneler yardımıyla method çağırımları yapmaktadır. Aşağıdaki Örnek 1 de nesneler üzerinde uygulanış şeklini gözlemleyebilirsiniz.

Channel: client application ile bir servis arasındaki iletişim kanalıdır. Bir client TCP, HTTP gibi iletişim protokolleri ve bir adres kullanarak belirli bir endpoint için iletişim kanalı oluşturabilmektedir.

WCF Client Object: İstemci tarafı servis operasyonlarını enkapsule etmek için kullanılan yapılardır. Başka bir değişle WCF Client Object servis metodlarına erişim için kullanılan proxy’ler olarak tanımlayabiliriz.

WCF Client Object herhangi bir uygulama tarafından hatta bir servis olarak bile host edilebilmektedir.

Bu nedenle bir servis içerisinde diğer servislerin proxy’lerini içeren nesneler oluşturup kullanmak mümkündür. (service aggregation – bu özellik SOA içerisinde önemli bir konseptir.) Bu proxy’ler de genellikle svcutil.exe komut satırı aracı kullanılarak oluşturulmaktadır.

Metadata: svcutil.exe komut satırı aracı kullanılarak oluşturulan veridir. Bu veri aşağıdaki bileşenleri içermektedir.

  • Servisin data contract‘larını tanımlayan XML şemayı
  • Servis metodlarının tanımlamak için kullanılan WSDL’i
  • Application configuration dosyalarını içermektedir.

Metadata exchange point: metadata bilgilerini yayınlamak için kullanılan bir endpoint adresidir.

Security: WCF içerisindeki güvenlik mesaj şifreleme, mesajların bütünlüğünü korumak için kimlik doğrulama (authentication) ve yetkilendirme (authorization) fonksiyonları içermektedir. Bu fonksiyonlar varolan HTTPS gibi güvenlik mekanizmaları ile sağlanmakta yada (“WS-*”) standartlarına uyan çeşitli güvenlik tanımlarını uygulayabilmektedir.

Message pattern: istemci ve servis arasındaki mesajların ilişkisi ve yönünü belirler.

En temel message pattern’i one-way (diğer bir adıda one-shot)’dir. Bu pattern servise tek yönlü herhangi bir mesajı göndermek için kullanılır ve geriye bir cevap (response) beklenmez.

En karmaşık pattern ise dual HTTP‘dir. Bu pattern ile istemci ile servis arasında iki tane HTTP kanalı oluşturulur. Bu şekilde istemci ve servisde kendi taraflarında çeşitli operasyonları çağırıp kullanabilmektedir.

Reliable messaging: Bir mesajın sadece bir kez alındığının ve hangi sırayla gönderildiğinin güvencesidir.

Sessions: bir session client ve servis arasında iletişim kurmak için kullanılmaktadır. Client ve servis arasındaki tüm mesajlar session kimlik bilgileri ile etiketlenmekte ve bu şekilde session tanımlanarak ilgili client mesajları ile istenen işlemler yapılmaktadır. Eğer bir session herhangi bir sebepten kesilirse aynı kimlik bilgileri ile tekrar başlatılabilir.

WCF Mimarisi

Aşağıdaki resim WCF mimarisinin ana bileşenlerini göstermektedir (Contracts, Service Runtime, Messaging ve Activation & Hosting):

WCF Mimarisi

Contracts

  • Data Contract: Bir servisin her mesaj için oluşturabileceği yada tüketebileceği parametreleri tanımlar. Bu mesaj parametreleri XSD kullanarak tanımlanmakta ve XML formatını anlayabilen ve bu mesajları işleyebilen herhangi bir sistem ile çalışabilmektedir.
  • Message Contract: SOAP protokolleri kullanarak belirli ileti parçalarını tanımlar ve mesaj parçaları üzerinde detaylı bir kontrol sağlar.
  • Service Contract: daha önce burada tanımlamıştık.
  • Policy and Binding: daha önce burada tanımlamıştık.

Service Runtime

Service Runtime katmanı yalnızca herhangi bir servisin asıl operasyon sırasında oluşan davranışları içerir. Örneğin throttling control mekanızması sayesinde kaç tane mesajın işlenebileceği belirlenebilir, Error behaviour tanımlanarak bir hata durumunda nasıl bir davranış sergileneceği belirlenebilir yada Metadata behaviour tanımlanarak metadata’yı dış dünyaya kullanıma nasıl sunulacağı belirlenilebilir vb.

Messaging

Messaging katmanı verinin olası formatı ve message pattern’leri ile ilgili işlemleri gerçekleştirmektedir. Örneğin, WS Security Channel messaging katmanında güvenliğini sağlayan WS-Security tanımlarına uyan güvenlik standartlarını uygulamaktadır. WS Reliable Messaging Channel mesajın teslimat garantisini vermektedir. Encoder’lar mesajın metin, XML veya diğer desteklenen format’lardan herhangi biri olarak gönderilmesi gerektiğini belirlemek için kullanılır.

Activation & Hosting

Bir servis kendi kendine barındırılabilir (self-hosted) yada başka bir uygulamaya bağlı olarakta barındırılabilir. Ayrıca bir servis yine bir EXE, Windows Service, COM+ yada IIS altında da çalışabilmektedir.

WCF ABC’si

WCF Mimarisi

Bir WCF servisinin aslında endpoint topluluğu olduğunu ve her endpoint’in dış dünya ile haberleşme noktası olduğunu, bir client uygulamasının bir yada birden fazla endpoint ile message alışverişinde bulunabildiğini hatırlayalım. Her endpoint ise Address, Binding, ve Contract bileşenlerine sahip olmalıdır.

ABC‘ aslında bir endpoint‘in nasıl oluştuğunu anlamak için kullanılan bir betimdir ve tanımlayacak olursak:

    • A ‘nın açılımı Address. Servisin nerede olduğunu belirtir.
    • B ‘nin açılımı Binding. Servis ile iletişimde kullanılacak aktarım protokolü (Http, Tcp, NamedPipes vb.), kodlama (encoding text, binary vb.) ve güvenlik gereksinimlerini ( SSL, SOAP message security vb.)belirtir ve servise dış dünyanın hangi kurallar ile bağlanabileceğini ifade eder.
    • C ‘nin açılımı Contract. Servis ile yapılabilecek işlemleri ifade eder.

Oluşturacağınız herhangi bir WCF servisi,  arkaplanda hangi yöntemi/teknolojiyi kullanırsa kullansın mutlaka yukarıda açıkladığınız bu üç temel bileşene sahip olmalıdır.

ServiceEndpoint sınıfı bir Endpoint’i temsil eder ve bir EndpointAddress, bir Binding ve ContractDescription bileşenlerini içerir.

Service Endpoint

Endpoint Address

Bir EndpointAddress temelde bir tanım (URI) bir kimlik bilgisi (identity), aşağıdaki şekilde gösterildiği gibi isteğe bağlı başlık topluluğudur ve servisin nerede bulunduğunu belirtir.

Bir Endpoint güvenlik kimliği (identity) normalde tanım olmakla birlikte, gelişmiş senaryolarda bu bileşeni URI’den bağımsız olarak Identity adres özelliğini değiştirerek ayarlayabilmekteyiz.

AddressHeader’lar bir endpoint’e URI ötesinde ek adresleme bilgileri sağlamak için kullanılır. Örneğin, adres başlıkları aynı adres tanımını paylaşan çok sayıda endpoint arasında ayırım yapmak için faydalıdır.

Endpoint Address

Bindings

Binding bir endpoint ile nasıl etkileşime geçileceğinin belirlendiği bileşendir ve Name, Namespace ve BindingElement öğelerinden oluşmaktadır.

Bindings

Aslında her binding element endpoint ile nasıl bir etkileşim ile iletişm kurulacağını belirtir. Binding elementleri inceleyecek olursak ;
TcpTransportBindingElement : endpoint taşıma protokolü olarak TCP kullanılarak dış dünya ile haberleşileceğini belirtir.
ReliableSessionBindingElement : endpoint’e message teslimi sağlamak için güvenilir bir mesajlaşma kullanacağını belirtir.
SecurityBindingElement : endpoint’in SOAP message güvenlik tanımlarının kullanılacağını belirtir.

Her binding element’in genellikle endpoint ile iletişimin nasıl yapılacağını açıklayan özellikleri vardır. Örneğin ReliableSessionBindingElement’in Assurances özelliği sayesinde en az bir kez, en fazla bir kez, ya da tam olarak bir kez gerekli mesaj iletimine güvence verilir.

BindingElements

Contracts

WCF Contract, endpoint’in dış dünya ile iletişiminde kullanacağı operasyonlar topluluğudur. Aslında buradaki her operasyon basit bir mesaj alışverişidir. (one-way yada request/response gibi)

WCF Contract’larını ve operasyonlarını tanımlamak için ContractDescription sınıfı kullanılmaktadır. ContractDescription içerisinde ise her Contract operasyonunun one-way yada request/reply şeklinde mi bir yaklaşım ile çalışacağının ayarlandığı OperationDescription bulunmaktadır. Her bir OperationDescription da MessageDescription topluluklarını kullanarak işlemler ile oluşturulan mesajları açıklar.

WCF programlama modeli içerisinde bir ContractDescription genellikle Contract’ı oluşturulan interface yada sınıf üzerinden oluşturulur. Oluşturulan tipe ServiceContract etiketi uygulanarak ve endpoint operasyonları içinde tip içerisindeki metodlara da OperationContract etiketi uygulanarak kullanılır.

Contracts

Behaviors

Bir ServiceBehaviour, IServiceBehaviour interface’i ile genişletilmiş ve yalnızca servislere uygulanan olan bir türdür. Aslında behaviors, servis veya client’ın işlevselliğini genişletmeye yarayan türleridir. ServiceBehaviour’a benzer olarak IChannelBehaviour interface’i ile genişletilmiş ve yalnızca client channel’lara uygulanan Channel Behaviour türüde WCF içerisinde hazır olarak gelmektedir.

Behaviour’lar bir channel oluşturma sürecine katılım sağlarlar ve kullanıcı tarafından belirlenen behaviour ayarlarına göre ilgili channel davranışını değiştirebilirsiniz.

Channels and Description

Service-side

ServcieDescription, bir WCF servisinin kullanıma açtığı endpoint’lerin, servis tarafından kullanılan behaviour’ların ve tiplerin (class vb.) yapısal olarak tanımıdır.

Bir ServiceDescription sınıfı metadata oluşturmak ve channel ayarlarını yapmak için kullanılmaktadır :

Servcie Description

Ayrıca ServiceDescription’ı ilgili WCF etiketlerini tiplerinize uygulayarak oluşturabilirsiniz.

Client-side

Service-side’a benzer olarak, bir ChannelDescription bir WCF istemcisinin iletişim kuracağı belirli bir endpoint’in yapısal olarak tanımıdır.

Channel Description

ServiceDescription’a farklı olarak, bir ChannelDescription istemci iletişim kanalının hangi endpoint ile iletişim kurulacağını temsil eden bir ServiceEndpoint içerir.

WCF Runtime

WCF Runtime aslında mesaj gönderme ve alma işlemlerinden sorumlu nesneler kümesidir. Bu mesajları biçimlendirme, güvenlik uygulama, çeşitli protokolleri kullanarak mesaj gönderme ve alma işlemlerini kapsamaktadır. Aşağıdaki başlıklarda WCF çalışma zamanının temel kavramları tanıyalım:

Message

Bir WCF Message bir istemci ile bir endpoint arasında veri alışverişi birimidir ve bir message aslında bir SOAP message InfoSet‘inin bir bellek içi gösterimidir. WCF message’ları XML formatına bağlı kalmamakla birlikte geliştiricinin belirleyeceği kodlama (encoding) biçimine göre text, binary, yada özel olarak serileştirilebilmektedir.

Channel

Channel’lar (Transport channels) ve (Protocol channels) olmak üzere iki ana kategoriye ayrılmaktadır. Transport channels TCP, UDP veya MSMQ aktarım protokollerini kullanarak stream gönderme ve alma işlemlerini gerçekleştirmektedir. Protocol channels ise SOAP spesifikasyonlarını uygulayarak message’ları işleme ve düzenleme işlemlerini gerçekleştirmektedir.

Endpoint Listener

Bir EndpointListener çalışma zamanında bir ServiceEndpoint eşdeğerdir.

ServiceEndpoint’in EndpointAddress, Binding ve Contract bileşenleri EndpointListener’ın listening address, message filtering ve dispatch, ve channel stack bileşenlerine karşılık gelmektedir.

EndpointListener içerisinde yer alan Channel (Stack) Yığını mesaj gönderme ve alma sorumludur.

ServiceHost and Channel Factory

Service Host

WCF Runtime genellikle ServiceHost.Open metodu çağırıldığında arka planda oluşturulur. ServiceHost, ServiceDescription nesnesinin oluşturulması ve bu nesne içerisindeki yer alan ServiceEndpoint koleksiyonunun config dosyasında yada kod içerisinde tanımlanan Endpoint’ler ile doldurma işlemlerini gerçekleştirir.

Sonrasında ServiceHost, ServiceDescription’ı Channel Stack oluşturmak için kullanır. Channel Stack ise EndpointListener nesnesi şeklinde olarak ServiceDescription içerisindeki her ServiceEndpoint’ten faydalanılarak oluşturulur :

Channel Description

Channel Factory

Server-side’a benzer olarak, client runtime ChannelFactory tarafından oluşturulmaktadır. ChannelFactory ise client tarafında sunucu tarafındaki ServiceHost’un eşdeğeridir. ChannelFactory ise Contract tipi, Binding, ve EndpointAddress’ini baz alarak ChannelDescription’ı oluşturmaktan sorumludur.

ChannelFactory daha sonra ChannelDescription’ları client’s channel stack oluşturmak için kullanır.

Service runtime’dan farklı olarak client runtime EndpointListener içermez çünkü client’a devamlı gelen bir bağlantı yoktur, bunun yerine client Service’den devamlı istekte bulunur.

Örnekler

Örnek 1

Aşağıdaki kod çalışan temel bir WCF uygulaması örneğini göstermektedir. Proje düzeni Solution Explorer aşağıda gösterilmiştir :

BasicClient projesi “Console application”, BasicServiceImplementation projesi “Class Library” ve BasicHost projeside “WCF Service Library” türündedir.

BasicClient konsol uygulaması, BasicHost üzerinden BasicServiceImplementation tarafından uygulanan servisi, çağıran bir WCF istemcisidir:

Sample Solution

BasicServiceImplementation.csproj

/*
Dış dünya ile paylaşılacak bir servis oluşturmak için ilk adım bir contract tanımlamaktır.
Bir contract oluşturmak için en kolay yol servis sınıfının uygulayacağı interface'i
ServiceContract etiketiyle işaretlemektir. Interface içerisinde bulunan metodları da 
aşağıda gösterildiği üzere OperatonContract etiketiyle işaretlememiz gerekmektedir.
 
Bu şekilde interface ile genişletilerek oluşturulmuş sınıf WCF Servis sınıfı haline gelir.
*/

using System.ServiceModel;

[ServiceContract()]
public interface IMyBasicService
{
    [OperationContract()]
    string MyOperation1(string myValue);
}

public class MyBasicService : IMyBasicService
{
    public string MyOperation1(string myValue)
    {
        return "Merhaba " + myValue;
    }
}

BasicHost.csporj

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <!-- Servisler <services> bölümünde tanımlanmıştır. Bir assembly 
         içerisinde bir çok servis barındırılabilir, her servis kendi 
         yapılandırma bölümü içerisinde <service> olarak tanımlanır.-->
        <services>
            <!-- Bu bölümde Address, Binding ve Contract (ABC) bilgilerini 
            içeren servis endpoint tanımlanır. 
      
            Kullanılan Contract adının Basics.IMyBasicService şeklinde 
            (fully-qualified name) olarak tanımlandığını unutmamak gerekir.
      
            Adress <host> element'i içerisinde tanımlanırken Contract ve Binding 
            <endpoint> elemanı altında tanımlanır. -->
            <service name="Basics.MyBasicService">

                 <!-- Endpoint aslında Contract'ın (ABC) sinin tanımlandığı kısımdır.
                 'address' bileşeni <host> öğesinde belirtilen baseAddress' e göre 
                 tanımlanır. <endpoint> öğresi içerisindeki 'address' bileşeni boş 
                 bırakılırsa endpoint adresi <host> öğesi içerisindeki baseAddress'i 
                 kendi adresi olarak kabul edecektir. -->
                <endpoint address="/MyBasicService" 
                          binding="wsHttpBinding"
                          contract="Basics.IMyBasicService" />
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8080"/>
                    </baseAddresses>
                </host>
            </service>
          </services>
    </system.serviceModel>
</configuration>
/*Sonraki adım olarak servisi çalıştırmak için gerekli konfigürasyonu ve barındırma
(hosting) ayarlarını yapılandırıp servisi açmamız gerekiyor. Bir WCF Servisi bir contract, 
behaviour ve endpoint'lerin tanımları ile ilgili yapılandırmaları içerir. Servisi 
başlatmak için ServiceHost sınıfından instance oluşturup Open metodunu çağırmamız 
gerekmektedir. Böylelikle client'lardan gelicek mesajları bekleyen dinleyiciler (listeners) 
otomatik olarak oluşur.*/

internal class MyServiceHost
{
    internal static ServiceHost myServiceHost = null;

    internal static void StartService()
    {
        myServiceHost = new ServiceHost(typeof(Basics.MyBasicService));

        // Servisi başlat
        myServiceHost.Open();

        // Servis bilgilerini görüntüle
        DisplayInfo(myServiceHost);
    }

    internal static void StopService()
    {
        // Servisi durdur
        Trace.WriteLine(" Servis Durumu: " + myServiceHost.State.ToString());

        if (myServiceHost.State != CommunicationState.Closed)
        {
            myServiceHost.Close();
            Trace.WriteLine(" Servis Kapatıldı!");
        }
    }

    internal static void DisplayInfo(ServiceHost host)
    {
        // Servis bilgileri
        ServiceDescription description = myServiceHost.Description;
        Trace.WriteLine("Servis Tipi: " + description.ServiceType.FullName);
        Trace.WriteLine("Behaviour sayısı: " + description.Behaviors.Count);

        if (description.Endpoints.Count > 0)
            foreach (ServiceEndpoint endpoint in description.Endpoints)
                Trace.WriteLine("Endpoint Adresi: " + endpoint.Address.ToString());
        else
            Trace.WriteLine("ServiceEndpoints Sayısı: " + description.Endpoints.Count);
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyServiceHost.StartService();

        // Servisi kullanıcı durdurana kadar çalıştır.
        Console.WriteLine("WCF Servisi kullanıma hazır. ");
        Console.WriteLine("Servisi durdurmak için <RETURN> tuşuna basınız.");
        Console.ReadLine();

        // Servisi kapat
        MyServiceHost.StopService();
    }
}

BasicClient.csporj

/*Bir WCF client uygulaması, WCF client nesnelerini kullananarak diğer uygulamalar ile 
iletişime geçen ve yönetilen (managed) bir uygulamadır. WCF Client nesneleri, ilgili 
WCF servisini nesne olarak temsil ettiğinden, yerel olarak uzakta (başka network, 
internet vb.) bulunan servis ile iletişim kurmak için kullanılabilmektedir. Diğer bir
deyişle; WCF client nesneleri uzaktaki servis için kullandığımız birer proxy'dir.*/
class Program
{
    static void Main(string[] args)
    {
        // Servis üzerindeki contract'a bağlanmak için channel oluştur.
        ChannelFactory<IMyBasicService> factory = new ChannelFactory<IMyBasicService>(
                                        new WSHttpBinding(),
                                        new EndpointAddress("http://localhost:8080/MyBasicService"));
        IMyBasicService channel = factory.CreateChannel();

        // Contract metodlarını çalıştır
        string strParam = "Kazım Cesur";
        Console.WriteLine("Gönderilen değer: " + strParam);
        string strReturnValue = channel.MyOperation1(strParam);
        Console.WriteLine("Servisten gelen değer: " + strReturnValue);

        // Kullanıcı herhangi bir tuşa bastığında servisi durdur.
        Console.WriteLine("Servisi durdurmak için <RETURN> tuşuna basınız.");
        Console.ReadLine();
        factory.Close();
    }
}

// Servisi kullanabilmek için ilgili interface'in client'tada olması gerekmektedir.
[ServiceContract()]
public interface IMyBasicService
{
    [OperationContract()]
    string MyOperation1(string myValue);
}

Uygulamayı çalıştırmak için Visual Studio içerisinden Solution Properties’ten Multiple startup projesi olarak BasicHost ve Basic Client projelerini start olarak seçmeniz gerekir. Sonrasında client-server uygulaması çalıştırıldığında çıktısı aşağıdaki gibi olacaktır :

Örnek 1 Sonuç

Örnek uygulamaları buradan indirebilirsiniz.

Örnek 2

Bu örnek, Örnek 1 ile benzerdir ancak client tarafından kullanılan proxy SvcUtil.exe aracı ile oluşturulmuştur. Solution içerisindeki tüm projeler aynı olarak kalmaktadır client olarak BasicClient.csproj yerine yeni eklenen BasicClientWithProxy.csproj projesi kullanılmıştır.

Sample Solution

Dikkat edileceği üzere BasicClientWithProxy projesi içerisinde schemas.microsoft.com.2003.10.Serialization.cs dosyası yer almaktadır. Bu dosya Visual Studio Command Prompt üzerinden SvcUtil.exe aracı(utility) kullanılarak oluşturulup projeye dahil edilmiştir. SvcUtil.exe aracı BasicHost projesi output folder’ında (BasicHost.exe nin bulunduğu dizinde) aşağıdaki komutlar ile çalıştırılmıştır.

svcutil.exe BasicServiceImplementation.dll

Bu komut çalıştırıldığında BasicServiceImplementation.dll’i içerisinde bulunan Contract yapısını kullanarak WSDL ve XSD dosyalarını üretir. Bu dosyalar Contract’ın meta verilerini içerir.

svcutil.exe *.wsdl *.xsd /language:C#

Ardından bu komutu çalıştırdığımızda ise C# dili için WSDL ve XSD dosyalarından proxy sınıfını oluşturmuş olur. Bu dosyayı proye dahil edip aşağıdaki şekilde kullandığımızda servise erişmemiz çok kolay olacaktır.

Svcutil aracı ayrıca .config dosyasıda oluşturmaktadır. Fakat oluşan bu dosya daha detaylı bilgileri içerdiği için aşağıdaki config’den de görüleceği üzere anlaşılabilirlik için sadeleştirdim :

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <client>
            <endpoint address="http://localhost:8080/MyBasicService" contract="IMyBasicService" binding="wsHttpBinding"/>
        </client>
    </system.serviceModel>
</configuration>
class Program
{
    static void Main(string[] args)
    {
        // Servis için proxy oluştur.
        MyBasicServiceClient proxy = new MyBasicServiceClient();
        string strReturnValue = proxy.MyOperation1("Kazım Cesur");
        Console.WriteLine("Servisten gelen değer: " + strReturnValue);

        // Kullanıcı herhangi bir tuşa bastığında servisi durdur.
        Console.WriteLine("Servisi durdurmak için <RETURN> tuşuna basınız.");
        Console.ReadLine();
    }
}

Kaynak ;

Understanding Service-Oriented Architecture
Windows Communication Foundation
Windows Communication Foundation Architecture
Windows Communication Foundation Architecture Overview