Burak Selim Senyurt(MVP)
Matematik Mühendisi bir .NET Severin Yazıları...

Microsoft Teknoloji Günleri Akşam Sınıfı – Gün 3 – WCF ile Servis Yaklaşımı Eğitimi Tamamlandı

Çarşamba, 21 Temmuz 2010 02:45 by bsenyurt

IMG_3578

Merhaba Arkadaşlar,

25 Mayıs 2010 Tarihinde C# 4.0 ile birlikte gelen yenilikleri anlatarak başladığımız Microsoft Teknoloji Günleri Akşam Sınıfının üçüncü gününü de kazasız belasız tamamladık. Öncelikli olarak tüm katılımcılarımızın ayağına sağlık.

Eğitimin video kayıtlarının alınması noktasında yardımcı olan Mustafa Demirhan’a, kameranın kapasitesi dolunca yardıma koşarak kendi kamerası ile çekim yapan Microsoft Student Partner(MSP) adayı Burak Özkan’a, şu anda okumakta olduğunuz blog yazısındaki resimler gibi kaliteli, yüksek çözünürlüklü sayısız fotoğraf çekerek bizle paylaşan Tuba Çebi’ ye, Akşam Sınıfı fikrinin olgunlaşmasında en büyük yardımcım olan ve özellikle katılımcıları aşağıdaki resimde olduğu gibi hediyeler ile mutlu etmemizi sağlayan Buket Şerefli’ ye(Microsoft Türkiye İş Ortağı Yöneticisi) canı gönülden teşekkür etmek istiyorum.

IMG_3582

Buket Şerefli tarafından temin edilen hediyeler arasında bulunan Yeşil Vista Logolu Havlu’ sunu, kazanan değerli katılımcımıza hediye ederken.

IMG_3761

Microsoft Certified Partner logolu duvar saatlerinden birisini, kazanan değerli katılımcımıza hediye ederken.

Eğitimde çok güzel bir sürprizi de ben yaşadım. Imagine Cup Türkiye birincisi olan ve ülkemizi Polonya’ da düzenlenen finallerde başarılı bir şekilde temsil eden ekipten iki arkadaşımız da aramızdaydı.

IMG_3547

Imagine Cup Türkiye birincisi olan ekipten İbrahim Kıvanç(Imagine Cup 2010 Polonya Dünya Finalleri Ardından) ve  Yasemin Çelik, yarıştıkları BabyRC projesi hakkında kısaca bilgi verirken. (Ekibin bu akşamki eğitime katılamayan diğer üyeleri ise Burak Kanmaz ve Fatih Coşkun’ dur)

Eğitimimiz boyunca öncelikli olarak Service Oriented Architecture(SOA) kavramını kısaca tanımaya/anlamaya çalıştık. Sonrasında ise Microsoft’ un uzun süredir vizyonda olan SOA implemantasyonu WCF’ e(Windows Communication Foundation) giriş yaptık. WCF üzerinden uygulanabilen SOA desenelerini görüp, mimarisini ve çalışma zamanını kavradık. WCF’ in ABC’ sini de(AddressBindingContract) işin içerisine katmayı unutmadık elbette. Son olarak basit bir Hello World uygulaması geliştirip, WCF 4.0 ile birlikte gelen bazı yenilikleri(Discovery, Routing, Simplified Configurations) örnek demolar üzerinden anlamaya çalıştık.

Yaklaşık olarak 3 saatten fazla bir zamanımızı Microsoft İstanbul Ofisi Jupiter 1 salonunda geçirdik. Tabi akşam saati ve bir sonraki gününde mesai olması nedeniyle, özellikle uzakta oturan veya çok erken saatte işe giden arkadaşlarımızın bir kısmı mecburen erken çıkmak zorunda kaldılar. Ancak üzülmesinler nitekim bir şey kaçırmadılar. Tüm eğitimin video kaydını gerçekleştirdik. En kısa sürede render işlemini tamamlayıp Nedirtv?Com topluluğu üzerinden sizlerle paylaşıyor olacağım.

Bunlara ek olarak bir önceki eğitimimizde vaat ettiğimiz Pro .Net 4.0 Parallel Programming kitabını da, kazanan arkadaşımıza hediye ettik.

Bir sonraki eğitimimizin konusu WCF Eco System. 20 Ağustos 2010 Cuma günü yapılacak bu eğitimi kaçırmamanızı öneririm. Eğitimin duyurusu ve kayıt linki 15 Ağustos’ tan sonra duyuruluyor olacaktır.

Eğitimde Kullanılan Örnekler : TeknolojiGunleri_WCF.rar (304,80 kb)

Eğitime ait Powerpoint Sunumu : WCF 4.0 - Introduction - Microsoft.pptx (483,87 kb)

Microsoft Teknoloji Günleri Akşam Sınıfı – Gün 3 – WCF ile Servis Yaklaşımı

Çarşamba, 14 Temmuz 2010 14:12 by bsenyurt

BizSpark

 
 

GelisimAtolyesi

Tarih
20 Temmuz 2010 Salı

Saat
19.00 - 21.30

Yer
Microsoft İstanbul Ofisi

Eğitmen:
Burak Selim Şenyurt
Microsoft MVP

HemenKayit

 

Microsoft Teknoloji Günleri -
Akşam Sınıfı


Her ay düzenli olarak gerçekleştireceğimiz ve bir seri olarak birbirini takip edecek sınıf etkinliklerimizle 9 ay boyunca siz yazılım geliştiren ve tasarım yapan iş ortaklarımızla birlikte olacağız.

Aşağıda detaylarını paylaştığımız ve sizler için hayli faydalı olacağına inandığımız Microsoft Teknoloji Günleri Akşam Sınıfı Etkinliğimize kaydınızı hemen yaptırabilirsiniz.

Ders İçerikleri:

1. 25.Mayıs.2010/Salı: C# 4.0 ile Gelen Yenilikler : (2 Saat) Bu eğitimde C# programlama dilinin 4.0 versiyonu ile birlikte gelen yenilikleri tanıtmaya çalışılmakta ve özellikle, Dynamic diller ile Office API vb yapılar ile olan etkileşim üzerine örnekler geliştirilmektedir. Eğitimde temel olarak dynamic keyword, optional and named parameters, PIA, Co-Contra Variance Generics konularına değinilmektedir.

2. 22.Haziran.2010/Salı: .Net 4.0 ile Paralel Programlama : ( 2 Saat ) Uzun süredir ev bilgisayarlarımız dahil en az iki çekirdekli sistemler üzerinde çalışabiliyoruz. Son zamanlarda 8 çekirdeğe kadar çıkabilen yeni nesil işlemciler üzerinde paralel programlama yeteneklerini sonuna kadar kullanıp daha performanslı, hızlı, verimli ve ölçeklenebilir uygulamalar geliştirmeye ne dersiniz? İşte tam size göre bir eğitim. Bu eğitim ile .Net 4.0 kütüphanelerini kullanarak kolay bir şekilde nasıl paralel programlama yapabileceğinizi göreceksiniz.

