Web servislerimi Windows uygulamasında nasıl host ederim?

0 dakikada yazıldı

12135 defa okundu

Düzenle

Dün bana gelen sorulardan birini cevaplamak üzerine hızlı bir makale
yazmaya karar verdim :) Gelen soruya doğrudan girmeden önce senaryoya
bir bakalım. Elimizde bir istemci var ve bu istemci sunucu üzerindeki
web servislerini kullanıyor. Söz konusu web servisleri IIS üzerine
yerleştirilmiş durumda. Oysa bizim istediğimiz şey bir anda bu web
servislerini IIS'ten bağımsız hale getirmek. Örneğin bize ait başka bir
sunucu uygulaması, özünde bir Windows uygulaması olsun ve söz konusu
uygulama bu web servislerini sunmak ile sorumlu olsun. Ne dersiniz?

Nasıl olacak ki?

Web servislerine genel olarak IIS üzerinden sunulan sayfalar gözü ile
bakarız oysa WCF ile bu manzara biraz değişiyor. WCF mantığında aslında
web servisi diye birşey yok, sadece Servis var. Söz konusu servisi ister
WEB ister başka bir şey üzerinden veya daha doğru bir tanımlama ile
başka bir protokol ile yayınlayabilirsiniz. Yayınlanan protokolün
mantığı vs aslında servisin iç yapısı ile alakasızdır! İşte WCF bunu
sağlıyor. O nedenle ilk olarak varsa yazmış olduğumuz eski ASMX'leri
birer WCF servisi haline dönüştürelim.

Bu dönüştürme işlemini yaparken projenize "Add New Item" diyerek yeni
bir WCF servisi eklemelisiniz. Fakat projeniz ne projesi olacak? Yani
eğer bu servisimizi bir web sitesi üzerinden sunmak istiyorsak tabi ki
elimizde bir ASP.NET projesi olmalı ve o projeye WCF servisimizi
eklemeliyiz. Oysa bizim istediğimiz şey bu Servis'in bir Windows
uygulaması tarafından sunulması. O zaman ilk olarak elimizde bir
Winforms veya WPF projesi bulunması gerekiyor, sonrasında bu projeye
"Add New Item" diyerek bir Service ekleyebiliriz.

Projemizde servisimiz bizi bekliyor...
Projemizde servisimiz bizi bekliyor...

Yukarıda projemizin Servis eklenmiş halini görebilirsiniz. Projemize
otomatik olarak bir Interface ve bir de Implentasyon kodları eklenmiş
durumda. Eğer ASP.NET tarafında WCF servisleri kullandı iseniz bu
noktada birşey dikkatinizi çekecektir. SVC uzantılı bir dosyamız yok!
Çünkü ona ihtiyacımız yok :) Bu servis IIS tarafından sunulmayacak, bunu
kendi programımız ile biz sunacağız o nedenle SVC gibi bir "placeholder"
dosyaya ihtiyacımız yok.

Bu noktadan sonra WCF ile klasik web servisleri arasındaki farklardan en
önemlisi bir Interface ve bir de Implementasyon dosyasının ayrı ayrı
bulunuyor olması. Makalemizin amacı WCF anlatmak olmadığı için bu farkın
detaylarına girmeyeceğiz fakat burada Interface'in servisin dışa sunduğu
imzası olduğunu düşünebilirsiniz. Biz basit bir servis hazırlayarak
devam edelim.

[VB]

Imports System.ServiceModel

 

<ServiceContract()> _

Public Interface IService1

 

    <OperationContract()> _

    Function Topla(ByVal x As
Integer, ByVal y As
Integer)

 

End Interface

