cub-e.net

just coding...

Plug-in'i Debug Etmek

CRM 2015 icerisinde yazmis olduğumuz bir plug-in’i debug etmenin iki temel yolu bulunmakta. Birinci yol calisan sisteme visual studio ile attach olarak yapilan, ikinci yol ise plug-in profiller kullanmak. Profiller icin Microsoft dokümantasyonlarda plug-in performansini ölçmek icin kullaniliyor dese de aslinda 1. Yöntemden daha saglikli olduğunu söyleyebilirim. Ozellikle Online sistemler icin başka çareniz de yok zaten.

Servis’lere Attach olarak Debug Etme

Plug-in’i sisteme kaydettikten sonra visual studio ile nereye attach olacagimizi seçmemiz gerekmekte.

 

Kayit Ayari

Servis

online

w3wp.exe

offline

Microsoft.Crm.Application.Hoster.exe

asynchronous olarak kaydedilmis plug-in’ler (ya da custom workflow’lar)

CrmAsyncService.exe

sandbox (isolation mode)

Microsoft.Crm.Sandbox.WorkerProcess.exe

 

Online : CRM Web arabirimini

Offline : Outllok Client gibi offline yapidaki yazilimlar

 

Kendimize uygun olan secimi yaptıktan sonra geriye bir tek breakpoint’i seçip attach olmak kaliyor.

 

Visual Studio’yu acip “Attach to Process..” diyoruz.

 


Sonra asagidaki ekran goruntusu gelecek ve ilgili servisi seçeceğiz.

 

 


Asagidaki ekran goruntusunde de goruldugu uzere visual studio ilgili yerde devreye girecek ve bizim kodu debug etmemizi saglayacaktir.


 

Islem bu kadar basit sadece dikkat etmeniz gereken noktalar bulunmakta;

1.       Eger disk’e yaz adimini seçerek plug-in’i sisteme kayit ettiyseniz bu plug-in’in debug modda yeni bir versiyonunu ayni dizine kopyalamak icin plug-in üzerinde calistigi servisi yeniden baslatmaniz gerekir.

2.       Plug-in üzerinde değişiklikler yaptiginizda her seferinde registration tool’u ile güncelleme islemini yapin.

3.       Eger plug-in’i bu sekilde test edip butun işlemleri bitirdiyseniz onu veritabanina kaydetmenizi tavsiye ederim. Disk olarak birakmaniz pek önerilen bir yöntem değildir.

4.       Her ne olursa olsun .pdb uzantili dosyalari assembly klasörü içerisinde birakmayin.

5.       Sandbox içindeki bir plug-in’i debug etmek istiyorsaniz asagidaki registery ayarinin 1 (DWORD) değeri tasidigindan emin olun : HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSCRM\SandboxDebugPlugins

Plug-in Profiller’i kullanarak Debug etme

Bu yöntemi kullanmak birçok bakimdan daha avantajli nedeni ise CRM size kullanicinin yaptigi hareketi simule ediyor ve böylece siz bunun üzerinden debug ediyorsunuz. Ayrica ciktilari baskalarina gönderme opsiyonu da bulunmakta. En değerli ozelligi ise plug-in’i derleyip derleyip CRM’e atmak gibi bir derdiniz yok. Yani bir hata mi yakaladiginiz ya da kodun bir yerini mi değiştirmek istiyorsunuz tek yapmaniz gereken degisikligi yapip uygulamaya yeniden bağlanmak ayni kullanici hareketi tekrar simule edilecek ve siz de yaptiginiz degisikligin etkilerini göreceksiniz.

 

Simdi sirasiyla bu işlemi nasil yapacagimiza bakalim. Oncelikle “Plug-in Registration Tool”’u aciyoruz ve işlem yapmak istediğimiz organizasyonu seçiyoruz.

Tool üzerindeki “Install Profiller” düğmesine tikliyoruz. Boylece “Plug-in Profiller”’da listemizde gozukmeye basliyor.

Daha sonra test etmek istediğimiz step’i seçiyoruz ve yine toolbar’da yer alan “Start Profilling” düğmesine basıyoruz. Karsimiza asagidaki gibi “Profiler Settings” ekrani cikiyor.

 

 

Bu adimda iki secenekten birini seçmeniz lazim.

·         Exception: Microsoft, Exception yöntemini önermekte gordugunuz gibi. Bunun anlami ise su kullanici ya da siz plug-in’i tetikledeginizde plug-in calisacak ve sistem size bir hata mesaji gösterecek. Bu hata mesaji içerisinde plug-i debug etmemize yarayacak bilgiler yer alacak. Bu bilgileri almak icin cikan hata penceresinde “Download Log File” düğmesine basmaniz gerekmekte.

 

·         Persist to Entity: Eger ikinci adimi seçerseniz bu sefer butun bilgiler CRM içerisinde bir Entity içerisine yazılacak.

 

Iki adimdan birini seçip plug-in’i tetikleyecek işlemi yaptıktan sonra “Plug-in Registration Tool” içerisinde “Debug” düğmesine tiklamaniz gerekmekte.

 

 

Karsiniza asagidaki gibi bir ekran gelecek. Bu ekran bir önceki seçtiğiniz adima gore iki işlemden birini yapmaniz gerekmekte;

 

Eger “Exception” adimini seçtiyseniz “…”’ya basarak kaydetmiş olduğunuz hata dosyasinin yerini gösterin. Eger “Persist To Entity” adimini seçtiyseniz asagi doğru duran ok düğmesine basiniz. Karsiniza soyle bir ekran cikacak;

 

 

Bu ekrandan kaydettiğiniz profile log’unu seçebilirsiniz.

 

Sonra sirasiyla .dll dosyanizi sisteme gösterin ve debug etmek istediğiniz Plug-in’i secin. Visual Studio’yu acin ve “PluginRegistration.exe” uygulamasina attach olun. Start Execution dugmesina basin ve breakpoint koyduğunuz yerde bekleyin. Bir sure sonra Visual Studio’a beklediğimiz yere gelecek ve bizim debug etmemizi sağlayacak.

 

 


Eger plug-in’de değişiklik yapmaniz gerekiyorsa değişiklikleri yapin ama CRM’e atmayin ilk once biraz önceki adimlari uygulayarak kodu tekrar test edin. Artik koddan eminseniz CRM içerisine gönderebilirsiniz güncellediğiniz .dll’i.

 

Bu arada belirtmeliyim ki asagida “plug-in traces” bolumunden de debug etmeden kodun nasil calistigini izleyebilirsiniz.



Burada icin TracingService ile yazacaginiz mesajlar görüntülenecektir.

Microsoft Dynamics CRM 2013 'de FetchXML ile Aggregate(Toplama Sorguları) İşlemleri

Bir önceki makalede FetchXML ile neler yapabileceğimize değindik. (Buraya tıklayarak o makaleye ulaşabilirsiniz) Eğer istersek FetchXML ile grouping ve aggregate işlemlerini de yapabilmekteyiz. FetchXML ile aşağıdaki işlemler desteklenmektedir;

·         sum

·         avg

·         min

·         max

·         count(*)

·         count(attribute name)

 