3. 20.Temmuz.2010/Salı: WCF ile Servis Yaklaşımı : (2 Saat) .Net 3.0 ile birlikte duyurulan ve tek bir servis geliştirme metodolojisi sunarak daha önceki dağıtık mimari geliştirme tiplerini (Xml Web Services, .Net Remoting, MSMQ vb...) bir çatı altında birleştiren Windows Communication Foundation konulu eğitimdir. Eğitimde özellikle .Net 4.0 ile birlikte gelen yeniliklere de değinilmekte olup asıl amaç WCF ile uygulama geliştirme şekillerinden bir kaçını göstermek ve tanıtmaktır.

4. 20.Ağustos.2010/Cuma: WCF Eco System : (3 Saat ) WCF alt yapısı üzerine kurulu olan WCF Eco System içerisinde Data Services, Workflow Services, RIA Services, WebHttp Services ve Core Services tipleri yer almaktadır. Bu eğitimde Data Services, Workflow Services, RIA Services ve WebHttp Services konulu örnekler geliştirilmekte olup, söz konusu alt yapı ile değerlendirilebilecek hazır servis modelleri irdelenmektedir.

5. 20.Eylül.2010/Pazartesi: Windows Server AppFabric : (2 Saat) Bu eğitimde WCF ve Workflow servis örneklerinin izlenmesi, sorunların teşhis edilmesi, örneklerin yaşam döngülerinin takibi, konfigurasyon ayarlarının belirlenmesi ve pek çok yönetimsel konuda geliştiriciler ile IT yöneticilerinin daha kolay anlaşabilmelerini de sağlayan Dublin kod adlı Windows Server AppFabric ürün ailesi incelenmektedir. Özellikle IIS üzerine gelen eklentiler ile söz konusu yönetsel işlemlerin nasıl yapılabildiği derinlemesine incelenmektedir.

6. 20.Ekim.2010/Çarşamba: Worfklow Foundation 4.0 : (3 Saat) WF 4.0 beraberinde pek çok köklü yenilik ile gelmektedir. Geliştirilen Base Activity Library, paralel programlama desteği, veri akışı için gelen Argument, Variable gibi kavramlar ve daha pek çoğunun ele alındığı eğitimde basit örnekler ile WF modelin tanıtılmaya çalışılmaktadır.

7. 23.Kasım.2010/Salı: Asp.Net 4.0 : (3 Saat) Web Programlama’ nın .Net 4.0 ile birlikte gelen yeni yüzünü görmeye hazır mısınız? Pek çok yeni özellik ile birlikte gelen Asp.Net 4.0’ ın anlatıldığı bu eğitimde, temelden orta seviyeye kadar basit bir web uygulaması tasarlanmakta ve konunun daha iyi kavranabilmesi amaçlanmaktadır.

8. 20.Aralık.2010/Pazartesi: Visual Basic 2010 : ( 2 Saat) Bu eğitimde Visual Basic 2010 programlama dili ile birlikte gelen pek çok yeni özellik üzerinde durulmakta ve geliştirilen örnekler ile bu kavramlar pekiştirilmeye çalışılmaktadır. Bu noktada AutoImplemented Properties, Collection Initializers, Implicit Line Continuation, Mutlipe Lambda Expressions, Dynamic keyword, Type Equivalance Support gibi konular üzerinde durulmaktadır.

9. 20.Ocak.2011/Perşembe: WPF 4.0 ile Windows Programlama : (3 Saat) .Net 3.0 ile birlikte duyurulan Windows Presentation Foundation modeli ile zengin kullanıcı deneyimine sahip windows uygulamaları tasarlanabilmektedir. Özellikle Windows 7 üzerinde en iyi kullanıcı deneyimini sunan WPF 4.0 ile birlikte gelen yenilikleri öğrenmeye ne dersiniz?

Microsoft E-Bültenlerine Kayıt Olun | Kaydınızı Silin | Profilinizi Güncelleyin
© 2010 Microsoft Corporation
Kullanım Koşulları | Ticari Markalar | Gizlilik

Microsoft

 
Alt

Workflow Services - Custom Authorization

Pazartesi, 22 Mart 2010 13:30 by bsenyurt

Merhaba Arkadaşlar,

Aşçılık zevkli ama bir o kadarda zor bir zanaattır. Hatta bazen o kadar zor bir zanaat olur ki, aşcının aldığı maaşı pek çok yazılımcı iki yılda kazanamaz. Tabi bu tip aşçılar işin ehli olan kişilerdir. Heleki tek bir mutfak değilde dünya mutfağının seçkin olanlarına ait becerileri bulunanlara paha biçilemez. Türk Mutfağından Japon mutfağına, Meksika yemeklerinden İtalyan spesiyallerine, Fransız tatlılarından Okyanus deniz ürünlerine ve daha nicelerine...Tabi bir aşçı için olmassa olmazlardan biriside yemeği için gerekli olan malzemelerin kalitesidir. Kaliteli zeytinyağı, hamur ve baharat ile yapılan spagettinin, kalitesiz olanlar ile yapılanı arasında dağlar kadar fark olabilir. Spagetti demişken bu günkü yazımızda neler yapacağımıza da bir bakalım dilerseniz. Aşçı olarak bu gün elimizde zor bir tarif var. Malzemelerimiz belli ama pişecek olan yemeğin yapımı biraz zahmetli. Haydi gelin hiç vakit kaybetmeden önlüğümüzü takıp klavyenin başına geçelim.Wink

Bu yazımızda .Net Framework 4.0 tarafında geliştireceğimiz Workflow Service' lerde yetkilendirme işlemini nasıl sağlayabileceğimizi görmeye çalışacağız. Ne yazık ki Authorization işlemini kolaylaştırmak adına hazır bir yapı mevcut değil. Bu nedenle biraz kodlama yapmamız ve çalışma zamanının işleyişine bu şekilde müdahale etmemiz gerekiyor. Hatta yapacağımız özelleştirme öylesine etkili olacak ki, aradan Doğrulamayı(Authentication) bile çıkaracağız farkına varmadan. Surprised Ama önce yemek için gerekli malzemelerimizin neler olduğuna bir bakalım.

  • Bir adet Workflow Service.
  • Bir adet konfigurasyon dosyası(Web.config).
  • System.IdentityModel.dll referansı.
  • ServiceAuthorizationManager türevli bir sınıf.
  • Windows üzerinde tanımlanmış roller ve bu roller içerisinde yer alan kullanıcılar.

Tabiki malzemeleri tedarik etmek yeterli değil. Birde tarifi bilmek lazım Wink Öncelikli olarak yetkilendirme işlemini üstelenen bir sınıf yazmamız gerekiyor. Çok doğal olarak bu sınıfın Workflow Service çalışma zamanı tarafından değerlendirilebilmesi için konfigurasyon dosyası üzerinde de gerekli düzenlemeleri yapmalıyız. Sonrasında ise işi istemci tarafından gelen taleplere bırakıyor olacağız. İşe ilk olarak aşağıdaki gibi bir Workflow Service projemiz olduğunu varsayarak başlayalım.

Calculus.xamlx içeriğimiz ise aşağıdaki gibidir;(Sadece Sequence elementi içeriği verilmiştir)