[C#]

namespace WindowsFormsApplication1

{

    [ServiceContract]

    public interface IService1

    {

        [OperationContract]

        int Topla(int x, int
y);

    }

}

Servisimiz şimdilik iki sayı alıp toplayacak. Yukarıda gördüğünüz
Interface dosyası içerisinde servisin fonksiyonu ile ilgili bir
implementasyon bulunmuyor. Sadece servisin uygulayacağı Intefrace'i
yazdık. Sıra geldi şimdi de gerekli kodları yazacağımız diğer VB/C#
dosyamıza geçmeye.

[VB]

Public Class Service1

    Implements IService1

 

    Public Function Topla(ByVal x As
Integer, ByVal y As
Integer) As Object
Implements IService1.Topla

        Return x + y

    End Function

End Class

[C#]

namespace WindowsFormsApplication1

{

    public class Service1 : IService1

    {

        public int Topla(int x, int
y)

        {

            return x + y;

        }

    }

}

Diğer dosyamızda artık çalışacak olan kodumuzu yazıyoruz. Burada
gördüğünüz metodun ve kodun klasik web servislerinde yazdığınız koddan
pek bir farkı yok. Genelde eski servislerinizden kodunuz alıp
kopyala-yapıştır metodu ile WCF'e rahatlıkla taşıyabilirsiniz.

Artık WCF servisimiz hazırladığımız Winforms uygulaması içerisinde hazır
olduğuna göre sıra geldi bu servisi nasıl başkalarına sunacağımza
bakmaya. Bunun için hızlıca kullanabileceğimiz özel bir sınıf bulunuyor.

[VB]

Public Class Form1

 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles
Button1.Click

        Dim ServisSunucu As New
ServiceModel.ServiceHost(GetType(Service1))

        ServisSunucu.Open()

    End Sub

End Class

[C#]

namespace WindowsFormsApplication1

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

 

        private void button1_Click(object sender, EventArgs e)

        {

            System.ServiceModel.ServiceHost ServisSunucu = new System.ServiceModel.ServiceHost(typeof(Service1));

            ServisSunucu.Open();

        }

    }

}

ServiceHost nesnesi parametre olarak yaratacağı servisin tipini
ister. Bizim daha önce yazdığımız servisin tipini kendisine iletmemiz
ile beraber aslında bir servis sunucusu yaratmış oluyoruz. Söz konusu
sunucuyu Open metodu ile başlatabilir veya Close metodu ile
kapatabiliriz. Uygun şekilde bu komutları sunucuda çalışacak olan
Winforms veya WPF uygulamamızda farklı düğmelere bağlayabilirsiniz.

Peki servisi başkaları nasıl kullanacak?

Servisi ekledik, çalıştırdık ama adresi nedir? Yani başkaları nasıl
kullanacak? Daha önce de bahsettiğim gibi aslında bir WCF servisinin
hangi Endpoint (çıkış noktası/adres) ile yayınlanacağı ve hangi protokol
ile sunulacağı gibi ayarların yapılması gerekiyor. Yine maalesef ki bu
ayarların detaylarına bu makalede inmeyeceğiz fakat biraz şanslıyız
çünkü zaten varsayılan ayarları ile WCF servisleri wsHttpBinding
kullanıyor. Yani HTTP üzerinden çıkıyorlar. Bizim de istediğimiz eski
web servisleri gibi bu servislerin de HTTP üzerinden ulaşılabiliyor
olmasıydı. Fakat çıkış noktası konusunda ufak bir ayar yapmamız şart.

Çıkış noktası veya servisimizin HTTP adresi ile ilgili ayar aslında
uygulamanın içindeki App.config dosyasında saklanıyor. Bu dosya eğer
Solution Explorer içerisinde gözükmüyorsa doğrudan "Show all files"
düğmesine tıklayarak görünür hale getirebilirsiniz.

App.Config dosyası karşınızda.
App.Config dosyası karşınızda.

App.Config dosyasını açtığınızda farklı ayarlar ile karşılaşacaksınız.
Bu ayarlar içerisinde bir adres dikkatinizi çekecektir.

[App.Config]

<?xml version="1.0"
encoding=
"utf-8" ?>

<configuration>

    <system.serviceModel>

        <behaviors>

            <serviceBehaviors>

                <behavior name="WindowsApplication1.Service1Behavior">

                    <serviceMetadata
httpGetEnabled=
"true" />

                    <serviceDebug
includeExceptionDetailInFaults=
"false" />

                </behavior>

            </serviceBehaviors>

        </behaviors>

        <services>

            <service
behaviorConfiguration=
"WindowsApplication1.Service1Behavior"

                name="WindowsApplication1.Service1">

                <endpoint
address=
"" binding="wsHttpBinding"
contract=
"WindowsApplication1.IService1">

                    <identity>

                        <dns
value=
"localhost" />

                    </identity>

                </endpoint>

                <endpoint
address=
"mex" binding="mexHttpBinding"
contract=
"IMetadataExchange" />

                <host>

                    <baseAddresses>

                        <add
baseAddress="http://localhost:8732/Design\_Time\_Addresses/WindowsApplication1/Service1/" />

                    </baseAddresses>

                </host>

            </service>

        </services>

    </system.serviceModel>

</configuration>

Yukarıda gördüğünüz adresi değiştirmeniz halinde uygulamanız söz konusu
adresi dinlemeye başlayacaktır. Tabi bu işlemi özellikle root adreslerde
denerseniz uygulamanızın Admin hakları ile çalışmasına da dikkat etmeniz
gerek. Örneğin aşağıdaki şekilde adresimizi değiştirelim ve sonrasında
da bu adres üzerinden servisimizi başka bir uygulama ile kullanmayı
deneyelim.

[App.Config]

<host>

  <baseAddresses>

    <add
baseAddress="http://localhost/benimservisim" />

  </baseAddresses>

</host>

Basit bir şekilde bu uygulamayı admin hakları ile başlattıktan sonra
yeni bir proje yaratarak "Add Service Reference" dediğinizde bu adresi
girmeniz servise ulaşmanız için yeterli olacaktır. Unutmayın servisi
host edecek uygulamanızın admin hakları ile başlamasının yanı sıra
servisin ServiceHost üzerinden Open metodu ile çalıştırılmış
olması da gerekiyor.

Normal bir servisi kullanmaktan farkı yok!
Normal bir servisi kullanmaktan farkı yok!

Gördüğünüz gibi yarattığımız başka bir projede rahatlıkla bir önceki
uygulamamızda çalışan servisi referans olarak alabiliyoruz. Tabi bu
referansa ait endpoint'i de kod ile set etmekte fayda var.

Bundan sonrası için servisinizi kullanırken normalden farklı bir
mekanizma söz konusu değil. Her zamanki gibi servisinizi IIS üzerinden
sunuluyormuş gibi kullanabilirsiniz. Hatta belki makalemizin devamında
WCF'i biraz daha araştırarak bu servisin farklı Binding'ler ile nasıl
sunulabileceğine de bakabilir ve birkaç saniye içerisinde aynı servisin
hem HTTP hem de TCP üzerinden sunulmasını sağlayabilirsiniz.

Hepinize kolay gelsin.