Aggregate yapabileceğimiz sorgu örneği standart olarak bildiğimiz fetchXML kurgusundan farklı değil burada sadece attribute kısmında aggregate ile ilgili keyword yer almakta. Aggregate=true diyerek bu şekilde bir sorgulama yapacağımızı sisteme söylüyoruz. Sonrasında ise sırasıyla hangi alan üzerinden işlem yapılacağını, alias yani etiketin ne olacağını ve aggregate türümüzün ne olacağını sisteme söylüyoruz.

<fetch distinct='false' mapping='logical' aggregate='true'>

  <entity name='opportunity'>

    <attribute name='name' alias='opportunity_count' aggregate='count'/>

  </entity>

</fetch>

Bu şekilde oluşturduğumuz bir sorgu ile aslında şunu demek istiyoruz : “select count('name') as opportunity_count from opportunity” yani standart bir count işleminden fazlası değil yaptığımız.

 

Bu fetchXML’i çalıştırmak için ise aşağıdaki gibi bir kod hazırladım;

 

string opportunity_count = @" <fetch distinct='false' mapping='logical' aggregate='true'>

                                                <entity name='opportunity'>

                                                    <attribute name='name' alias='opportunity_count' aggregate='count'/>

                                                </entity>

                                              </fetch>";

 

                EntityCollection opportunity_count_result = ServiseBaglan().RetrieveMultiple(new FetchExpression(opportunity_count));

 

                foreach (var c in opportunity_count_result.Entities)

                {

                    Int32 aggregate2 = (Int32)((AliasedValue)c["opportunity_count"]).Value;

                    System.Console.WriteLine("Count of all opportunities: " + aggregate2);

                }

 

Burada dikkat edilmesi gereken nokta geriye EntityCollection döndürmesi. Bir önceki makalemden hatırlarsanız normalde bu tarz sorgulama ile biz geriye account, contact gibi sitem içerisindeki nesnelerden oluşmuş bir dizi alıyoruz. FetchXML yapısı gereği tek bir metod kullanıyoruz ve bu metod sonucunda yukarıdaki örnekte olduğu gibi tek bir satır dahi dönecek olsa bile yine sonucu bir collection içerisinde almaktayız. Bu nedenle mecbur foreach içerisinde dönüyoruz ya da collection’un 0. üyesini alıyoruz. Ben örneğimde foreach ile collection içinde döndüm ve gördüğünüz gibi değeri aldım.

 

Yine bir önceki makalemde ileri düzey sorgular bölümünde anlattığım gibi eğer nesne üzerinden direkt bir değer döndürmeyeceksek sonuç her zaman AliasedValue olarak gelmekte. işte bu nedenden dolayı şu şekilde bir convert işlemi yapıyoruz;

 

Int32 aggregate2 = (Int32)((AliasedValue)c["opportunity_count"]).Value

 

Bu işlem sonucunda bu koddan aşağıdaki gibi çıktımızı alabiliyoruz.

 

 

Eğer distinct yapmak istersek de fetchXML içerisine yerleştireceğimiz bir distinct=”true” ifadesiyle ile sisteme bunu beliretebiliriz.

Aşağıda ise distinct yapılmış bir kod örneği bulunmakta;

 

<fetch distinct='false' mapping='logical' aggregate='true'>

  <entity name='opportunity'>

    <attribute name='name' alias='opportunity_distcount' aggregate='countcolumn' distinct='true'/>

  </entity>

</fetch>

 

Bu FetxhXML’i de aşağıdaki kodla çalıştırabiliriz.

 

                string opportunity_distcount = @"

                                           <fetch distinct='false' mapping='logical' aggregate='true'>

                                               <entity name='opportunity'>

                                                  <attribute name='name' alias='opportunity_distcount' aggregate='countcolumn' distinct='true'/>

                                               </entity>

                                           </fetch>";

 

                EntityCollection opportunity_distcount_result = ServiseBaglan().RetrieveMultiple(new FetchExpression(opportunity_distcount));

 

                foreach (var c in opportunity_distcount_result.Entities)

                {

                    Int32 aggregate4 = (Int32)((AliasedValue)c["opportunity_distcount"]).Value;

                    System.Console.WriteLine("Distinct name count of all opportunities: " + aggregate4);

                }

 

                Console.ReadLine();

 

Bu kod sonucunda da aşağıdaki gibi bir cevap alabiliriz sistemden;


 

Gelin olayı biraz renklendirelim. Bu sefer de bir sorgu içerisinde birden fazla aggregate seçeneğinin cevabını isteyelim. Böyle bir işlem için standart fetchXML’in içerisinde sırasıyla hangi özelliklerin bize geri döneceğini belirtiyoruz tabii unutulmaması gereken nokta ise hepsi için ayrı birer alias olması gerektiğidir.

 

<fetch distinct='false' mapping='logical' aggregate='true'>

  <entity name='opportunity'>

    <attribute name='opportunityid' alias='opportunity_count' aggregate='count'/>

    <attribute name='estimatedvalue' alias='estimatedvalue_sum' aggregate='sum'/>

    <attribute name='estimatedvalue' alias='estimatedvalue_avg' aggregate='avg'/>

  </entity>

</fetch>

 

Bu sorgu için ise aşağıdaki kodu hazırladım;

 

                string estimatedvalue_avg2 = @"

                                    <fetch distinct='false' mapping='logical' aggregate='true'>

                                        <entity name='opportunity'>

                                           <attribute name='opportunityid' alias='opportunity_count' aggregate='count'/>

                                           <attribute name='estimatedvalue' alias='estimatedvalue_sum' aggregate='sum'/>

                                           <attribute name='estimatedvalue' alias='estimatedvalue_avg' aggregate='avg'/>

                                        </entity>

                                    </fetch>";

 

                EntityCollection estimatedvalue_avg2_result = ServiseBaglan().RetrieveMultiple(new FetchExpression(estimatedvalue_avg2));

 

                foreach (var c in estimatedvalue_avg2_result.Entities)

                {

                    Int32 aggregate8a = (Int32)((AliasedValue)c["opportunity_count"]).Value;

                    System.Console.WriteLine("Count of all opportunities: " + aggregate8a);

                    decimal aggregate8b = ((Money)((AliasedValue)c["estimatedvalue_sum"]).Value).Value;

                    System.Console.WriteLine("Sum of estimated value of all opportunities: " + aggregate8b);

                    decimal aggregate8c = ((Money)((AliasedValue)c["estimatedvalue_avg"]).Value).Value;

                    System.Console.WriteLine("Average of estimated value of all opportunities: " + aggregate8c);

 

                }

 

                Console.ReadLine();

 

İşte bu şekilde aynı anda count, sum ve avg işlemlerini yapabilmekteyim. Sonuç ise aşağıdaki gibi;

 

 

Bu iki makalede FetchXML’ler üzerinde konuştuk. Umarım faydalı olmuştur.

Dynamics CRM Seminer Dizisi

Dynamics CRM 2013 versiyonu artık yayında bildiğiniz üzere, hatta 2013 üzerinde birçok proje live olmaya bile başladı bile. Peki siz Dynamics CRM nedir biliyor musunuz? Microsoft'un en çok para yatırdığı platformlardan biri olan Dynamics ailesini ne kadar tanıyorsunuz? Dynamics CRM nasıl bir yazılım platformu olarak kullanılır biliyor musunuz? işte bütün bu sorulara cevap verecek üstüne 2011 ve 2013 veriyonlarını öğreneceğiniz güzel bir web seminerleri dizisi başlatmaktayım. Aşağıda detayları bulabilirsiniz.