<p:Sequence DisplayName="Sequential Service" sad:XamlDebuggerXmlReader.FileName="D:\Projects\Workflow Foundation 4.0\UsingCustomAuthorization\UsingCustomAuthorization\CalculusService.xamlx" sap:VirtualizedContainerService.HintSize="277,336">
    <p:Sequence.Variables>
      <p:Variable x:TypeArguments="CorrelationHandle" Name="handle" />
      <p:Variable x:TypeArguments="x:Int32" Name="X" />
      <p:Variable x:TypeArguments="x:Int32" Name="Y" />
      <p:Variable x:TypeArguments="x:Int32" Name="Sum" />
    </p:Sequence.Variables>
    <sap:WorkflowViewStateService.ViewState>
      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
        <x:Boolean x:Key="IsExpanded">True</x:Boolean>
      </scg3:Dictionary>
    </sap:WorkflowViewStateService.ViewState>
    <Receive x:Name="__ReferenceID0" CanCreateInstance="True" DisplayName="ReceiveRequest" sap:VirtualizedContainerService.HintSize="255,86" OperationName="SumOp" ServiceContractName="p1:IService">
      <Receive.CorrelatesOn>
        <MessageQuerySet />
      </Receive.CorrelatesOn>
      <Receive.CorrelationInitializers>
        <RequestReplyCorrelationInitializer CorrelationHandle="[handle]" />
      </Receive.CorrelationInitializers>
      <ReceiveParametersContent>
        <p:OutArgument x:TypeArguments="x:Int32" x:Key="XValue">[X]</p:OutArgument>
        <p:OutArgument x:TypeArguments="x:Int32" x:Key="YValue">[Y]</p:OutArgument>
      </ReceiveParametersContent>
    </Receive>
    <SendReply Request="{x:Reference __ReferenceID0}" DisplayName="SendResponse" sap:VirtualizedContainerService.HintSize="255,86">
      <SendParametersContent>
        <p:InArgument x:TypeArguments="x:Int32" x:Key="SumResult">[X + Y]</p:InArgument>
      </SendParametersContent>
    </SendReply>
  </p:Sequence>

Aslında Calculus isimli Workflow Service içerisinde yer alan SumOp isimli operasyonun görevi çok basit ve bellidir. Int32 tipinden iki sayısal değerin toplanması ve sonucunun istemci tarafına geri döndürülmesi. Bizim hedefimiz sadece yetkisi olan kişilerin bu operasyonu çalıştırmasıdır. Bu durumda güvenlik ile ilişkili olarak yetki kontrolünün özel bir sınıf tarafından yapılması gerekmektedir. Söz konusu sınıf System.ServiceModel isim alanı(Namespace) altında yer alan ServiceAuthorizationManager tipinden türetilmelidir. İçeriğini ise çok sade olarak aşağıdaki gibi tasarlayabiliriz.

using System.Collections.Generic;
using System.Security.Principal;
using System.ServiceModel;

namespace UsingCustomAuthorization
{
    public class Authorizer
        : ServiceAuthorizationManager
    {
        protected override bool CheckAccessCore(OperationContext operationContext)
        {
            var authCtx = operationContext.ServiceSecurityContext.AuthorizationContext;
            var identities=(List<IIdentity>)authCtx.Properties["Identities"];

            foreach (var identity in identities)
            {
                var winIdentity = identity as WindowsIdentity;
                if (winIdentity != null)
                {
                    var winPrincipal = new WindowsPrincipal(winIdentity);
                    return winPrincipal.IsInRole("Administrators");
                }
            }

            return false;
        }
    }
}

Authorizer sınıfı içerisinde CheckAccessCore metodu ezilmiş ve parametre olarak gelen operationContext değişkeninden yararlanarak gerekli yetki kontrolü yapılmıştır. Buna göre Workflow Service' ten talepte bulunan bir Windows kullanıcısı, servisin host edildiği makinede tanımlı ise, Administrators rolünde olup olmadığı kontrol edilmekte ve buna göre geriye true veya false değeri döndürülmektedir. Tahmin edileceği üzere CheckAccessCore metodunun geriye false değer döndürmesi güvenlik hatasına yol açacaktır. Burada unutulmaması gereken bir noktayı da hatırlatmak yarar var. Örneğimizde konuyu son derece basit bir şekilde ele almak istediğimizden, doğrudan Administrator rolünün kontrolünü yapıp işin içinden sıyrılmaktayız. Oysaki yetki kontrolü için harici bir listeden yararlanılabilir. Bu liste web.config dosyasında appSettings kısmında tutulabileceği gibi bir Text dosya içerisinde veya veritabanı üzerindeki bir tabloda konuşlandırılabilir. Yinede varmak istediğimiz noktayı anladığınızı düşünerek devam ediyorum.