19 Aralık Perşembe Saat 10:00 : Dynamics CRM Nedir? Ne işe Yarar?

   Seminere giriş linkimiz : https://www.livemeeting.com/cc/mvp/join?id=MVP4025099&role=attend&pw=hq.%27SG%28c3

23 Aralık Pazartesi Saat 10:00 : Dynamics CRM 2011 ve 2013 Versiyonlarındaki Farklılıklar.

   Seminere giriş linkimiz : https://www.livemeeting.com/cc/mvp/join?id=MVP4025099&role=attend&pw=p%60dG4%40ChR 

27 Aralık Cuma Saat 10:00 : Dynamics CRM 2013 ile Yazılım Geliştirme.

Facebook event adresine bu linkten ulaşabilirsiniz : https://www.facebook.com/events/432791460180088/

 

 

Asp.Net Yazılımcı İş İlanı

Firmamızın ekibine yeni yazılımcılar katmak istiyoruz. Pozisyona kabul edilecek arkadaşlar direkt bana bağlı olarak çalışacaklar ve benden Dynamics CRM ve Dynamics Mimarisine özgü programlama tekniklerini öğreneceklerdir(Javascript, Workflow ve Plugin dizayn edip kodlama gibi). Başta proje içerisinde verilen görevi yerine getirme sorumluluğu daha sonra ise projeyi komple ele alıp bitirebilme yetenekleri kişiye kazandırılacaktır. Kısacası ekibimize katacağımız kişiler Dynamics CRM projelerinde ilk başta yazılımcı daha sonra ise danışman olarak yetiştirilecektir. Bu yüzden başvuracak adayın yeniliklere adapte olabilen, hızlı öğrenen, kendine her ortamda güvenen, yükselme hedefi olan nitelikte bir kişi olması gerekmektedir. Tabii ki okuduğunu anlayabilecek kadar ve karşılaştığı problemleri internette arayabilecek kadar İngilizce bilgisi de gerekmektedir.

İlerleyen aşamalarda danışman statüsüne yükselmek isteyen arkadaşların müşteri ile diyaloga geçip istek, öneri ve sorunlarını anlayabilmesi ve bunlara ekibiyle birlikte çözüm üretmesi gerekmektedir. 

Bu bağlamda ASP.Net ve C#’ı bilen kişiler arıyoruz. Bunun yanı sıra Windows Forms, Windows Servisleri, MS Sql Server, XHTML, DOM, XML, CSS gibi teknolojilere yatkınlık da aramaktayız. Asp.Net ile en az 1 yıl bir firmada yazılım geliştirmiş adaylar kabul edilecektir. Bir firmada tam zamanlı yazılım geliştirme deneyimi olmayan arkadaşlar lütfen başvurmasın.

Şirketimiz Kadıköy Hasanpaşa’da Metrobüs hattının son durağında yer almaktadır.  Başvuracak adayların maaş beklenti aralıklarını da belirtmesi gerekmektedir. Maaş beklenti aralığı verilmeyen CV’ler dikkate alınmayacaktır.


Başvuracak adayların Cv’lerini baris.kanlica@omerd.com veya idil.oter@omerd.com adreslerine göndermeleri rica olunur.

İş İlanı

Hızla büyüyen firmamızın ekibine 3 adet yeni arkadaş katmak istiyoruz. Pozisyona kabul edilecek arkadaşlar direkt bana bağlı olarak çalışacaklar ve benden Dynamics CRM ve Dynamics Mimarisine özgü programlama tekniklerini öğreneceklerdir(Workflow ve Plugin dizayn edip kodlama gibi). Başta proje içerisinde verilen görevi yerine getirme sorumluluğu daha sonra ise projeyi komple ele alıp bitirebilme yetenekleri kişiye kazandırılacaktır. Kısacası ekibimize katacağımız kişiler Dynamics CRM projelerinde ilk başta yazılımcı daha sonra ise danışman olarak yetiştirilecektir. Bu yüzden başvuracak adayın yeniliklere adapte olabilen, hızlı öğrenen, kendine her ortamda güvenen, yükselme hedefi olan nitelikte bir kişi olması gerekmektedir. Tabii ki okuduğunu anlayabilecek kadar ve karşılaştığı problemleri internette arayabilecek kadar İngilizce bilgisi de gerekmektedir.

İlerleyen aşamalarda danışman statüsüne yükselmek isteyen arkadaşların müşteri ile diyaloga geçip istek, öneri ve sorunlarını anlayabilmesi ve bunlara ekibiyle birlikte çözüm üretmesi gerekmektedir. 

Bu bağlamda ASP.Net ve C#’ı bilen kişiler arıyoruz. Bunun yanı sıra Windows Servisleri, MS Sql Server,XHTML, DOM, XML, CSS gibi teknolojilere yatkınlık da aramaktayız.

Senior olarak başvuracak adayların askerliğini tamamlamış olması gerekmektedir. Junior adayların ise en az 2 yıl tecilli olması yeterlidir. 

Şirketimiz Kadıköy Hasanpaşa’da Metrobüs hattının son durağında yer almaktadır.  Başvuracak adayların maaş beklenti aralıklarını da belirtmesi gerekmektedir. Maaş beklenti aralığı verilmeyen CV’ler dikkate alınmayacaktır.


Başvuracak adayların Cv’lerini baris.kanlica@omerd.com veya idil.oter@omerd.com adreslerine göndermeleri rica olunur.

Akbank C# Eğitimi

Akbank Bilgi İşlem ekibinden 2 gruba 4 hafta boyunca C# eğitimi verdim. Eğitim içeriği ise şöyleydi :

Programming with C#

Programming with the Microsoft .NET Framework

Developing Microsoft .NET Applications for Windows

Developing Microsoft ASP.NET Web Applications Using Visual Studio .NET

Eğitimden sadece 2. Grubun foroğrafı elime ulaştığından onu yayınlayabiliyorum sadece.

Güncel eğitim bilgisi bu adreste : http://www.cub-e.net/page/crm_egitim_referanslari.aspx

Eğitim referanslarımı eğitim bölümde bulabilirsiniz. Sorularınız ile ilgili Murat Manoğlu'yla irtibata geçebilirsiniz. 0216 450 0 331
murat.manoglu@omerd.com 

 

Windows Vista Kullanıcı Hesap Denetimi (UAC-User Account Control)

Windows Vista Kullanıcı Hesap Denetimi (UAC-User Account Control)

Birçok kişi Vista’ya gıcık olsa da ben Vista’yı gerçekten çok sevdim. Microsoft son zamanlarda hissedilir bir şekilde üzerinde durduğu kullanıcı güvenliği konusunun son halini Vista içerisinde bir program çalıştırırken ya da bir kopyalama işlemi yaparken sürekli karşımıza çıkan o meşhur güvenlik ekranından biliyoruz.  Windows her zaman kullanıcı dostu yapısıyla bilinirken birdenbire birçok son kullanıcı için problemli bir işletim sistemi oldu.