Sırada çalışma zamanı için Authorizer sınıfının yetki kontrolü amacıyla kullanılacağını bildirmemiz gerekiyor. Bunun için web.config dosyasını aşağıdaki şekilde düzenlememiz yeterli olacaktır.(Bu arada projemize System.IdentityModel.dll assembly' ını referans etmeyi unutmamalıyız. Aksi takdirde authCtx üzerinden hiç bir özelliğe erişemeyiz)

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceAuthorization serviceAuthorizationManagerType="UsingCustomAuthorization.Authorizer, UsingCustomAuthorization"/>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add scheme="http" binding="wsHttpBinding"/>
    </protocolMapping>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
</configuration>

Dikkat edileceği üzere serviceAuthorization elementi ile yetkilendirme davranışını ele alacak Authorizer tipi belirlenmiştir. Ayrıca iletişimin güvenli olmasını sağlamak adına protocolMapping sekmesinde wsHttpBinding bağlayıcı tipinin kullanılacağı bildirilmiştir. İşte bu kadar. Wink Artık yemeğimizi orta ateşte 40 dakika kadar pişirip servis edebiliriz. Tabi servis etmeden önce tadına bakmak gerekmektedir. Nasıl mı?

Öncelikli olarak Administrator rolünde olan ve olmayan iki test kullanıcımız olduğunu düşünelim. Ben, örneği geliştirmekte olduğum makinede bu amaçla bsenyurt ve runi isimli iki kullanıcı oluşturdum. Bu kullanıcılardan bsenyurt Administrator rolünde iken runi User rolü içerisinde yer almakta. Dolayısıyla test sonuçlarımıza göre runi isimli kullanıcı talebi karşılığında Access Denied hata mesajını almalı. Bakalım gerçektende böylemi oldu?

WcfTestClient uygulamamızı Run As.. komutu yardımıyla önce bsenyurt kullanıcısı ile çalıştıralım. Eğer Asp.Net Developement Server' ı Visual Studio ortamına Attach' larsak CheckAccessCore metodu içeriğini de debug edebiliriz. Buna göre debug modunda aşağıdaki sonuçlar ile karşılaşırız.

Görüldüğü üzere bsenyurt kullanıcısı doğrulanmıştır. IsAuthenticated değerinin true olduğuna dikkat edelim. Şimdi WcfTestClient uygulamasının sonuç ekranına bakarsak toplama işleminin başarılı bir şekilde gerçekleştirildiğini görebiliriz.

Şimdi de WcfTestClient aracını Runi isimli kullanıcı ile çalıştıralım. Debug modda aşağıdaki sonuçlar ile karşılaşırız.

Tahmin edileceği üzere Runi isimli kullanıcı da doğrulanmıştır. Nitekim servisin çalıştırıldığı makine de tanımlı bir Windows kullanıcısıdır. Ancak WcfTestClient uygulaması üzerinden bir toplama işlemi talebinde bulunulduğunda hata mesajı ile karşılaşılacaktır.

Volaaaaa!!! Bu çok doğaldır. Nitekim Runi isimli kullanıcı Administrators grubuna dahil değildir ve bu yüzden yetki kontrolünden geçememiştir.

Yapmış olduğumuz bu çalışmaya göre bir Workflow Service' ini host ettiğimiz sunucu üzerindeki Windows kullanıcılarından ve dahil oldukları grup bilgilerinden yararlanarak az bir kodlama ile doğrulama ve yetkilendirme işlemlerini gerçekleştirebiliriz. Afiyet olsun Wink

UsingCustomAuthorization_RC.rar (17,67 kb) [Örnek Visual Studio 2010 Ultimate RC sürümü üzerinde geliştirilmiş ve test edilmiştir]

.Net Remoting Dünyasından WCF' e Geçmek

Pazartesi, 3 Aralık 2007 04:23 by bsenyurt

Windows tabanlı olan Servis Yönelimli Mimari(Service Oriented Architecture) tekniklerinden biriside .Net Remoting' dir. .Net Remoting mimarisi ağırlıklı olarak TCP bazlı ve Binary tabanlı paket iletiminde kullanılır. En büyük özelliklerinden birisi, sadece Windows işletim sistemlerinden oluşan ağlarda koşabilmesidir. Elbette HTTP üzerinden SOAP-Simple Object Access Protocol formatına uygun alt yapı kurulmasıda mümkündür. Bu sayede internet ağındada ektin şekilde kullanılabilir. Ancak Windows bağımlı olması platform bağımsızlığını ortadan kaldırmaktadır. Günümüzde WCF(Windows Communication Foundation) gibi daha ölçeklenebilir(Scalable), birleştirilmiş(Unified) bir Servis Yönelimli Mimari(SOA) açılımıda mevcuttur. Bu durumda geliştiricilerin karşısına önemli bazı sorular ve sorunlar çıkmaktadır. İşte bunlardan bir kaçı;

  • Var olan .Net Remoting alt yapısı, WCF tabanlı bir hale dönüştürülebilir mi?
  • Dönüştürülürse ne gibi düzenlemeler yapmak gerekir?
  • Sıfırdan WCF tabanlı bir model geliştirmek yerine, .Net Remoting WCF'e göç etmek mantıklı mıdır?
  • .Net Framework 2.0 hatta 1.1 uyumlu sistemler üzerine kurulmuş senaryolarda, var olan .Net Remoting uygulamalarında yapılacak WCF düzenlemeleri geçerli olacak mıdır? Yoksa bu makinelere Framework 3.0 yüklenmeli midir?

Bu sorular farklı açılardan bakıldığında artabilir. İlerleyen kısımlarda bu sorulara ve beraberinde gelen sorunlara cevap bulmamızı kolaylaştıracak şekilde ilerlemeye çalışacağız.

NOT : Windows Communication Foundation, .Net Remoting, Web Servisleri, MSMQ, Named Pipes, WSE gibi pek çok dağıtık mimari modelini tek bir çatı altında birleştirip sunabilmesiyle ön plana çıkmış bir Servis Yönelimli Mimari(Service Oriented Architecture) alt yapısıdır. Bu alt yapı, önceki mimarilerde daha fazla kodlama gerektiren yada geliştiricileri zorlayan standartların(Örneğin WS-Specifications) kolay ve etkin bir şekilde uygulanabilmesini hatta bir arada tutulabilmesine de izin vermektedir.

Bazı durumlarda çalışmakta olan sistemi yeni bir mimariye adapte etmenin maliyeti çok yüksek olabilir. Söz gelimi ölçek olarak çok büyük çaplı projelerde sistemi yeniden tasarlamak son derece sancılı bir süreç olabilir. Ancak böyle bir durum söz konusu değilse karşımızda iki alternatif olacaktır. Var olan sistemi modifiye ederek WCF' e taşımak yada sıfırdan tasarlamak. Aslında var olan bir .Net Remoting alt yapısını bir kaç küçük değişiklik ile WCF' e taşımak son derece kolaydır. Herşeyden önce .Net Remoting içerisinde yer alan temel parçaları göz önüne alarak ilerlemekte yarar vardır.

.Net Remoting ile hazırlanmış bir sistemde istemcilerin(Clients) kullanacakları fonksiyonellikleri barındıran uzak nesneler(Remote Objects) bir sunucu(Server) uygulama üzerinden Client Activated Object yada Server Activated Object modeline uygun olacak şekilde yayınlanırlar. Hatta SAO nesneleride Singleton veya SingleCall olarak tasarlanırlar. İstemci uygulamalar aslında uzak nesne referanslarını kullanırken bu referanslar Marshal By Reference modeline göre sunucu üzerinde örneklenirler. Bir başka deyişle istemci uzak nesneyi sanki kendi uygulama alanı(Application Domain) içerisindeymiş gibi kullanırlarken, tüm işlevler sunucu üzerinde gerçekleşmektedir.

Çok doğal olarak burada istemci ve sunucu arasındaki mesaj trafiğinin ortak bir zemine oturtulması şarttır. Bu nedenle genellikle istemci ve sunucu uygulamalar hizmete ait nesne tasarımını içeren şartnamelerin yer aldığı bir arayüz(Interface) tipini ortaklaşa referans ederler. Böylece servis tarafındaki fonkisyonelliklerin iç yapılarının değiştirilmesi halinde istemciler üzerinde yeniden güncelleme yapılmasına gerek kalmayacaktır. Ayrıca istemciler sadece arayüzü görebildiklerinden, çağırdıkları fonksiyonelliklerin iç yapısını bilmeyeceklerdir ki buda servis kodunun tam olarak istemci tarafından görülmesini engellemektedir. Zaten WCF' in tamamen arayüzlere dayalı bir sistemi önermesinin ve kullanmasının en önemli nedenleride bunlardır.

Bu noktada geliştirici tarafından tanımlanan serileştirilebilir tiplerinde (Serializable Types) ortak bir sınıf kütüphanesi(Class Library) üzerinde olması gerekmektedir. Serileştirilebilir nesneler aslında servis tarafında örneklenip sadece varlıkları(Entities) istemci tarafına aktarılan örnekler olarak düşünülebilir. Söz gelimi istemcinin talep ettiği bir ürünün, Product isimli bir sınıfa ait nesne örneği olacak şekilde servis tarafında doldurulması ve istemciden elde edilmesi buna örnek olarak verilebilir. Burada istemcinin talebi sonrasında servis tarafından dönen veriler Product isimli sınıfın özellik(Property) veya alanlarının(Fields) değerleridir. Serileştirilebilir nesnelerin WCF mimarisinde ele alınması çok daha kolaydır. Özellikle versiyonlamanın(Versioning) WCF üzerinden gerçekleştirilmesi daha esnektir.

NOT : Makalenin konusu .Net Remoting' den WCF' e bir iki adımda taşınmanın nasıl sağlanabileceğini göstermek olduğundan, .Net Remoting ve WCF mimarilerinin çok geniş detayları göz ardı edilmektedir.

Artık bir örnek üzerinden hareket ederek devam edebiliriz. Öncelikli olarak bir .Net Remoting uygulamasını Visual Studio 2005 üzerinden geliştiriyor olacağız. İlk olarak istemci ve servis uygulamasının ortaklaşa kullanacağı sınıf kütüphanesini(Class Library) tasarlayarak işe başlanabilir. Sınıf kütüphanesi içerisindeki tiplere ait sınıf diyagramı(Class Diagram) ve kod içerikleri aşağıdaki gibidir.

IProductManager arayüzü(Interface);

using System;

namespace AdvLibrary
{
    public interface IProductManager
    {
        Product GetProductInfo(int productId);
    }
}

Örneğin daha basit olarak ele alınabilmesi için arayüz(Interface) tanımlamasında, geriye Product tipinden nesne örneği döndürebilen ve integer tipinden bir parametre alabilen GetProductInfo isimli bir metod bildirimi yer almaktadır.

Product sınıfı(Class);

using System;

namespace AdvLibrary
{
    [Serializable]
    public class Product
    {
        public int Id;
        public string Name;
        public double ListPrice;
    }
}

Product isimli sınıf içerisinde bir ürüne ait Id, Name ve ListPrice değerleri tutulmaktadır. Bununla birlikte Product sınıfı için dikkat çekici en önemli özelliklerden biriside Serializable niteliği(attribute) ile imzalanmış olmasıdır. Burada açık bir şekilde Product sınıfına ait nesne örneklerinin Marshal By Value olarak sunucudan istemciye serileşerek taşınabileceği garanti altına alınmaktadır.

Servis tarafında yer alan program, söz konusu örnekte bir Console uygulaması olarak tasarlanmaktadır. Bu uygulamanın çok doğal olarak yukarıda tasarlanan tipleri içeren AdvLibrary isimli sınıf kütüphanesini(Class Library) referans ediyor olması gerekmektedir. Nitekim sunucu uygulama içerisinde asıl iş yapan sınıfın uyarlayacağı arayüz ve kullanacağı serileştirilebilir tip bu sınıf kütüphanesi içerisinde bulunmaktadır.

NOT : Gerçek hayat senaryolarında en çok tercih edilen .Net Remoting yöntemi, sunucu uygulamasını bir Windows Service olarak tasarlamaktadır. Bu yönetimi daha güçlü olan, ölçeklenebilir ve güvenli bir uygulama seçimidir. Bunun dışında IIS(Internet Information Services) üzerinden barındırma(Host) imkanıda bulunmaktadır. Diğer taraftan sunucu uygulama bir Windows uygulaması hatta bu örnekte olduğu gibi bir Console uygulamasıda olabilir. 

Tekrar sunucu uygulamasına dönülecek olursa, IProductManager isimli arayüzü(Interface) uygulayan uzak nesne sınıfının aşağıdaki gibi tasarlanabileceği düşünülebilir.

using System;
using AdvLibrary;
using System.Data.SqlClient;

namespace ServerApp
{
    public class ProductManager:MarshalByRefObject,IProductManager
    {
        public ProductManager()
        {
            Console.WriteLine("ProductManager nesnesi oluşturuldu...");
        }   
        #region IProductManager Members

        public Product GetProductInfo(int productId)
        {
            Product prd = null;
            using (SqlConnection conn = new SqlConnection("data source=.;database=AdventureWorks;integrated security=SSPI"))
            {
                using (SqlCommand cmd = new SqlCommand("Select ProductId,Name,ListPrice,SellStartDate From Production.Product Where ProductId=@PrdId", conn))
                {
                    cmd.Parameters.AddWithValue("@PrdId",productId);
                    conn.Open();
                    SqlDataReader reader = cmd.ExecuteReader();
                    if (reader.Read())
                    {
                        prd = new Product();
                        prd.Id = productId;
                        prd.Name = reader["Name"].ToString();
                        prd.ListPrice = Convert.ToDouble(reader["ListPrice"]);
                    }
                    reader.Close();
                }
            }
            return prd;
        }

        #endregion
    }
}

Bu sınıf içerisinde yer alan metod uyarlamasında AdventureWorks isimli veritabanına gidilmekte ve Production şemasında(Schema) yer alan Product tablosundan parametre olarak gelen ProductID değerine sahip olan ürün bilgisi geriye döndürülmektedir. Nesne oluşumlarının kolay takip edilebilmesi amacıyla ProductManager sınıfı içerisine birde varsayılan yapıcı metod(Default Constructor) ilave edilmiştir. Burada dikkat edilmesi gereken nokta sınıfın IProductManager isimli arayüz dışında MarshalByRefObject sınıfından türemiş olmasıdır.

Sunucu tarafındaki Remoting ayarlarını konfigurasyon bazlı olarak aşağıdaki config dosyasında tanımlayabiliriz.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.runtime.remoting>
        <application>
            <channels>
                <channel ref="Tcp Server" port="4500"/>
            </channels>
            <service>
                <wellknown mode="Singleton" type="ServerApp.ProductManager,ServerApp" objectUri="ProductMng.rem" />
            </service>
        </application>
    </system.runtime.remoting>
</configuration>

Konfigurasyon dosyası içerisinde tahmin edileceği üzere Wellknown bir nesne tanımı yapılmıştır. Bu nesne Singleton modeline göre çalışacaktır. Bir başka deyişle tüm istemcilerin talepleri aynı uzak nesne referansı üzerinden karşılanmaktadır. Sunucu uygulama, uzak nesne(Remote Object) için TCP bazlı 4500 numaralı portu kullanıma sunmaktadır. Buradaki konfigurasyon ayarlarının sunucu uygulama üzerinde tesis edilmesi içinde aşağıdaki başlangıç kodlarının yazılması yeterlidir.

using System;
using AdvLibrary;
using System.Runtime.Remoting;

namespace ServerApp
{
    class Program
    {
        static void Main(string[] args)
        {
            RemotingConfiguration.Configure("..\\..\\App.config",false);
            Console.WriteLine("Sunucu dinlemede. Kapatmak için bir tuşa basınız...");
            Console.ReadLine();
        }
    }
}

Bu noktada şunu hatırlamakta yarar vardır; sunucu uygulama çalıştığı sürece istemcilerden gelecek taleplere cevap verilebilir.

Gelelim istemci uygulamaya. Herşeyden önce istemci uygulamanında arayüzü barındıran ortak kütüphaneyi referans etmesi gerekmektedir. Diğer taraftan istemci uygulamanın kod içeriği aşağıdaki gibi olabilir.

using System;
using AdvLibrary;

namespace ClientApp
{
    class Program
    {
        static void Main(string[] args)
        {
            IProductManager prdMng = (IProductManager)Activator.GetObject( typeof(IProductManager), "tcp://localhost:4500/ProductMng.rem");
            Product prd=prdMng.GetProductInfo(1);
            Console.WriteLine(prd.Name+" "+prd.ListPrice.ToString("C2"));
            Console.ReadLine();
        }
    }
}

Burada en kritik nokta, arayüz(interface) tercihi nedeniyle Activator sınıfının GetObject metodunun kullanılmasıdır. Bu metod ile aslında ikinci parametre ile belirtilen adresten ProductMng.rem isimli tanımlayıcının(Uniform Resource Identifier) işaret ettiği uzak nesne referansı talep edilmektedir. İstemciye döndürülecek olan referansın taşınabileceği tek yer IProductManager arayüzü olduğundan da metodun dönüş tipi bilinçli(Explicit) olarak çevrilmektedir. Buraya kadar yapılan hazırlıklar sonucunda test işlemi yapılırsa aşağıdakine benzer çıktılar elde edilir.

Görüldüğü gibi istemciler başarılı bir şekilde sunucu üzerinden taleplerini karşılayabilmektedirler. (Burada oluşturulan sistemin düzgün çalıştığının kontrol edilmesi için sunucu uygulama çalıştırılmadan bir istemcinin çalıştırılması denenebilir. Eğer gerçekten sunucu üzerindeki nesne kullanılmaya çalışılıyorsa çalışma zamanında istemci tarafında "No Connection Could Be Made, Becouse the Target Machine Actively Refused It..." hatası alınır.)

Buraya kadar anlatılanlar basit olarak bir .Net Remoting uygulamasının alt yapısını özetlemektedir. Aşağıdaki şekil üzerinden, yapılanlar ve sonuçları tartışılabilir.

Şekilde .Net Remoting içerisinde 50000 metre yukarıdan bakıldığında göze çarpan etkenler betimlenmeye çalışılmıştır. Şimdi bu sistemi Windows Communication Foundation alt yapısına taşımaya çalışıyor olacağız.

İlk yapılması gereken servis tarafında sunulmak istenen fonksiyonellikleri tanımlayacak bir sözleşme(Contract) oluşturmaktır. Burada söz konusu olan servis sözleşmesi(Service Contract) bir arayüze rahatlıkla uygulanabilir. Tek yapılması gereken System.ServiceModel.dll isimli .Net Framework 3.0 assembly' ının referans edilmesi ve ServiceContract ile OperationContract niteliklerinin(attributes) kullanılmasıdır. Aşağıdaki şekilde Visual Studio 2005 üzerinden söz konusu assembly' ın referans edilişi görülmektedir.

Bu işlemin ardından IProductManager isimli arayüzün yapısı aşağıdaki gibi değiştirilmelidir.

using System;
using System.ServiceModel;

namespace AdvLibrary
{
    [ServiceContract]
    public interface IProductManager
    {
        [OperationContract]
        Product GetProductInfo(int productId);
    }
}

Bu değişiklik arayüzün Windows Communication Foundation uyumlu bir serviş sözleşmesi(Service Contract) olması için yeterlidir. ServiceContract niteliği ile tanımlanan servis sözleşmesi içerisinden dışarıya sunulabilecek fonksiyonelliklerin tamamı OperationContract niteliği(attribute) ile imzalanmalıdır. Yapılan bu değişiklik her ne kadar ortak kütüphane içerisinde olsada sonuç itibariyle tüm istemcilere gerekli assembly' ın yeniden dağıtılması gerekmektedir. Ama zaten bu göz önüne alınması gereken bir aşamadır.

Gelelim sunucu tarafına. Sunucu tarafındada çok doğal olarak yapılması gereken bazı işlemler vardır. Herşeyden önce konfigurasyon içeriğinin WCF mimarisine uyumlu olacak şekilde değiştirilmesi gerekmektedir. Bu amaçla sunucu uygulama tarafındaki App.config dosyasının içeriği aşağıdaki gibi yenilenmelidir.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <!--<system.runtime.remoting>
                <application>
                    <channels>
                        <channel ref="Tcp Server" port="4500"/>
                    </channels>
                    <service>
                        <wellknown mode="Singleton" type="ServerApp.ProductManager,ServerApp" objectUri="ProductMng.rem" />
                    </service>
                </application>
            </system.runtime.remoting>-->
    <system.serviceModel>
        <services>
            <service name="ServerApp.ProductManager">
                <endpoint address="net.tcp://localhost:4500/ProductMng" binding="netTcpBinding" contract="AdvLibrary.IProductManager" />
            </service>
        </services>
    </system.serviceModel>
</configuration>

Windows Communication Foundation(WCF) mimarisinde servis için belkide en önemli kavram EndPoint' dir. EndPoint içerisinde WCF mimarisinin ABC' si yer almaktadır. AddressBindingConfiguration yardımıyla servisin hangi lokasyondan, hangi protokol ile, hangi nesneyi nasıl ve ne şekilde sunduğu belirtilmektedir. .Net Remoting bazlı geliştirilen örnekte TCP bazlı ve Binary serileştirme yapan bir sistem kullanıldığından bu özellikleri bünyesinde barındıran bir tipin WCF tarafında ele alınması gerekmektedir. Bu işi NetTcpBinding isimli sınıf üstlenmektedir. Bu aynı zamanda bağlayıcı tiptir(Binding Type). Contract bilgisi ile tahmin edileceği üzere servisin dış ortama sunduğu sözleşme ve operasyonları belirtilmektedir. Son olarak Address bilgisi ile servis üzerinde sunulan nesneye hangi adres üzerinden erişilebileceği belirtilmektedir.

NOT : WCF mimarisinde bir servis birden fazla EndPoint sunabilir. Bu geliştiricilere senaryoya göre birden fazla bağlayıcı tipin(Binding Type) ve dolayısıyla imkanın sunulabildiği bir ortam hazrılayacaktır. Söz gelimi bir servis uygulaması WCF' e göre yazıldığında, MSMQ, TCP, HTTPS üzerinden vb... hizmet verebilecek mesaj seviyesinde(Message Level) yada iletişim seviyesinde(Transport Level) korumalı hizmetleri sunabilir. Üstelik bunlar için ayrı ayrı uygulama çeşitleri tasarlanmasına gerek kalmaz. Bir başka deyişle bu tip bir senaryo için ayrı bir .Net Remoting, Xml Web Service veya MSMQ uygulaması yazılmasına gerek yoktur. İşte WCF' in birleştirici rolünün önemi burada belirgin bir biçimde ortaya çıkmaktadır.

Elbetteki sunucu uygulamanın kodlarınıda aşağıdaki gibi değiştirmek gerekmektedir. Artık ServiceHost isimli sınıf başlatıcı rolü üstlenmektedir.

using System;
using AdvLibrary;
//using System.Runtime.Remoting;
using System.ServiceModel;

namespace ServerApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //RemotingConfiguration.Configure("..\\..\\App.config",false);
            ServiceHost host = new ServiceHost(typeof(ProductManager));
            host.Open();
            Console.WriteLine("Sunucu dinlemede. Kapatmak için bir tuşa basınız...");
            Console.ReadLine();
            host.Close();
        }
    }
}