Peki neden Microsoft böyle bir şeye ihtiyaç duydu derseniz? Herkes Windows’un çok güvensiz olduğundan sürekli virüs bulaşmasından ya da Internet Explorer ile bilgisayarımızı ele geçiren (virüs,solucan,trojan...) gibi kötü niyetli yazılımlardan bahseder işte Microsoft da bu durumun farkında. Yani siz sistem üzerinde Administrator (tam yetkili kullanıcı) olarak çalıştığınızdan uygulamalarınızın da Administrator olarak çalışmakta ve herşeye erişmede tam yetkili olmaları durumundan kaynaklanmaktaydı. Vista ile işte bu değişti.

Bu durum Windows uygulaması geliştiren programcılar için de sıkıntılı durumlar yarattı. Artık istediğimiz dosya ya da klasöre yazma işlemini gerçekleştiremiyor, registry üzerinde işlem yapamıyor ya da Sistem üzerindeki WMI gibi arabirimlere bağlanamıyor olduk. Nedeni ise çok basit; çünkü geliştirdiğimiz uygulama, kullanıcı sistem Administrator’u olsa bile  Administrator haklarına sahip değil.

UAC Nedir?

Peki Vista bu işi nasıl yönetiyor diyorsanız; cevap, Vista üzerinde geliştirilen Kullanıcı Hakları Denetimi (UAC – User Account Control) isimli mimari. Kullanıcı Hesaplarını Denetimi (UAC); aynı kullanıcı altında çalışan yazılımların farklı haklar ile çalışabilmesini sağlıyor yani kullanıcıların bir program çalıştırmaya kalktıkları zaman bir uyarı diyaloğu göstererek programa doğrudan girişi engelliyor. Mesela bir program yönetici (administrator) hakları gerektiriyorsa o program çalışmadan önce sizden o programa administrator hakkı verip vermeyeceğinizi soruyor. Kullanıcısı hakkın verilmesini  onaylarsa program yönetici olarak çalışıyor. Windows’ un kendi uygulamaları için de bu durum  geçerli, mesela sistem dosyalarını değiştirmek isterseniz Windows Explorer sizden yönetici onayı istiyor.

Kısacası düşük kullanıcı hakları (LUA-Least Priviliged User Account) ile yazılımları çalıştırmak güvenliğin temel noktalarından biri. Microsoft ise bu şekilde bilgisayarın güvenliğinin en üst düzeye çıktığını ve yöneticiler dışındaki kişilerin bilgisayarda değişiklikler yapmalarının engellediğini savunuyor.

Integrity Levels

UAC’ nin en kritik özelliklerinden biri Integrity Levels. Vista’ da uygulamalar dört farklı seviyede çalışıyorlar (düşükten yükseğe)

  1. Low – Potected Mode
  2. Medium – LUA
  3. High - Elevated
  4. System

Her Integrity Level’in objeye göre hakları olabilir (obje çalışan bir uygulama ya da normal bir dosya olabilir).

Normal yazılımlar özel olarak belirtilmedikçe Medium seviyede çalışıyorlar;

  • High, özel olarak UAC penceresi ile yetkilendirilmiş yazılımlar.
  • System, sistem uygulamaları.

Dolayısıyla bu integerity seviyeleri sadece çalışan programlar ile ilgili değil aynı zamanda dosya sistemindeki erişim haklarıyla da ilgili. Eğer okunmaya çalışan obje dosya sistemindeki bir obje ise çalışan uygulama sadece kendi seviyesindeki ve altında objeleri okuyabilir.

(IE genelde sorun çıkarmaya müsait olduğu için en düşük haklar olan Low – Protected Mode ile çalışıyor.)

Sanallaştırma (Virtualization)

Vista’dan önce (hatta Vista’dan sonra bile) birçok uygulama “C:\windows” ya da en azından kendisinin kurulu olduğu örneğin “c:\Program Files\herhangi bir uygulama\ayarlar.ini” dosyasını okumak hatta buraya yazmak isteyebilir ve sistem işleyişi gereği kullanıcının buralara yazma yetkisi olmayabilir.

Bu durumda Vista sanal dosya ve sanal registry kullanarak orjinal dosya ve registry sistemini korumaya alıyor. Dolayısıyla eğer bir program yönetici yetkileri ilebir şeyler yazmaya çalışırsa Vista bunu otomatik olarak aktif kullanıcının profili altındaki klasöre ve registery' ye yönlendiriyor. Bu sayede bir dizi program hata almaktan kurtuluyor.

UAC File Virtualization Filter Driver (%SystemRoot%\System32\Drivers\Luafv.sys) dosya sistemi üzerindeki bu sanallaştırma işlemini yöneten mimari.

Kısacası bir uygulama “C:\Program Files\uygulama klasörü\ayarlar.ini” isimli bir dosyaya erişmek istediğinde “C:\Users\Username\AppData\Local\VirtualStore\Program Files\uygulama klasörü\ayarlar.ini” dosyasına erişiyor olacak. Eğer aynı uygulama registry üzerindeki “HKEY_LOCAL_MACHINE\Software\uygulama adı\”  düğümüne bir değer yazmak istiyorsa otomatik olarak “HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\Software\uygulama adı” ya da “HKEY_USERS\UserSID_Classes\VirtualStore\Machine\Software\uygulama adı” düğümlerinden birine veri yazıyor olacak. Uygulama böylece bir sandbox’un içinde çalışıyor olacak.

Şimdi bu konulara bir uygulama ile sistemin bizi nasıl sandbox’a alıp sanallaştırdığını görelim.

1.       Visual Studio 2008’i açıp VistaVirtualizationTester isimli bir console uygulaması açalım.

2.       Aşağıdaki kodları uygulamamıza ekleyelim; 

using System;
using System.Collections.Generic;
using System.Text;

using System.IO;

namespace VistaVirtualizationTester
{
   
class Program
   
{
       
static void Main(string[] args)
       
{
           
//dönüş noktamız
       
tryagain:
           
try
           
{
               
//yazılacak metin
               
string lines = "birkaç satır birşeyler \r\ndenemeye değer bir uygulama \r\nBarış KANLICA."

                //yazma işlemi
                string localPath = "c:\\windows";
              
//string localPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
               
System.IO.StreamWriter file = new System.IO.StreamWriter( localPath + "\\test.txt");
               file.WriteLine(lines);
                file.Close(); 

                //ekrana gerçekleşen işlemi yaz
               
Console.WriteLine("Yazma işlemi başarıyla sonuçlandı.");
                Console.ReadLine();
            }
            catch (Exception ex)
            {
                //ekrana hatayı yazdır
                Console.WriteLine("Yazma işlemi sırasında hata oluştuı.");
                Console.WriteLine(ex.Message);
                Console.ReadLine();
                //tekrar dene emri
                goto tryagain;
            }
        }
    }
}

3.       Solution üzerinde sağ tuşa basıp Properties ekranını açalım 

4.       Icon and Manifest kısmı altında “Create application witout manifest” ‘i seçiyoruz. 

Böylece manifest dosyası olmayan bir uygulama yaratmış olduk.  (Manifest nedir diyenler için açıklama da yapalım. Manifest içerisinde assembly metadata'larını bulunduran bölümdür. Asembly adı, versiyonu, başka Assembly'lere olan referanslar gibi bilgilerin tamamına metadata denir. Bu bilgilerin oluşturduğu kümeye Manifest denilmektedir.) Bu yaptığımız adımlar ile biz manifest bölümü olmayan bir assembly yaratmış olduk.