Örnek koda göre ServiceHost nesne örneği, ProductManager isimli sınıfı uzak nesne olarak hizmete açmaktadır. Open metoduna yapılan çağrıdan sonra, sunucu uygulama istemciden gelecek olan talepleri dinleyecek konuma gelmektedir. Close metoduna yapılan çağrı sonrasında ise servis kapatılmaktadır. Elbette ServiceHost sınıfının kullanılabilmesi için System.ServiceModel.dll assembly' ının sunucu uygulama tarafınada referans edilmesi gerekmektedir.

Peki istemci tarafında neler yapılmalıdır? Herşeyden önce istemci tarafında gerekli ayarların konfigurasyon bazlı olacak şekilde geliştirilmesi önerilmektedir. Bu amaçla istemci tarafına eklenecek olan bir konfigurasyon dosyasının içeriği, örneğe göre aşağıdaki gibi tasarlanabilir.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <client>
            <endpoint name="ProductMng" address="net.tcp://localhost:4500/ProductMng" binding="netTcpBinding" contract="AdvLibrary.IProductManager"/>
        </client>
    </system.serviceModel>
</configuration>

Konfigurasyon içeriğine bakıldığında dikkat edileceği üzere yine bir EndPoint tanımlaması yapılmaktadır. Bu EndPoint aslında istemcinin bağlantı kuracağı servis tarafındaki noktayı tanımlamaktadır. İstemci tarafındaki kod içeriği ise aşağıdaki gibi geliştirilebilir.