Uygulamamız ise “c:\Windows” içerisine birkaç satır dosya yazmayı amaçlamaktadır. Eğer hata oluşursa kullanıcıya bunu göstermekte ve klavye girdisi beklemektedir. Kullanıcı klavyede enter tuşuna basarsa tekrar aynı kodu çalıştırıp yazma işlemini tekrar deneyecektir.

Uygulamayı bu haliyle çalıştırdığınızda (Uygulamayı Visual Studio içerisinden değil build edilen yerden çalıştırılım.) “C:\Users\<kullanıcı adı>\AppData\Local\VirtualStore\Windows” içerisine test.txt isimli bir dosya oluşturduğunu göreceksiniz. Böylece sanallaştırma ile ilgili yukarıda anlattıklarımı örneklemiş oldum.

Peki bir uygulamanın sanal olarak çalıştığını nasıl anlarım diyebiilirsiniz hatta bir adım daha öteye gidip bir uygulamayı nasıl sanallaştırma içerisine sokabilirim diyebilirsiniz. Bu durumda görev yöneticisi (task manager) devreye giriyor. Task Manager açık iken İşlemler (Process) ekranında Görünüm (View)->Sütun Seç (Select Columns)->Sanallaştırma (Virtualization) sütununu açabilirsiniz. Bu sütunda bir uygulamanın hangi modda çalıştığını görebilirsiniz.

Bizim uygulamamızı tekrar çalıştırdığımızda uygulamanın virtualization modunun enabled olduğunu göreceksiniz. Şimdi bir adım daha ileri gidelim ve uygulammızın manifest durumunu tekrar eski haline alalım yani “Embed manifest with default settings” seçeneğini bu sefer seçelim. Ve uygulamamızı çalıştıralım. (Uygulamayı Visual Studio içerisinden değil build edilen yerden çalıştırılım.)  Çalıştırdığımızda uygulamanın yazamadığını ve hata verdiğini göreceksiniz.

Uygulamamızın Virtaualization kısmının Disabled olduğunu görüyoruz. Peki nasıl aktif hale getirebiliriz ? Çok basit task manager içerisinde uygulama üzerinde sağ tuşa bastığımızda Virtualization’ı tıklarsak bir uyrarı gelecek bu uyarıya evet dersek uygulamamız sanallaştırılmış moda dönecek.

Bu işlemden sonra uygulamamızın üzerine gelip enter’a basarsanız yazma işleminin gerçekleştiğini görebilirsiniz. Biraz daha derine inerek Sanallaştırmanın geçerli olduğu ve olmadığı durumlara da bir göz atalım,

Sanallaştırmanın geçerli olduğu durumlar:

  • 32 bit interaktif işlemler
  • Administrator haklarıyla yazılabilir dosya/klasör ve registry keys

Sanallaştırmanın geçerli olmadığı durumlar:

  • 64 bit işlemler
  • İnteraktif olmayan işlemler
  • İmpersonate kaynaklı işlemler
  • Kernel mod çağrıları
  • requestedExecutionLevel yetkisiyle çalıştırma

UAC ile Yetki İstemek

Bütün bu adımlardan sonra size bir de app.manifest dosyamızda yapacağımız küçük ama etkili bir değişiklik ile uygulamamızın kullanıcıdan nasıl yetki isteyeceğini göstereceğim.

Şunu unutmamak gerekir ki eğer bu yetkilendirme gerekli değilse gerçekten kullanmayın eğer bir klasöre ya da registry’e bir şeyler yazmanız gerekiyor ise Vista’nın size yazma okuma yetkisi verdiği yerleri kullanabilirsiniz. Örnek olarak yönetici yetkisi olmadan dosya yazmak veya okumak için en mantıklı yol Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) gibi komutlar kullanarak kullanıcının yazma yetkisinin olacağı bir klasörü kullanmak.

Ama yok uygulamanızın illa ki bu haklara ihtiyacı varsa mesela IIS üzerinde işlem yapan bir uygulama ya da sistem üzerinden WMI sorgusu çekmeniz gerekiyorsa o zaman app.manifest dosyamızı değiştirmemiz gerekli.

Burada Visual Basic kullanıcıları için bir güzellik yapmış Microsoft ve Visual Studio’nun içerisine bir kısayol gömmüş. 

VB Solution’ınızın üzerinde sağ tuşa basar ve Properties’e gelirseniz;

 

 

View UAC Settings isimli bir düğme bulacaksınız bu düğmeye tıkladığınızda ise;

 

 

App.manifest dosyanızın geldiğini göreceksiniz. 

C# kullananlar ise farklı bir yol izlemek zorunda. Yine solution üzerinde sağ tuşa tıklayarak bu sefer “ add->new item” demelisiniz açılan pencereden Application Manifest File dosyanızı seçip projenize ekleyebilirsiniz.

App.manifest dosyamızın içeriği şöyledir; 

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <
requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <!-- UAC Manifest Options
            If you want to change the Windows User Account Control level replace the
            requestedExecutionLevel node with one of the following.

        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

            If you want to utilize File and Registry Virtualization for backward
            compatibility then delete the requestedExecutionLevel node.
       
-->
        <
requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
    </
security>
  </
trustInfo>
</asmv1:assembly>

“requestedExecutionLevel” seviyesinin standart olarak “asInvoker” olarak ayarlı olduğu görebilirsiniz.

Değer

Açıklama

asInvoker

Uygulama en düşük yetki seviyesinde çalışır.

highestAvailable

Uygulama kendisini çağıran kullanıcıdan daha yüksek yetki ile çalışır ve mevcut kullanıcıdan yetki ister.

requireAdministrator

Uygulama administrator yetkisiyle çalışır ve mevcut kullanıcıdan yetki ister.

Bu durumda bizim asInvoker yazan yere requireAdministrator yazmamız gerekmekte. Bu değişikliği yapıp projeyi Visual Studio içerisinden çalıştırmak istediğimizde Visual Studio da yönetici haklarını bizden isteyecektir. “Restart under different credentials”’ı seçmemiz gerekmekte.

Ve Visual Studio kapanıp yeniden açılacaktır. Açıldığından onun da yönetici moduyla çıldığını görürüz.

Hatta uygulamamızın klasörüne gidip baktığımızda ise uygulamızın simgesinin altına Shield işaretinin geldiğini görebiliriz. 

Uygulamızı her çalıştırmak istediğimizde bizden yetki isteyecek. Eğer kullanıcı onaylarsa uygulamamız yönetici (administrator) haklarıyla çalışacak ve sistem üzerinde tam yetkili olacaktır. Tam bu noktada şu açıklamayı yapmak ta sanıyorum yerinde olacaktır. Eğer Windows’ un nasıl çalıştığı hakkında detaylı bilginiz varsa (en azından Windows’un mesaj tabanlı bir işletim sistemi olduğunu biliyorsanız) Windows’ un iç mesajlarını kullanarak başka yazılımlara istek göndermek ve bu sayede haklarınızı yükseltmek (privilige escelation) şeklinde saldırıya uğradığını da duymuşsunuzdur. (Shatter Saldırıları)

Bu nedenle UAC penceresi ayrı bir masaüstü olan “Session0” da çalışıyor. Bu bağlamda masaüstleri tamamen ayrı durumdalar ve birbirlerine windows mesajları ile mesaj gönderememektedirler. (Hatta arkadaki siyah plan bile aslında gerçek değil, isteğin yapıldığı anda arka planın kaydedilmiş bir resmi.)