using System;
using AdvLibrary;
using System.ServiceModel;

namespace ClientApp
{
    class Program
    {
        static void Main(string[] args)
        {
            //IProductManager prdMng = (IProductManager)Activator.GetObject(typeof(IProductManager), "tcp://localhost:4500/ProductMng.rem");
            //Product prd=prdMng.GetProductInfo(1);

            ChannelFactory<IProductManager> chn = new ChannelFactory<IProductManager>("ProductMng");
            IProductManager prdMng=chn.CreateChannel();
            Product prd = prdMng.GetProductInfo(1);
            Console.WriteLine(prd.Name+" "+prd.ListPrice.ToString("C2"));
            Console.ReadLine();
        }
    }
}

ChannelFactory nesne üretimi için gerekli bilgileri, parametre olarak verilen değere göre konfigurasyon dosyasından almaktadır. Böylece servis tarafındaki hangi EndPoint ile konuşabileceğini bilmektedir. CreateChannel metodu önceden hazırlanan ayarlara göre, servis tarafı ile konuşacak olan kanal nesnesini örneklemektedir. Açıkçası CreateChannel metodunun sonucu .Net Remoting için kullanılan Activator.GetObject metodunun ürettiğine benzerdir. Nitekim aşağıdaki ekran görüntüsünden de anlaşılacağı üzere CreateChannel metoduda Transparent bir Proxy üretmektedir. Bu Proxy, çalışma zamanında servis üzerindeki EndPoint ile haberleşmektedir.