UAC’nin devreye giridği işlemlerin tam listesi ise şöyle; 

·         Program Vista’ nın Uyumluluk listesindeyse

·         Program manifest dosyasında bunu belirtirse 

·         API ile bu istek yapılırsa

·         Kullanıcı özel olarak bir programın “Run As Administrator” ile çalıştırırsa (Bu noktada yine küçük bir bilgi vereyim; eğer çok sık kullandığınız bir program var ise üzerinde sağ tuşa basıp Uyumluluk (Compatibility) sekmesi üzerinde “Bu programı yönetici yetkisiyle çalıştır” (run this program as an administrator) checkini işaretlerseniz artık sizden yetki istemeyecek otomatik olarak yönetici haklarıyla çalıştıracaktır)

·         Vista bir programın “installer” programı olduğunu düşünürse.

UAC’yi Devre Dışı Bırakmak ya da Tekrar Aktif Hale Getirmek

UAC devre dışı da bırakılabilen bir yapı ve bir Vista üzerinde 2 şekilde devre dışı bırakabilirsiniz;

1.       Denetim Masasından (Control Panel)

a.       Denetim Masası içerisinde Kullanıcı Hesapları (User Accounts) altından

b.      Kullanıcı Hesapları Denetimi’ni aç ya da kapat (Turn User Account Control on or off) düğmesine tıklayınca karşınıza bir ayar ekranı açılır.

c.       Buradaki tiki kaldırarak kapatabilir ya da açabilirsiniz.

2.       Komut Satırı üzerinden (Command Prompt) 

a.       Aktive etmek

C:\Windows\System32\cmd.exe /k %windir%\System32\reg.exe ADD HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 1 /f

b.      Kapatmak

C:\Windows\System32\cmd.exe /k %windir%\System32\reg.exe ADD HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f

 

Windows 7’de Nasıl Olacak

Gelecek senenin sonlarında çıkarılması planlanan yeni işletim sistemi Windows 7’de de bu uygulamayı devam ettirilecek. Tabi arabirimde köklü değişiklikler yapılacak bu sefer devam uyarıların sıklığı kullanıcıların kendisi tarafından ayarlanabilecekmiş hatta açılması istenen programla ilgili açıklayıcı sorular sorulacakmış.

2007'nin ağustos ayından 2008'in ağustos ayına kadar "yönetici olarak çalıştırma" gerektiren programlar tam %75 oranında azalmış. Yani, yazılım firmaları Vista ile beraber “Microsoft Standartlarında” güvenli yazılımlar üretmeye başlamışlar.

Son Sözler

Konuyu toparlayacak olursak. Windows 7’de de bu uygulama süreceğine göre artık yazılımlarımızı buna göre geliştirmeye alışmamız gerekiyor. Microsoft bence bu konuda da çok haklı çünkü herkes sistem üzerinde istediği gibi davranırsa Windows sürekli problem çıkartan bir işletim sistemi olur ve bu zamana kadar da öyle oldu zaten. Eğer gerçekten yönetici haklarına ihtiyacınız yoksa sanallaştırmanın bize sunduğu ile yetinip yolumuza devam edelim ve sistemi stabil kılan uygulamalar yazalım. Bir makale de burada biter hepiniz hoşçakalın.

Diğer Kaynaklar

  • Programların hangi integrity seviyesinde çalıştığını görebilmek için AccessChk
  • Dosya sisteminde bu hakları görmek için icacls
  • Windows Engineering Blog için tıklayınız
  • Technet Magazinden konuyla ilgili bir makale için tıklayınız

Barış KANLICA
Yazılım Uzmanı – Software Specialist

brsk@e-kolay.net
www.cub-e.net
forum.cub-e.net

Core Entity mi Dynamic Entity mi? ( 2.Bölüm Veri Yazma)

Dynamic Entity'ler ile ilgili birinci makalemiz veri sorgulama idi. İkinci makalede ise veri yazma yöntemlerini göreceğiz. Burada dynamic entity'i anlatmadan önce core entity yöntemiyle veri yazmaya değineceğim. Böylece aradaki farkları görmemiz daha kolay olacaktır.

Konuyu hatırarsak; bir web servisini add web reference diyerek projenize dahil ettiğinizde visual studio arka tarafta bir bir class mimarisi oluşturur ve siz o mimariyi kullanırsınız. Eğer core enitity kullanırsanız, bu class özelleştirme nedeniyle her firmada farklı bir hal alabilir ve kodu yeniden derlemize neden olur. İşte bundan kurtularak çalışma zamanında nesneler yaratıp bunlara değer atamayı göreceğiz.

Hatırlarsanız bir örnek uygulamamız vardı. Senaryo şöyle idi; bir web sitemiz olacak ve bu web sitemize insanlar ad,soyad,e-mail,ilçe ve il bilgilerini yazarak kayıt olacaklar. Fakat biz forma girilen e-mail'i kullanarak veritabanımızda bu kişinin kayıtlı olup olmadığını kontrol edeceğiz eğer yoksa müşteri adayı (lead) olarak bu kişiyi Microsoft Dynamics CRM'e kaydedeceğiz.

Kaydet düğmesinin arkasında aşağıdaki kod yer almakta.
Mail adresinin yazılıp yazılmadığına bakıyoruz. Eğer yazıldı ise
dynamicRetrieve metodu ile bu mailinde birilerinin sistemde olup olmadığına bakıyoruz.



/// <summary>
///
Kaydet Dugmesi Click Olayi
/// </summary>
///
<param name="sender"></param>
///
<param name="e"></param>
protected void btnSave_Click(object sender, EventArgs e)
{
   
if (txtMail.Text != "")
    {
       
if (!dynamicRetrieve(txtMail.Text))
        {
           
if (coreCreate())
                lblMessage.Text =
"başarıyla oluşturuldu";
           
if (dynamicCreate())
                lblMessage.Text =
"başarıyla oluşturuldu";
        }
    }
}

Birinci makalede e-mail adresinden kontrol etmeyi gördük. Kontrol sonucunda e-mail adresinin sistemde bulunmadığını ve oluşturmamız gerektiğini düşünelim.


1.Core Entity

Burada önemli 3 adım bulunmakta.
1. web servisteki lead sınıfını çağırıyoruz
        lead myLead = new lead();
2. class içerisindeki proprty'e ilgili değeri atıyoruz
        myLead.firstname = txtName.Text.ToString();
3. içersisini veri ile doldurduğumuz class'ı servise oluşturması için veriyoruz.
        MyService.Create(myLead);

/// <summary>
///
coreCreate metdodu Core Entity kavramiyla lead olusturmayi bize gosterecek
/// </summary>
private bool coreCreate()
{
   
try
   
{
       
// CRM Servis'ini cagiriyoruz
       
CrmService MyService = service();
       
//lead sınıfımız aryoruz ve üretiyoruz.
       
lead myLead = new lead();
       
       
//textbox'ın değer içerip içermediğine bakıyoruz.
       
if (txtName.Text != string.Empty)
           
//eğer değer içeriyor ise class içerisindeki ilgili attribute a değerini veriyoruz.
           
myLead.firstname = txtName.Text.ToString();
       
if (txtSurname.Text != string.Empty)
            myLead.lastname = txtSurname.Text.ToString();
       
if (txtMail.Text != string.Empty)
            myLead.emailaddress1 = txtMail.Text.ToString();
       
if (txtState.Text != string.Empty)
            myLead.address1_stateorprovince = txtState.Text.ToString();
       
if (txtCity.Text != string.Empty)
            myLead.address1_city = txtCity.Text.ToString();
       

        //Son olarak da değer atamalarımız bitince servisin Create metodu ile
        //lead imizi oluşturuyoruz.
       
MyService.Create(myLead);
       
return true;
    }
   
catch (Exception ex)
    {
        HandleException(ex);

        return false;
    }
}

2. Dynamic Entity

Eğer bu oluşturma işlemini dynamic entity özelliğini kullanarak yapmış olsaydık kod bu sefer aşağıdaki gibi olacaktı.
Ama önce ne yaptığımızı anlatalım;

1. CRM Servis'ini cagiriyoruz. Burada service(); benim yazdığım bir metod ve crm servisini oluşturuyor.

       
CrmService MyService = service();
2. DynamicEntity nesnesini yaratyoruz

        DynamicEntity leadEntity = new DynamicEntity();
3. Entity ismini veriyoruz.

       
leadEntity.Name = EntityName.lead.ToString();
4. Eger deger iceriyorsa; Property nesnemizi cagiriyoruz ve adın ve degeri veriyoruz. Boylece calisma aninda bir class'in icerisindeki bir nesneye deger vermis oluyoruz.

           
StringProperty firstname = new StringProperty();
            firstname.Name =
"firstname";
            firstname.Value = txtName.Text;

Tabii burada yeri gelmişken söz etmekte fayda var CRM sadece string türünde bir değişken biçimi ile çalışmıyor. Yukarıdaki örnek "StringProperty" classından bir değişken türeterek string oluşturmaya yarıyor. Diğer değişken türleri (sınıflar) ise aşağıdaki listede yer almakta;


Sınıf Adı Microsoft Dynamics CRM Attribute Türü
CrmBooleanProperty CrmBoolean
CrmDateTimeProperty CrmDateTime
CrmDecimalProperty CrmDecimal
CrmFloatProperty CrmFloat
CrmMoneyProperty CrmMoney
CrmNumberProperty CrmNumber
CustomerProperty Customer
DynamicEntity N/A
DynamicEntityArrayProperty N/A
EntityNameReferenceProperty EntityNameReference
KeyProperty Key
LookupProperty Lookup
OwnerProperty Owner
PicklistProperty Picklist
Property N/A
StateProperty State
StatusProperty Status
StringProperty String
UniqueIdentifierProperty UniqueIdentifier
N/A Internal

Memo

Virtual



///
<summary>
///
dynamicCreate metdodu Dynamic Entity kavramiyla lead olusturmayi bize gosterecek
/// </summary>
private bool dynamicCreate()
{
    try
   
{
       
// CRM Servis'ini cagiriyoruz
       
CrmService MyService = service();
   
       
// DynamicEntity nesnesini yaratyoruz
       
DynamicEntity leadEntity = new DynamicEntity();
       
// Entity ismini veriyoruz.
       
leadEntity.Name = EntityName.lead.ToString();
       
// Property'ler icin bir Array olusturuyoruz.
       
ArrayList arrProps = new ArrayList();
   
       
// Textbox deger iceriyor mu diye kontrol ediyoruz.
       
if (txtName.Text != string.Empty)
        {
           
// Eger deger iceriyorsa; Property nesnemizi cagiriyoruz ve
            // adn ve degeri veriyoruz. Boylece calisma aninda bir class'in
            // icerisindeki bir nesneye deger vermis oluyoruz.
           
StringProperty firstname = new StringProperty();
            firstname.Name =
"firstname";
            firstname.Value = txtName.Text;
            arrProps.Add(firstname);
        }
       
if (txtSurname.Text != string.Empty)
        {
           
StringProperty lastname = new StringProperty();
            lastname.Name =
"lastname";
            lastname.Value = txtSurname.Text;
            arrProps.Add(lastname);
        }
       
if (txtMail.Text != string.Empty)
        {
           
StringProperty mail = new StringProperty();
            mail.Name =
"emailaddress1";
            mail.Value = txtMail.Text;
            arrProps.Add(mail);

        }
       
if (txtState.Text != string.Empty)
        {
           
StringProperty state = new StringProperty();
            state.Name =
"address1_stateorprovince";
            state.Value = txtState.Text;
            arrProps.Add(state);
        }
       
if (txtCity.Text != string.Empty)
        {
           
StringProperty city = new StringProperty();
            city.Name =
"address1_city";
            city.Value = txtCity.Text;
            arrProps.Add(city);
        }
       
// Property'leri bir DynamicEntity'e teslim ediyoruz.
       
leadEntity.Properties = (Property[])arrProps.ToArray(typeof(Property));
       
       
// Ve final entity'imizi olusturmasi icin servise veriyoruz.
       
MyService.Create(leadEntity);
        return true;
    }
   
catch (Exception ex)
    {
        HandleException(ex);
   
    return false;
    }
}


Uygulamamızı çalıştırdığımızda aşağıdaki ekran görüntüsünü elde edeceğiz.



Bir makale daha burada biter. Hepiniz hoşçakalın.

Barış KANLICA
Yazılım Uzmanı – Software Specialist
brsk@e-kolay.net
www.cub-e.net

 

Core Entity mi Dynamic Entity mi? ( 1.Bölüm Veri Sorgulama)

Microsoft Dynamics CRM üzerinde program geliştiriren herkes veri yazarken ve veri okurken web servisinden faydalanmamız gerektiğini bilir. (Veri okurken ek olarak fetchxml ve filteredview da kullanılabilir)
 
Peki bu işlemler sırasında web servisindeki nesnelere nasıl erişirsirsiniz?

Peki CRM üzerinde çalışacak bir uygulama geliştirdiniz ve bu uygulama web servislerini kullanarak CRM üzerine veri yazan bir uygulama olsun. Amacınız bu uygulamayı CRM kullanan firmalara satarak çok para kazanmak. Ama her müşterideki özelleştirme (customization) birbirinden farklı olacağından web servisleri de birbirinden farklı olacak. Çünkü standart yöntemde web servisindeki bir sınıf türetilerek, türetilen sınıftaki nesnelere erişilir. Her firmada nesneler de birbirinden farklı olabilir.  Sonucunda uygulamanızı her müşteri için derleyecek misiniz?

Bu çok saçma ve çok yorucu olurdu. Bu durumda bize kod zamanında değil çalışma zamanında nesneleri yönetmemizi sağlayacak bir yapıya ihtiyacımız var. Yani çalışma zamanında nesneler yaratıp bunlara değer atamalıyız.

İşte CRM içerisinde bu düşünülmüş, Core Entity yani standart nesne yönetimini yerine Dynamic Entity modeli ile nesneleri çalışma zamanında oluşturabilir ve yönetebiliriz. Dynamic Entity yöntemiyle veri sorgulayabilir ve veri yazabiliriz. Sırasıyla bu ikisini göreceğiz.