Çok doğal olarak proxy nesnesinin üretilmesinde de kullanılan ChannelFactory sınıfı System.ServiceModel isim alanı(Namespace) altındadır. Bu nedenle söz konusu isim alanını içeren assembly' ın istemci uygulamayada referans edilmesi gerekmektedir.

Artık var olan .Net Remoting uygulaması bu bir kaç adım ile WCF formatına çevrilmiştir. Uygulamalar test edildiğinde aşağıdakine benzer sonuçlar alınacaktır.

Elbetteki servisin ve operasyonların davranışları WCF mimarisi içerisinde çok daha geniş bir şekilde ele alınmaktadır. Örnekte bunlara gerek kalmadanda WCF' e geçilebileceği gösterilmektedir. Ancak ele alınması gereken başka noktalarda olabilir.

Örneğin her istemci için birer uzak nesne referansı sunucu üzerinde oluşturulmaktadır. Oysaki tasarlanan .Net Remoting alt yapısında Singleton modeli benimsenmiştir. Bir başka deyişle her istemci talebi(Request) aynı uzak nesne örneği üzerinden karşılanmaktadır. WCF tarafında bu, servis tarafında sunulan uzak nesnenin bir çalışma zamanı(run-time) davranışıdır(Behavior). Dolayısıyla bu davranışın bir nitelik(attribute) yardımıyla belirlenmesi yada konfigurasyon içeriğinde tanımlanması gerekmektedir. Bu sebepten örnekte yer alan ProductManager sınıfı başında ServiceBehavior niteliğinin(attribute) aşağıdaki gibi kullanılması gerekir.

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class ProductManager:MarshalByRefObject,IProductManager

InstanceContextMode enum sabitinin Single olarak belirlenen değeri örnekte ele alınan senrayoya uygun olacak şekilde uzak nesne referanslarının oluşturulmasını sağlamaktadır. Bunun sonucunda çalışma zamanındaki durum aşağıdaki gibi olacaktır.

Bunun dışında binary olarak serileştirilebilen Product sınıfı için herhangibir ekstra çalışma yapılmadığı ortadadır. Nitekim böyle bir çalışma yapılmasına gerek kalmamıştır. Fakat versiyonlama yapıldığı durumlarda WCF mimarisi .Net Remoting' e göre daha efektif bir çözüm sunmaktadır.

Burada versiyonlamanın(Versioning) nasıl sorunlar yaşatabileceğini anlamak önemlidir. Söz gelimi Product isimli serileştirilebilir sınıfın sonradan yazılan ikinci bir versiyonu olduğu ve bu versiyonda işin içerisine SellStartDate isimli yeni bir alan(Field) katıldığı göz önüne alınsın. Eski Product sınıfını kullanan istemcilerin sorunsuz olarak onunla çalışmaya devam etmelerini, yeni versiyonu kullananların ise yeni eklenen alanı ele alabilmelerini sağlamak için kuvvetle muhtemel tasarımı aşağıdaki gibi değiştirmek gerekecektir.

using System;
using System.Runtime.Serialization;

namespace AdvLibrary
{
    [Serializable]
    public class Product:ISerializable
    {
        public int Id;
        public string Name;
        public double ListPrice;
        public DateTime SellStartDate; // Yeni versiyonlar için eklenen alan.
   
        public Product()
        {
   
        }

        public Product(SerializationInfo info, StreamingContext context)
        {
            Id = info.GetInt32("Id");
            Name = info.GetString("Name");
            ListPrice = info.GetDouble("ListPrice");
            // Versiyonlama nedeni ile oluşabilecek hataları görmezden gelmek için bir try...catch
            try
            {
                SellStartDate = info.GetDateTime("SellStartDate");
            }
            catch
            {
            }
        }

        #region ISerializable Members

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Id", Id);
            info.AddValue("Name", Name);
            info.AddValue("ListPrice", ListPrice);
            info.AddValue("SellStartDate", SellStartDate); // Yeni versiyon için ekenen kod satırı
        }
   
        #endregion
    }
}

Burada dikkat edilecek olursa serileştirme işlemleri ISerializable arayüzünün(Interface) kullanılmasıyla özelleştirilerek, değerlerin aktarımı kontrollü bir hale getirilmektedir. Özelleştirme için ISerializable arayüzünün uygulanması haricinde yapıcı metodun(Constructor) aşırı yüklenmiş(Overload) bir versiyonuda ele alınmaktadır. Sorunun detayları çok önemli olmamakla birlikte Windows Communication Foundation içerisinde bu tip versiyonlamalarında kontrol edilebilmesi son derece kolaydır. Tek yapılması gereken aşağıdaki gibi Product sınıfını bir veri sözleşmesi(Data Contract) haline getirmektir.