Konuyu örnek uygulamamızda irdeleyelim. Örnek uygulamamız için şöyle bir senaryo düşünelim. Bir web sitemiz olacak ve bu web sitemize insanlar ad,soyad,e-mail,ilçe ve il bilgilerini yazarak kayıt olacaklar. Fakat biz forma girilen e-mail'i kullanarak veritabanımızda bu kişinin kayıtlı olup olmadığını kontrol edeceğiz eğer yoksa müşteri adayı (lead) olarak bu kişiyi CRM'e kaydedeceğiz.




Kaydet düğmesinin arkasında aşağıdaki kod yer almakta.
Mail adresinin yazılıp yazılmadığına bakıyoruz. Eğer yazıldı ise
dynamicRetrieve metodu ile bu mailinde birilerinin sistemde olup olmadığına bakıyoruz.

/// <summary>
///
Kaydet Dugmesi Click Olayi
/// </summary>
///
<param name="sender"></param>
///
<param name="e"></param>
protected void btnSave_Click(object sender, EventArgs e)
{
   
if (txtMail.Text != "")
    {
       
if (!dynamicRetrieve(txtMail.Text))
        {
           
if (coreCreate())
                lblMessage.Text =
"başarıyla oluşturuldu";
           
if (dynamicCreate())
                lblMessage.Text =
"başarıyla oluşturuldu";
        }
    }

}

Dynamic Entity yönetemiyle veri sorgulamayı göreceğiz ilk önce. (Core entity ve diğer veri sorgulama yöntemleri ile ilgili olarak 3 makalelik bir yazı dizisi yayınlamıştım hatırlarsanız o yüzden bu makalede bu konulara girmeyeceğim.)

İlk önce kodu inceleyelim.


1. query nesnemizi oluşturuyoruz

        QueryByAttribute query = new QueryByAttribute();

2. hangi entity üzerinde sorgulama yapacağımızı söylüyoruz.

        query.EntityName =
EntityName.lead.ToString();

3. sorgulama sonucunda hangi alanları geri istiyoruz bunu söylüyoruz

       
ColumnSet cs = new ColumnSet();
        cs.Attributes =
new string[] { "firstname","lastname","address1_city" };
        query.ColumnSet = cs;

 4. koşulumuzu veriyoruz.
        query.Attributes =
new string[] { "emailaddress1" };
        query.Values =
new object[] { mail };

        Aslında buraya kadar ( " select firstname","lastname","address1_city from filteredlead where emailaddress1 = '"+ mail +"' ") dedik. Ama servis kullanarak bunu demek daha zahmetli.

5. servisimizi çağırıyoruz. Burada service(); benim oluşturduğum bir metod. CRM 3.0 ve CRM 4.0 arasında servise bağlanmakta farklılıklar var. Bunu daha önceki bir makalemde anlattığım için burada anlatmıyorum.

       
CrmService MyService = service();

6. işte can alıcı nokta burası geriye core entity değil dynamic entity istediğimizi söylüyoruz.
        retrieved.ReturnDynamicEntities =
true;

7. gelen sınıfı DynamicEntity türüne çeviriyoruz.
           
DynamicEntity entity = (DynamicEntity)responsed.BusinessEntityCollection.BusinessEntities[0];

8. işte ikinci can alıcı nokta burası. gelen DynamicEntity içinden property leri birer birer çıkartıyoruz.
Gelen property inin Value attribute 'u içerisinde değer bulunmakta bunu set ediyoruz.
           
StringProperty property = (StringProperty)entity.Properties[i];
            firstname = property.Value;

Kodun tamamı aşağıdadır.

/// <summary>
///
dynamicRetrieve metdodu Dynamic Entity kavramiyla veri cekmeyi bize gosterecek
/// </summary>
private bool dynamicRetrieve(string mail)
{
   
try
   
{
        //query nesnemizi oluşturuyoruz
        QueryByAttribute query = new QueryByAttribute();

        //hangi entity üzerinde sorgulama yapacağımızı söylüyoruz.
        query.EntityName =
EntityName.lead.ToString();

        //sorgulama sonucunda hangi alanları geri istiyoruz bunu söylüyoruz
       
ColumnSet cs = new ColumnSet();
        cs.Attributes =
new string[] { "firstname","lastname","address1_city" };
        query.ColumnSet = cs;

        //koşulumuzu veriyoruz.
        query.Attributes =
new string[] { "emailaddress1" };
        query.Values =
new object[] { mail };

        //aslında buraya kadar ( " select firstname","lastname","address1_city from filteredlead where emailaddress1 = '"+ mail +"' ") dedik.

        //
servisimizi çağırıyoruz.
       
CrmService MyService = service();
       
RetrieveMultipleRequest retrieved = new RetrieveMultipleRequest();

        //işte can alıcı nokta burası geriye core entity değil dynamic entity istediğimizi söylüyoruz.
        retrieved.ReturnDynamicEntities =
true;
        retrieved.Query = query;
       
RetrieveMultipleResponse responsed = (RetrieveMultipleResponse)MyService.Execute(retrieved);
       
if (responsed != null && responsed.BusinessEntityCollection.BusinessEntities.Length > 0)
        {

   
        //gelen sınıfı DynamicEntity türüne çeviriyoruz.
           
DynamicEntity entity = (DynamicEntity)responsed.BusinessEntityCollection.BusinessEntities[0];
           
string firstname = "";
           
string lastname = "";
           
string city = "";
           
for (int i = 0; i < entity.Properties.Length; i++)
            {
               
if (entity.Properties[i].Name.ToLower() == "firstname")
                {
           
        //işte ikinci can alıcı nokta burası. gelen DynamicEntity içinden property leri birer birer çıkartıyoruz.
                    //gelen property inin Value attribute 'u içerisinde değer bulunmakta bunu set ediyoruz.
                   
StringProperty property = (StringProperty)entity.Properties[i];
                    firstname = property.Value;
                }
               
if (entity.Properties[i].Name.ToLower() == "lastname")
                {
                   
StringProperty property = (StringProperty)entity.Properties[i];
                    lastname = property.Value;
                }
               
if (entity.Properties[i].Name.ToLower() == "address1_city")
                {
                   
StringProperty property = (StringProperty)entity.Properties[i];
                    city = property.Value;
                }
            }
           
string result = "<table border=1><tr>";
            result +=
"<td>Ad</td>";
            result +=
"<td>Soyad</td>";
            result +=
"<td>Şehir</td>";
            result +=
"</tr>";
            result +=
"<tr>";
            result +=
"<td>" + firstname + "</td>";
           
result += "<td>" + lastname + "</td>";
            result +=
"<td>" + city + "</td>";
            result +=
"</tr></table>";
            lblMessage.Text =
"eşleşen kayıtlar bulundu";
            lblMessage.Text += result;
           
return true;
        }
       
return false;
    }
   
catch (Exception ex)
    {
        HandleException(ex);
       
return false;
    }
}

Daha önceden sitemize kayıt olmuş test1 kişisinin sitemize tekrar kayıt olmaya çalıştığını düşünelim uygulama eşleşen bir kayıt bulacağından görüntü şöyle olacak.




Bu makaleye de burada noktayı koyalım. Unutmayın sırada veri yazma ile ilgili bir makale var.

Barış KANLICA
Yazılım Uzmanı – Software Specialist
brsk@e-kolay.net
www.cub-e.net