using System;
using System.Runtime.Serialization;

namespace AdvLibrary
{
    [DataContract]
    public class Product
    {
        [DataMember(IsRequired=true)] // Mutlaka olmalı
        public int Id;

        [DataMember(IsRequired = true)] // Mutlaka olmalı
        public string Name;

        [DataMember(IsRequired = true)] // Mutlaka olmalı
        public double ListPrice;
       
        [DataMember] // Opsiyonel oldu.
        public DateTime SellStartDate; // Yeni versiyonlar için eklenen alan.
    }
}

DataMember niteliği(attribute) varsayılan olarak uygulandığı üyeye opsiyonel bir davranış getirmektedir. Bir başka deyişle çalışma zamanında karışa tarafın bu alanı içermeyen bir tipi kullanması halinde hiç bir problem oluşmayacak ve bu alan görmezden gelinecektir. Tam tersine bu alanı kullanan bir versiyon varsa SellStartDate alanıda hesaba katılacaktır. Bu sayede versiyonlamada çok kolay bir şekilde ele alınabilmektedir. Product sınıfının tasarlanmasında dikkat edilmesi gereken önemli bir nokta vardır. Buna göre DataContract ve DataMember niteliklerinin(attributes) tanımlandıkları isim alanı(Namespace), System.Runtime.Serialization.dll assembly' ı içerisindedir. Dolayısıyla sınıf kütüphanesine bu assembly' ın aşağıdaki ekran görüntüsünde olduğu gibi referans edilmesi gerekmektedir.

Son olarak ele alınması gereken bir durum daha olabilir. İstemci ve servis tarafının .Net Framework 2.0 yüklü sistemler olduğu göz önüne alındığında yapılan son değişikliker sonrasında uygulamalar sorunsuz bir şekilde çalışabilecek midir?( Burada iyimser bir yaklaşım güdülerek .Net Framework 1.1 versiyonu hiç hesaba katılmamıştır.)

NOT : Yukarıdaki referans ekleme kısmında dikkat çeken noktalardan biriside Framework 3.0 için geliştirilmiş pek çok assembly' ın çalışma zamanında(Run Time) v2.0.50727 versiyonuna ihtiyaç duymasıdır. Bir başka deyişle System.ServiceModel veya System.Runtime.Serialization gibi 3.0 assembly' ları, .Net Framework 2.0 yüklü bir makinede belleğe yüklenip çalışabilirler. Nitekim ihtiyaçları olan v2.0.50727 versiyonlu Common Language Runtime(CLR)' dır.

Aslında sistemler üzerinde .Net Framework 3.0' ın yüklü olması sorunun çözümü için yeterlidir. Lakin sadece .Net Framework 2.0 yüklü olan bir sistemde değiştirilen uygulamalar çalıştırılabilirse, bir .Net Framework 3.0 yükleme derdinden kurtulunabilinir. Ancak bunun bir dert olup olmadığıda tartışılması gereken bir vakadır.

Söz konusu durumu test etmek için servis veya istemci uygulamaları, üzerinde .Net Framework 2.0 yüklü olan bir sistemde, System.ServiceModel.dll ve System.Runtime.Serialization.dll assembly' larınıda kopyalayarak çalıştırmak yeterli olacaktır. Başlangıçta servis ve istemci tarafında var olması düşünülen exe, config ve dll dosyaları aşağıdaki gibidir.

Ne yazıkki buradaki dll' lerin hedef bilgisayara(bilgisayarlara) taşınmaları yeterli olmamaktadır. .Net Framework 2.0 yüklü makinede örnek olarak ServerApp uygulaması çalıştırıldığında aşağıdaki ekran görüntüsünde yer alan hata ile karşılaşılabilir.

Bunun üzerine SMDiagnostics.dll isimli assembly' ında hedef bilgisayarda ServerApp ve ClientApp program dosyalarının olduğu yere konması gerekir. Söz konusu assembly hedef programların bulunduğu lokasyona taşındıktan sonra bir deneme daha yapılırsa aşağıdakine benzer bir hata mesajı ile daha karşılaşılabilinir.

Bu hatanın oluşmasının en büyük nedeni, programın çalıştığı makine üzerinde .Net Framework 3.0 yüklü olmadığı için, machine.config' de olması gereken bazı ayarların bulunmayışından kaynaklanmaktadır. Bu nedenle ServiceModelReg aracının kullanılarak gerekli konfigurasyon bilgilerinin hedef makineye yüklenmesi gerekecektir. Bu sebepten komut satırından aşağıdaki gibi bir çalışma yapılmalıdır.

Bu çalışmanın ardından hedef bilgisayarda yer alan konfigurasyon dosyas için gerekli Handler ve Module yüklemeleri gerçekleştirilecektir. Artık herşey halloldu diye düşünülebilir ama bu seferde ServerApp uygulaması çalıştırıldığında aşağıdakine benzer bir hata mesajı daha alınabilir.

Çok doğal olarak System.IdentityModel.dll' ininde kopyalanmış olması gerekecektir. Bu hata beraberinde System.IdentityModel.Selectors.dll isimli assembly' ında yüklenmesini gerektirmektedir. Her iki assembly yüklensede bu kez doğrulama(Authentication) ve yetkilendirme(Authorization) problemleri oluşmaktadır. Bunların çözümü adına config dosyalarında gerekli düzenlemele yapılabilir. Yinede bu sancılı süreç hemen çözümlenemeyecektir. Yazının ilerleyen kısımlarında konunun daha fazla dağılmaması adına bu yöntemler göz ardı edilmiştir.

Sonuç olarak her ne kadar .Net Remoting' den Windows Communication Foundation tarafına geçiş yapmak kolay olsada, gerçek çalışma ortamında özellikle .Net Framework 2.0 yüklü sistemlerde bazı ayarlamaların yapılması gerekmektedir. Bu durum .Net Framework 1.1 yüklü makinelerde tam bir kabus haline gelebilir. Nitekim kopyalanan dll' lerin bazıları CLR 1.1 versiyonunda çalışmayacaktır. Bu nedenle .Net Framework 3.0' ın Redistruable paketinin hedef sistemlere yüklenerek çalışmalara devam edilmesi doğru bir davranış olacaktır. Hatta istemciler için bir setup paketinin hazırlanması ve gerekliliklerden birisi olarak .Net Framework 3.0 seçiminin eklenmesi çok yerinde bir davranıştır. O halde cevaplanması gereken bir soru daha vardır. Bu kadar zahmete girilecekse, sistemin WCF için yeninde yazılması yoluna gidilemez midir? Aslında bu sorunun cevabı daha önceden tasarlanıp kullanılılmakta olan .Net Remoting sistemine bağlıdır. Eğer yazılan çok fazla kod ve birbirlerine bağlı parça var ise, bir iki düzenleme ile WCF' e uyumlu bir sistem oluşturmak son derece kolaydır.

Bu noktalarda vakayı doğru değerlendirip karar vermekte ve gerekirse cevap için profesyonel destek almakta yarar olabilir.Böylece geldik bir makalemizin daha sonuna. Bir sonraki makalemizde görüşünceye dek hepinize mutlu günler dilerim.

FromRemotingToWCF.rar (15,06 kb)