cub-e.net

just coding...

Veri Turleri Hakkinda

Microsoft Dynamics CRM 2011 ve Microsoft Dynamics CRM Online'da programlama modeli .NET'in temel türlerini kullanacak şekilde değiştirildi.

Bu tabloda beni en çok şaşırtan ise Customer, Lookup, Owner nesnelerinin artık EntityReference türünden sadece bir değer almaları. CRM'i yeni öğrenler için işler gerçekten kolaylaştırılmış. Artık kod yazarken CRM ile başlayan nesnelerimiz yok.

Aşağıdaki tablo bize Microsoft Dynamics CRM 4.0 ile CRM 2011, 2013 ve 2015 arasındaki tür dönüşümünü göstermektedir.

Özellik Adı

Microsoft Dynamics CRM 2011, 2013, 2015 Türü

Microsoft Dynamics CRM 4.0 Türü

AttributeTypeCode.Boolean

bool ya da System.Boolean

CrmBoolean

AttributeType.CalendarRules

EntityCollection

DynamicEntity[] or calendarrule[]

AttributeType.Customer

EntityReference

Customer

AttributeType.DateTime

System.DateTime

CrmDateTime

AttributeType.Decimal

decimal ya da System.Decimal

CrmDecimal

AttributeType.Double

double ya da System.Double

CrmFloat

AttributeType.Integer

int ya da System.Integer

CrmNumber

AttributeType.Internal

System.Object

Kayıtlarda Kullanılmaz

Kayıtlarda Kullanılmaz.

AttributeType.Lookup

EntityReference

Lookup

AttributeType.Memo

string ya da System.String

System.String

AttributeType.Money

Money

CrmMoney

AttributeType.Owner

EntityReference

Owner

AttributeType.PartyList

EntityCollection or ActivityParty[]

activityparty[] or DynamicEntity []

AttributeType.Picklist

OptionSetValue

Picklist

AttributeType.PrimaryKey

System.Guid

Key

AttributeType.String

System.String

System.String

AttributeType.State

OptionSetValue yada oluşturulan enumeration kullanılmalı

EntityNameStateInfo

AttributeType.Status

OptionSetValue ya da int

Status

AttributeType.Uniqueidentifier

System.Guid

UniqueIdentifier

AttributeType.Virtual

System.Object

Kayıtlarda Kullanılmaz

Kayıtlarda Kullanılmaz

Eski Tür

Yeni Tür

CrmAttributeType Class (MetadataService)

Microsoft.Xrm.Sdk.Metadata.AttributeTypeCode

Moniker Class (CrmService)

Microsoft.Xrm.Sdk.EntityReference

SecurityPrincipal Class (CrmService)

Microsoft.Xrm.Sdk.EntityReference

 

OptionSetValue

OptionSetValue’a değer atamak için ilk önce OptionSetValue türünden bir nesne oluşturmanız gerekmektedir.  Burada dikkat çekmek istediğim konu ise eğer state alanı ile çalışacaksanız (yani firma için aktif/pasif, teklif için açık/kazanıldı/kaybedildi gibi) early-bound sınıflarda bunlar için mutlaka bir enumaration oluşturulmakta. Ama late bound sınıflarda bu durumu programcı yönetmektedir.

Örnek olarak adres üzerindeki bir optionset alana değer atama aşağıdaki şekilde olmaktadır;

OptionSetValue osv = new OptionSetValue(1);

contact.Attributes["address1_freighttermscode"] = osv;

 

EntityReference

CRM sisteminde iki entity’yi birbirine bağlamak için lookup nesnesini kullanmak zorundayız. Lookup’lar üzerinde programatik işlem yapabilmek için EntityReference nesnesini kullanmaktayız. Bu nesneye Lookup alana reference vermek istemiz nesnenin türü ve Id’sini vermemiz gerekmektedir.

Aşağıdaki örnekte parentAccountId atama yapılacak nesnenin guid cinsinden Id’si olmalı;

EntityReference parentaccountid = new EntityReference("account", parentAccountId));

accountEntity.Attributes["parentaccountid"] = parentaccountid;

ioService.Update(accountEntity);

Null Değer Atama

CRM 4.0’dan farklı olarak .Net Type türleri kullanıldığı için null değer atama işlemi artık sadece alana değer vermekten ibaret oldu. İşte birkaç örnek;

EntityAdi.IndustryCode = null;

EntityAdi.AccountId = Guid.Empty;

EntityAdi.AccountNumber ="";

EntityAdi.Address1_Country = String.Empty;

Early ve Late Binding Arasındaki Farklar

Dynamics CRM 2011 ve sonrasinda CRM içerisinde programcılar kendilerine birden fazla programlama biçimi seçebilirler. Dynamics CRM’de WSDL kullanarak early-bound tipleri ve Dynamics Entity sınıflarını kullanarak da late-bound programlama yapabilirsiniz. Plug-in ve Workflow yazabilmek için late-bound tipleri kullanmamız gerekmektedir.

Dynamics CRM 4.0’da entity sınıflarının duruşu aşağıdaki şekildeki gibiydi;

Şimdi ise Dynamics CRM 2011’de bu yapı şu şekilde değişti;

DynamicEntity sınıfı artık Entity sınıfı isimli bir sınıfla yer değiştirdi. Bunun anlamı ise build time yani early bound tiplerle, runtime yani late bound tiplerin artık tek sınıftan türemesinin gerçekleşmiş olduğudur.

Dynamics CRM’de artık WSDL’e direkt ulaşamıyoruz. Daha önceki makalemde de anlattığım gibi 2 tane dll’i referans olarak eklemek ve servise bağlantı kurmak gerekmektedir.

Late-Bound olarak isimlendiren mimaride siz Entity sınıfından bir nesne türetmeli ve bu nesnenin attribute collection’da da değerlere yer vermelisiniz. Tabii burada değer alanlarının crm içerisindeki logical name’lerini kesinlikle bilmeniz gerekmektedir.

Aşağıdaki örnek bize late-bindig yapısının nasıl işlediğini gösterecektir;

Entity lead = new Entity("lead");

lead.Attributes["subject"] = "Deneme Firmasi";

lead.Attributes["firstname"] = "Baris";

lead.Attributes["lastname"] = "KANLICA";

lead.Attributes["companyname"] = "Mawens Business Solutions";

lead.Attributes["numberofemployees"] = 20;

Guid leadid = service.Create(lead);

Entity sınıfını kullanmaya başladığımız zaman late-binding’e giriş yapmış oluyoruz. Entity türünden oluşturduğumuz nesneye biz Lead türünden bilgileri içine dolduracağız diyoruz. Contact, Opportunity gibi CRM içerisindeki bütün nesneleri bu şekilde oluşturabiliriz.

Daha sonra ise alanların logical name’lerini vererek bunların değerleri veriyoruz. Burada .net tabanlı türleri kullanabilmekteyiz. CRM 4.0’da CrmBoolean, CrmNumber gibi türlere çeviriler yaparak nesnelerin içini doldururken artık buna ihtiyacımız bulunmamaktadır.

service isimli WCF tabanlı servisimizden türemiş nesnenin Create Metodunu kullanarak nesnemizi CRM içerisinde bir kayıt olarak oluşturuyoruz.

Early-Bound olarak isimlendirilen mimaride de ise CrmSvcUtil.exe aracını kullanarak bir OrganizationServiceContext türetmelisiniz. Daha sonra ise bu aracın türettiği nesneleri kullanabilir hale gelebilirsiniz. Tabii burada her bir nesnenin şema isimleriyle hareket ettiğimiz unutulmamalıdır.

Aşağıdaki örnek bize early-binding yapısının nasıl işlediğini gösterecektir;

CrmDataContext orgContext = new CrmDataContext(ServiseBaglan());

 

var contact = new Contact()

{

    FirstName = "Alan",

    LastName = "Smith"

};

orgContext.AddObject(contact);

 

orgContext.SaveChanges();

 

Burada ServiseBaglan() daha önceki makelemde belirttiğim gibi IOrganizationService Interface’inden türemiş bir sınıfı teşkil  etmektedir. Yani CRM’in WCF servisine hazır ve açık bir bağlantıdır.

Contact ise CRM içerisinde kişiler entity’sidir, Account, Lead, Invoice,Quote gibi daha bir çok entity bulunmaktadır.

Firstname ve Lastname ise kişinin adı ve soyadı için değerleri temsil etmektedir  ve bu bilgi OrganizationContext’ten gelmektedir. Bir sonraki yazında CrmDataContext isimli bu OrganizationContext’in CrmSvcUtil.exe aracılığıyla nasıl oluşturulduğu göstereceğim.

Daha sonra ise bu doldurduğumuz contact nesnesini OrganizationContext’e teslim ediyoruz ve işlem yapılması için SaveChanges() metodumuzu çağırıyoruz.

Farklılıkları ise şu şekilde sıralayabiliriz;

·         Early-Bound Entity Sınıflarının en büyük avantajı compile time da bize bütün hataları göstermesidir. Yani uygulamamızı yazarken ya da derlerken türler arası uyumsuzluk ya da yanlış değer atama gibi bütün yanlışlıklarımızı gözler önüne sermektedir. 

·         CrmSvcUtil bize tüm CRM mimarisini örneklerken bütün nesneleri ve onun ilişkilerini de getirmektedir. Böylece nesne dönüşümleri ve tür güvenliği de sağlanmış olmaktadır.

·         Visual Studio içerisinde inteli sense özelliğini kullanmamızı sağlar.

·         Dynamics CRM 4.0’dan beri WSDL ile çalışan kişiler bu yeni yapıda hiçbir farklılık hissetmeyeceklerdir.

CrmSvcUtil.exe ile Early-Bound Sınıflar Oluşturmak

Early-Bound tiplerle çalışabilmek için obje modelini bilmeye ihtiyacımız vardır. İşte CrmSvcUtil.exe bize bu kodu üretecek olan programdır.

Program early-bound .Net Framework sınıflarını ve entity modellerini Microsoft Dynamics CRM 2015 içerisinden almakta ve bize bir .cs dosyası halinde vermektedir. Bu noktadan sonra üretilen bu .cs dosyasını ya Visual Studio ile kodunuzun bir parçası olarak kullanabilir ya da bir dll haline getirip projenize referans olarak ekleyebilirsiniz. Bu sayede Visual Studio içerisinde intelli-sense özelliği ile kod geliştirebilirsiniz.

Eğer isterseniz uygulama her bir entity için ayrı bir partial class’da oluşturabilir.

CRM’in SDK’sında bin klasörü içerisinde bulabileceğiniz bu aracı command prompt ile çalıştırabilirsiniz.
crmsvcutil.exe            

/url: buraya Organization Service’in adresi gelecek

/out: çıktının hangi dosyaya olacağı bilgisi

/username : servise bağlanılacak kullanıcı adı

/şifre : servise bağlanılacak şifre

Eğer CRM’de zaten kullanıcı olan bir kişi ile oturum açtıysanız k.adı ve şifre belirtmenize gerek yok.

Bu şekilde gerekli cümleyi command promt’a yazdığınızda yukarıdaki ekranda olduğu gibi .cs dosyanızı alabilirsiniz.

Ek olarak aşağıdaki parametreleri de verebilirsiniz;

/serviceContextName: Eğer .cs dosyanızı LINQ Service Context vasıtasıyla LINQ sorgularını da desteklemesini istiyorsanız bu özelliği kullanmalısınız. Buraya türetilecek servis context’inin adını girmelisiniz örneğin “CrmDataContext” gibi.

Burada ek olarak şunu da belirtmeliyim ki bu komutu varsayalında ben hep kullanıyorum. Bu komutu kullandığımız zaman  2 şeyi unutmamız gerekmekte;

1.      Bir OrganizationContext oluşmakta artık onu kullanmamız gerekmekte, aşağıdaki örnekte olduğu gibi;

CrmDataContext orgContext = new CrmDataContext(ServiseBaglan());

2.      Crm Servis çağrısına şu özelliği eklememiz gerekmekte;

_serviceproxy.EnableProxyTypes();

 

Bu iki maddenin detayını LINQ ile veri  sorgulama makalemde daha detaylı anlatacağım.

/namespace : Varsayılanda .cs dosyası bir namespace olmadan türetilir bu özelliği kullanarak kodu bir namespace altında toplayabilirsiniz.

 /language : CrmSvcUtil.exe varsayılanda C# kodu üretil eğer VB kodu üretmek istiyorsanız bu özelliğe VB değerini vermeniz gerekmekte.

Bu tool aşağıdaki örnekte olduğu gibi bir kod üretmektedir;

 

    /// <summary>

    /// Bir müşteriyi veya potansiyel müşteriyi temsil eden işletme. Ticari işlemlerde faturalanan şirket.

    /// </summary>

    [System.Runtime.Serialization.DataContractAttribute()]

    [Microsoft.Xrm.Sdk.Client.EntityLogicalNameAttribute("account")]

    [System.CodeDom.Compiler.GeneratedCodeAttribute("CrmSvcUtil", "5.0.9688.1244")]

    public partial class Account : Microsoft.Xrm.Sdk.Entity, System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged

    {

 

        /// <summary>

        /// Default Constructor.

        /// </summary>

        public Account() :

            base(EntityLogicalName)

        {

        }

 

        public const string EntityLogicalName = "account";

 

        public const int EntityTypeCode = 1;

 

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

 

        public event System.ComponentModel.PropertyChangingEventHandler PropertyChanging;

 

        private void OnPropertyChanged(string propertyName)

        {

            if ((this.PropertyChanged != null))

            {

                this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));

            }

        }

Dynamics CRM Servis Mimarisi

Dynamics CRM üzerinde uygulama geliştirebileceğiniz çok güçlü bir mimari ile gelmektedir. Bu mimarinin temel yapı taşı ise WCF servisleridir. Bu yazımda sizlere CRM'in temel web servisleri olan Discovery ve Organization Servislerinin yapısını ve ne işe yaradıklarını anlatacağım.

CRM için kod geliştirirken her ne kadar sdk'nın içinden çıkan dll'leri kullansak da bu dll'ler vasıtasıyla ilk önce servis bağlantısı oluşturmamız gerekmektedir.  Yani verilere ulaşmak ve veri yazmak için WCF servislerini kullanmak zorundayız. Bu servislerle daha hızlı ve güvenli bir şekilde CRM platformuna entegre olmamızı sağlamaktadır.

WCF standartlaşmış bir teknoloji olduğu için biz yazılım geliştiricilere yeni özellikler sunmakta ve sürekli kendi içerisinde gelişmektedir. Dynamics CRM yapısında entity ve attribute katmanlı bir mimari bulunmaktadır. Yani biz CRM'in Business Logic katmanına müdahele edip yazılımlarımızı onunla entegre hale getirmekteyiz. Temel olarak nesne katmanı Entity isimli nesneden türemiştir. late-bound türlerde bu nesneyi sıklıkla kullanmaktayız. Early-bound olarak program geliştirme metodolojisini tercih edersek Entity class'ı ile işimiz olmamaktadır ama arka planda bütün nesnelerin bu class'dan türediği unutulmamalıdır. Bu konuya aşağıda bir örnekle tekrar değineceğim. CRM servislerine OrganizationServiceProxy ve DiscoveryServiceProxy sınıflarıyla bağlanmaktayız. Aşağıdaki kod bize bunu göstermektedir;

using (OrganizationServiceProxy _serviceProxy =
    new OrganizationServiceProxy(organizationUri, homeRealmUri, userCredentials, deviceCredentials)) ;

Discovery Servis

Dynamics CRM 4.0 versiyonundan itibaren multi-tenant bir mimaridedir. Yani tek bir uygulama birden fazla organizasyonu içerisinde barındırmaktadır. Yazılımcı olarak birden fazla organizasyon arasında geçiş yapmamız gerekiyorsa sistemde hangi organizyonlar olduğunu sorgulama işini Discovery servis ile yapmamız gerekmektedir. Bu servis yazma okuma işlemlerinin yapılacağı ana servise bağlanmamıza yardımcı olacak ve organizasyonların bilgisini bize döndürecektir. Aşağıdaki kod bize bu servise nasıl bağlanacağımızı ve organizasyonların bilgisine nasıl ulaşacağımızı göstermektedir.

Device ID bilgisini vermek istemezsek

Uri dInfo = new Uri("http://192.168.5.102/XRMServices/2011/Discovery.svc");
ClientCredentials clientcred = new ClientCredentials();
DiscoveryServiceProxy dsp = new DiscoveryServiceProxy(dInfo, null, clientcred, null);
dsp.Authenticate();
RetrieveOrganizationsRequest
rosreq = new RetrieveOrganizationsRequest();
RetrieveOrganizationsResponse
r = (RetrieveOrganizationsResponse)dsp.Execute(rosreq);
foreach
(OrganizationDetail o in r.Details)
{
      Console.WriteLine("Organizasyon Adı : " + o.FriendlyName);
}
Console
.ReadLine();

Device ID bilgisini vermek istersek

Normalde dokümantasyonlarda bu sekilde bir ayrim göremezsiniz. Ben bunu deneyimlerime dayanarak yapıyorum. Aslinda yukarıdaki kod da Online Organizasyon’a baglanir ama DiscoveryService’in varsayilan yapici metoduna 4. Parametreyi gönderirseniz yani DeviceCredential null olmazsa calisir.Sorun ise DeviceCredential’i oluşturmak icin CRM SDK\SampleCode\CS\HelperCode klasöründeki DeviceIdManager.cs kodunu kendi kodunuza implemente etmeniz gerekmekte.

Ek Bilgi

Bu kodla discovery servise bağlandıktan sonra ClientCredentials'ı kullanarak hali hazırda oturum a��mış kullancının bilgisini sisteme göndermekteyiz. Ama her zaman bunu kullanmak istemeyebiliriz yani başka bir kullanıcı adı ve şifre ile sisteme girmek istediğimizde ClientCredentials'a kullanıcı adı, şifre bilgilerini verebiliriz.

clientcred.Windows.ClientCredential = new System.Net.NetworkCredential("kullanici adi", "sifre", "domain");

Yukarıdaki kodun çalışabilmesi için System.ServiceModel.Description,System.Runtime.Seriliazation, Microsoft.Crm.Sdk.Proxy ve Microsoft.Xrm.Sdk dll'lerinin referanslara eklenmiş olduğundan emin olun. Ayrıca uygulamayı .Net Framework 4.5.2'de derlemek gerekiyor.

Organization Servis

Dynamics CRM 2015'in ana web servisi Organization Servis'tir. Bu servis içerisinde entity instance'ları üzerinde işlem yapabileceğimiz 6 metod ve execute metodu bulunmaktadır. CRM Servis sınıfını oluşturabilmek için Organization Service Proxy'nin bir instance'ını oluşturmamız gerekmekte. Daha sonrasında ise Organization Servis sınıfını bunu göre ayarlayacağız.

Uri organizationUri = new   Uri("https:// !organizasyon crm url! /XRMServices/2011/Organization.svc");

ClientCredentials clientcred = new ClientCredentials();

clientcred.UserName.UserName = " kulllanici adi ";

cientcred.UserName.Password = " sifre ";

OrganizationServiceProxy _serviceproxy = new OrganizationServiceProxy(organizationUri, null, clientcred, null);

IOrganizationService _service = (IOrganizationService)_serviceproxy;Yukarıdaki kodun çalışabilmesi için System.ServiceModel.Description, Microsoft.Xrm.Sdk ve Microsoft.Xrm.Sdk.Proxy dll'lerinin referanslara eklenmiş olduğundan emin olun. Ayrıca uygulamayı .Net Framework 4.5.2'de derlemek gerekiyor. Oluşturduğumuz bu servisi daha sonra programımızın ilerleyen bölümlerinde çağırıp işlemler yapacağız.

Tabi burada belirtilmesi gereken bir konu da işlem yapmak istediğiniz nesnenin üzerinde yetkilerinizin olmasıdır. Bir kayıt oluşturabilmek için oluşturma yetkisine sahip olmanız gerekmektedir. Sadece okuma yetkisiyle bir kayıt oluşturamazsınız. Bir sonraki yazımda sizlere entity mimarisi ve yazma okuma işlemlerini anlatacağım.

Yukaridaki kod orneginde biz bir kullanici adi ve sifre ekledik. Eger her kullanicinin kendi kullanici haklariyla sistem üzerinde işlem yapmasini istiyorsaniz yukarıdaki kodda kullanici adi ve sifre kodunu silip asagidaki kodu eklemeniz gerekir.

ClientCredentials clientcred = new ClientCredentials();

Boylece sistemde oturum acmis kullanici bilgileri ile devam etmis olacagiz.

Bilmemiz gereken diğer bir konu da eger Early Bind veri tipi kullanacaksak servisi oluştururken ek bir komut daha girmemiz gerekmektedir. Yani linq ile sorgulama ve generated code üzerinde işlemler yapabilmek icin oluşturduğunuz servis nesnesine bu sekilde işlem yapacaginizi belirtmeniz lazim iste bunun icin asagidaki satiri eklememiz gerekmekte.

_serviceproxy.EnableProxyTypes();

Bu arada CRM servisi olusturmanin yeni bir yöntemi daha bulunmakta. Bu da CrmConnection nesnesini kullanmak. Bu nesneye erişebilmek icin Microsoft.Xrm.Client dll’ini referans olarak eklemeniz gerekmekte.

CrmConnection crmConnection = CrmConnection.Parse("Url=https://! Crm organizasyon url !/XRMServices/2011/Organization.svc; Username= kullanici adi; Password= sifre");

OrganizationService service = new OrganizationService(crmConnection);

Boylece servis oluşturma işlemini 2 satirda da halledebilmekteyiz. Tabii bu bilgileri ben bu sekilde kod içerisine koymus gibi oldum size gostemek icin ama projelerde tabii ki bunlari ya app.config, web.config içerisine ya da belli bir lokasyonda tuttuğumuz xml dosyasi içerisinde tutuyoruz ki bu bilgiler degistiginde sürekli kod degisikligi yapmak zorunda kalmayalım.

Microsoft Dynamics Workshop - CRM Development Tickets, Manchester | Eventbrite

I'm one of presenter of this event. Please join us :)
More details here : bit.ly/1KGCxtp

ORGANISED BY
CRM Consultants UK
Event Description
The Objectives of the CRM User / Developer Group is to tackle issues related to overcoming common business obstacles when implementing CRM Business solutions.

This Month Microsoft CRM MVP Boris will be giving a presentation on how dynamics CRM can be extended and developed to provide XRM Solutions for various Industry requirements, and go beyond customer relationship management.

Razwan ( Microsoft Dynamics Solutions Architect) will then explore new features of CRM 2015 and SDK enhancements and open the floor and workshop for further dialogue related to technologies for business automation and analytics
WHEN
Saturday, 13 June 2015 from 18:00 to 20:00 (BST) 
WHERE
SpacePortX - 24-26 Lever Street Manchester, Gt Man M1 1DZ GB

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.

IFD Tabanlı Güvenlik Mekanizması Oluşturulması Hakkinda

CRM, ADFS Server kullanarak Security Token Service (STS) mimarisi altında daha fazla güvenlik içeren bir doğrulama mekanizmasına kavuşmaktadır.

Daha pratik bir şekilde anlatmak gerekirse normal şartlar altında kullanıcı internetten bir talepte bulunduğunda güvenlik mekanizmasından geçen talep direkt CRM sunucusuna ulaşmakta ve CRM sunucusu içeride güvenlik kontrolünü yapmaktadır. CRM sunucu DC ve SQL Server ile iletişime geçerek güvenlik kontrolünü yapmakta ve sonucunda kullanıcıya ya hata ya da içeriği döndürmektedir.


Eğer aynı senaryo IFD yapılandırılmış bir CRM için geçerli olsaydı, güvenlik sisteminden (ISA, Firewall) sonra CRM’e ulaşan kullanıcı güvenlik kontrolü için ADFS’e sunucusuna gönderilecek ve burada doğrulama işlemi gerçekleştikten sonra tekrar CRM sunucuna dönülecek ve içeriği iletmesi istenecektir. Eğer kullanıcı bilgileri yanlışsa IFD kullanıcıya hata döndürecektir.

Daha ayrıntılı bakacak olursak;


Görüldüğü gibi 3 adımlı doğrulama mekanizması IFD sayesinde 10 adımlı bir yapıya dönüşmektedir. Bu yüzden IFD CRM sisteminin güvenliğini arttırmaktadır.

IFD’nin bir diğer avantajı ise CRM sistemiyle aynı domainde olmayan kullanıcının sanki domain içinde bir kullanıcıymış gibi sistem üzerinde hareket etmesini sağlamaktadır.

Bu giriş bilgisinden sonra IFD yapılandırmasının adımlarından ve zorunluluklarından bahsedelim. Öncelikle ADFS ile CRM aynı sunucuya kurulabilse dahi bu pek önerilen bir yöntem değildir. Bu yüzden her zaman ADFS sunucusunu ayrı bir sunucu olarak düşünmek en mantıklısıdır.

Adımlar ise şu şekildedir;

1.       CRM standart bir şekilde kurulur.

2.       ADFS 2.0 default web site’da olacak şekilde ADFS sunucusuna kurulur.

3.       *.domainadı.com şeklinde wildcard sertifika alınır ve CRM ve ADFS sunucularına yüklenir.

4.       Sistem kontrol için iki sunucu kullanacağından bu iki sunucuya dışarıdan erişmek gerekmektedir. İstemci tarafından sunuculara erişilirken aşağıda belirtilen subdomain yönlendirmelerin Firewall ve public dns’de yapılmış olması gerekmektedir (Sistem ssl sertifikası kullandığından 443 nolu port düşünülerek işlem yapılmalıdır);

a.       Organizasyonadı.domainadı.com -> CRM sunucusuna

b.      Auth.domainadı.com -> CRM sunucusuna

c.       Dev.domainadı.com -> CRM sunucusuna

d.      Adfs.domainadı.com -> ADFS sunucusuna

e.      İnternalcrm.domain.com -> CRM sunucusuna (bu subdomain sadece sistemin içindeki DNS’de açılacaktır. Diğerleri gibi dış dünyaya açılmayacaktır.)

Yukarıda da görüldüğü gibi dışarıdan erişilmesi gereken 2 sunucumuz olduğuna göre 2 adet ip adresine ihtiyacımız olacaktır subdomainlerin yönlendirilmesi için.

5.      Bu işlemler yapıldıktan sonra CRM sunucusu üzerinde Deployment Manager ile gerekli yapılandırma ayarları yapılmalı

6.      ADFS Sunucu üzerinde de Primary SID, UPN ve AccountName ayarlarının yapılması gerekemektedir.

Eğer bir sistem sağlayıcıyla iş bölümü yapılacaksa sunucuların kurulması, 2. , 3. ve 4. Adımlar bu firma tarafından yapılmalıdır.

Plug-in Registration Tool’u Kullanmak

Ilk plug-in’imizi yazdıktan sonra geldi onu CRM içerisine eklemeye. Bu işlem için Plugin Registration Tool dediğimiz CRM SDK içerisinden cikan bir uygulamayi kullanacagiz. Bu uygulama sayesinde hem plug-in hem de custom workflow’lari CRM içerisine ekleyebilmekteyiz.

 

SDK\Tools\PluginRegistration\PluginRegistration.exe yolu ile ulaşabileceğiniz uygulamayi calistirdiginizda sizden bağlanmak istediğiniz server ile ilgili bilgileri isteyecektir.

 

Dynamics CRM Online için Online’i seçebilirsiniz ama unutmayin ki Office 365 hesabi kullaniyorsaniz Office 365’i seçmeniz gerekmekte. Ikisi de Online ama yetki mekanizmaları farkli.

 

Eger On-Premises yani Microsoft disinda host edilen bir CRM’e erişmek istiyorsaniz o zaman On-Premises seçeneğini seçmeniz gerekmekte. IFD’ler için de bu seçeneği kullanabilirsiniz.


 

Eger “Always display list of available orgs” seçeneğiniz seçerseniz bağlanmak istediğiniz kullanici ile erişebileceğiniz organizasyonlarin listesini görüntüleyebilirsiniz.

Basarili bir sekilde giriş yaptiginizda asagidaki gibi bir ekran karsiniza gelecektir.


 

1.       Plug-in’i sisteme kayit edebilmek için yukarıdaki “Register” düğmesine tikliyoruz ve ardindan “Register New Assembly” ‘ ye tikliyoruz.

2.       Step#1 bolumundeki … düğmesine tikliyarak kayit ettirmek istediğimiz .dll’i seçiyoruz.


          


3.       Step#2 bolumunde kaydetmek istediğimiz plug-in class’ini seçiyoruz.

4.       Step#3 bolumunde 2 tane seçeneğimiz bulunmakta;

a.       Sandbox : Bu seçeneği seçer isek plug-in bir Sandbox içerisinde calisacak yani dis ortamdan izole edilecek. Boylece bu plugin sistem içerisinde calisacak ama sisteme zarar veremeyecek ve izlenebilir olacak. Kisacasi yazdiginiz bir plug-in production ortamina tasimadan once test etmek için bu senecegi kullaniyoruz.

b.      None : hiçbir kisitlama olmadan .dll içerisindeki kodlar icra edilir.

5.       Step#4 bolumunde ise plug-in nerede duracagini seçmemizi istemekte.

a.       Database: tavsiye edilen yöntem budur. Boylece dll işletim sistemi kaynakli sorunlardan izole edilir. Veritabani yedeklendikçe dll de içinde olduğundan yedeklenecektir ve herhangi bir durumda geriye dönmenizi sağlar.

b.      Disk: Sistemin varsayilan dll yerleştirme yeri olan CRM Kurulum Yolu\Server\bin\assembly klasörü içerisinden dll’i okur.

c.       GAC: Global Assembly Cache üzerinden dll’leri okur.


Bu noktada bir not ileteyim eger server üzerinde calisan kodu debug etmek isterseniz yine server\bin\assembly klasörüne .pdb uzantili debug symbol’lerinizi yerleştirmeniz gerekmekte.

 

Ikinci bir not da eger serverda custom code execution kapaliysa açmak için server üzerinde powershell ile su kodlari calistirmaniz gerekmekte:

 

Add-PSSnapin Microsoft.Crm.PowerShell

$setting = get-crmsetting customcodesettings

$setting.AllowExternalCode="True"

 

Degerleri kontrol etmek için bu komutlari calistirabilirsiniz :

set-crmsetting $setting

get-crmsetting customcodesettings

 

Ayarlari tersine çevirmek için “AllowExternalCode”’a “False” değerini vermeniz yeterli.


Butun bu adimlari tamamladıktan sonra “Register Selected Plugin” düğmesine tikliyoruz. Plug-in kaydetmediki ilk adimi gerçekleştirmiş olduk sira diğer adimlarda :)

 

Bu noktada plug-in’i hangi event(ler) için yazdiysak onun için adim(lar) eklememiz gerekiyor. Plug-in anlatirken hep bir olay olduğunda yani veritabanina bir kayit eklendiğinde, silindiğinde ya da bir alani güncellendiğinde tetiklenebilir gibi orneklerle anlatıyoruz ama aslinda olay bundan daha derin gelin simdi custom entity’ler için yani bizim oluşturduğunuz varliklar için sistem üzerinde nasil olaylarin tetiklenmelerini yakalayabiliyoruz. Literaturde bu konu message olarak geçmekte yani CRM eventlarina mesaj adi verilmekte.

 

Message Name

Ownership Type

Message Availability

Entity Supported Deployment

Assign

User-owned entities only

Server

Server

Create

User-owned and organization-owned entities

Both

Server

Delete

User-owned and organization-owned entities

Both

Server

GrantAccess

User-owned entities only

Server

Server

ModifyAccess

User-owned entities only

Server

Server

Retrieve

User-owned and organization-owned entities

Both

Server

RetrieveMultiple

User-owned and organization-owned entities

Both

Server

RetrievePrincipalAccess

User-owned entities only

Both

Server

RetrieveSharedPrincipalsAndAccess

User-owned entities only

Both

Server

RevokeAccess

User-owned entities only

Server

Server

SetState

User-owned and organization-owned entities

Both

Server

SetStateDynamicEntity

User-owned and organization-owned entities

Both

Server

Update

User-owned and organization-owned entities

Both

Server

 

Listede de yer aldigi gibi Retrieve, RetrieveMultiple yani veritababindna sorgulama ya da SetState yani bir kaydin durumun değişmesi gibi birçok farkli mesaj için plug-in’i tetikletebilmekteyiz.

 

Lutfen sunu unutmayin yukarıdaki liste sadece custom entity’ler için campaign, campaignactivity, list gibi entity’ler için farkli mesajlar da mevcut tum listeye SDK içindeki “Message-entity support for plug-ins.xlsx” isimli dosyadan ulaşabilirsiniz.

 

Simdi yeni bir adim ekleyerek bir mesaj için plug-in’imizin tetiklenmesini saglayalim. Bunun için plug-in üzerinde sag tuşa tıklayarak ya da yukarıdaki “Register” düğmesine tıklayarak acilan menüden “Register New Step”’e tikliyoruz. Karsimiza asagidaki gibi bir pencere cikacak:


 

Message:  Yukarida bahsettigim mesajlardan birini buraya yazabilirsiniz. Hangi mesaji yazarsaniz plug-in bu olay icin calisacak. Create/Update gibi mesaj isimleri yazarken otomatik olarak tamamlamaya calistigini göreceksiniz. Her bir mesaj icin ayri step’ler tanimlaniz gerekmektedir.

Primary Entity: Bu plug-in hangi entity yani varlik üzerinde calisacak. Buraya account, contact gibi bir varlik adi yazabilirsiniz.

Secondary Entity: Bu plug-in’i ikinci bir varlik icin tanıtacaksak buraya yazabiliriz.

Event Pipeline Stage of Execution: Bu kisimda plug-in’i pre yani veri veritabanina gitmeden mi calistiracagiz yoksa post yani kaydedildikten sonra mi calistiracagiz bunu seçiyoruz.

Execution Mode: (sadece post da ikisinden birini seçebilmekteyiz) kod senkron yani sistemde kullanici ile etkileşimli ayni anda mi hareket etsin yoksa asenkron yani kullanicidan bagimsiz arka tarafta sessizce mi calissin bunu seciyoruz.

Deployment: Bu kod server da mı calissin yoksa Outlook client gibi offline modda da calissin seçeneğidir.

 

Bu yukarida acikladigim bolumler standart ayarlar. Yani her plug-in step’i tanimladigimizda mutlaka bakmamiz gereken ayarlar. Ekranda bir de farkli ayarlar var onlara da bakalim.


Event Handler: Bu kodun calismaya baslayacagi class’in seçildiği yerdir. Cok değişik bir hareket yapmadiginiz surece zaten plugin registration tool otomatik bir sekilde “Execute” metodunu görecek ve orayi seçecektir.

Name: Sistem bu step icin otomatik bir atamakta ama değiştirmek isterseniz buradan yapabilirsiniz.

Run in User’s Context: Belki dokunmaniz gereken noktalardan biri olabilir. Bu kodu hangi kullanici yetkileriyle calistirmak istiyorsaniz onu seçebilirsiniz. Standartta ayari “Calling User” yani hangi kullanici bu işlemi yaparsa seçilidir.

ExecutionOrder: eger ayni varlik içinde ve ayni mesaj icin başka bir plug-in daha varsa buraya sira numaralari vererek hangisini once-sonra calisacagini belirleyebilirsiniz.

 

Unsecure ve Secure Configuration’larin ne ise yaradigina zaten “Plug-in Yapici Metodlari” basligi altinda değinmiştim.

 

Butun gerekli ayarlamalari yaptıktan sonra en allta bulunan “Register New Step” düğmesine tıklayarak işlemi tamamlıyoruz.  Artik plug-in’i test edebilirsiniz.

Hadi Plug-in Yazalim

Plug-in’ler hakkında temel bilgileri öğrendiğimize gore artik plug-in yazabiliriz. Asagida vereceğim orneklerde bir plug-in içerisinde yapabileceğiniz temel işlemleri anlatmaya calisacagim. Bu kodlara CRM SDK\SampleCode\CS\Plug-ins içerisinden ulaşabilirsiniz.

Veritabanina gitmeden kayitlari değiştirmek

Daha once de ifade ettiğim gibi CRM içerisinde bir kayit veritabanina gitmeden Pre-Operation(Pre-Event) adiminda kaydettiğiniz bir plug-in ile kullanicinin oluşturmak istediği kayda ulaşabilirsiniz.

Asagidaki kod oluşturulan bir account(firma) nesnesinin içerisine eger yok ise bir numara oluşturarak bunu accountnumber(müşteri numarasi) alanina vermekte böylece kayitta olmayan bir alan veritabanina bu alan eklenmiş bir sekilde gidecek.

Kodda da görebileceğiniz uzere ilk once Execute metodumuzu oluşturuyoruz. Biliyorsunuz ki bu metod parametre olarak içine aldigi ServiceProvider ile bize ihtiyacimiz olan butun verileri sunacak.

Ilk once Context’i ServiceProvider’dan türetiyoruz. Daha sonra da Context içerisindeki Target’in bir Entity mi olup olmadigina bakıyoruz. Tam bu noktada gelin Context nesnesinin içerisine bir bakalim.

Asagidaki ekran goruntusunu bu plug-in’i debug ettiğim anda aldim. Ilerleyen bölümlerde bir plug-in’in nasil debug edileceğini anlatacagim. Simdilik Context’e odaklanalim.

Gorebileceginiz uzere Context UserId, BusinessUnitId, MessageName, PrimaryEntityName, CreatedOn gibi o anda isimize yarayacak birçok veri yiginini içermekte. Iste Plug-in içerisinde ihtiyacimiz olanlari buradan alip kullanacagiz.

Entity ise onu entity sinifindan bir nesne haline getiriyoruz.

Bu sefer bu oluşturduğumuz yeni entity nesnesi account turunden bir nesne midir diye bakıyoruz.

Daha sonra Icinde accountnumber diye bir alan var mi diye bakıyoruz. Yoksa iste tam bu noktada veritabanina doğru yolculuğa cikmis olan kullanicinin bu kaydına müdahale edip içerisine bizim urettigimiz numara ile accountnumber nesnesini doldurarak entity mize veriyoruz. Artik içerisinde accountnumber alani da var.

             /// <summary>

        /// A plug-in that auto generates an account number when an

        /// account is created.

             /// </summary>

        /// <remarks>Register this plug-in on the Create message, account entity,

        /// and pre-operation stage.

        /// </remarks>

        //<snippetAccountNumberPlugin2>

        public void Execute(IServiceProvider serviceProvider)

             {

            // Obtain the execution context from the service provider.

            Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)

                serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));

 

            // The InputParameters collection contains all the data passed in the message request.

                    if (context.InputParameters.Contains("Target") &&

                           context.InputParameters["Target"] is Entity)

            {

                // Obtain the target entity from the input parameters.

                           Entity entity = (Entity)context.InputParameters["Target"];

                //</snippetAccountNumberPlugin2>

 

                // Verify that the target entity represents an account.

                // If not, this plug-in was not registered correctly.

                if (entity.LogicalName == "account")

                {

                    // An accountnumber attribute should not already exist because

                    // it is system generated.

                                  if (entity.Attributes.Contains("accountnumber") == false)

                                  {

                        // Create a new accountnumber attribute, set its value, and add

                        // the attribute to the entity's attribute collection.

                                        Random rndgen = new Random();

                        entity.Attributes.Add("accountnumber", rndgen.Next().ToString());

                                  }

                                  else

                                  {

                                        // Throw an error, because account numbers must be system generated.

                        // Throwing an InvalidPluginExecutionException will cause the error message

                        // to be displayed in a dialog of the Web application.

                        throw new InvalidPluginExecutionException("The account number can only be set by the system.");

                                  }

                           }

                    }

             }

Umarim birsey dikkatinizi çekmiştir. Entity içerisine direkt alani Attributes.Add metodu ile ekliyoruz. Yani bir update işlemi yapmıyoruz zaten kayit daha veritabanina gitmedi doğal olarak CRM Service nesnesinin bir instance’ini olusturmamiza da gerek kalmadi.

Update aninda update edilmemiş değerlere ulaşmak

Baslik biraz karisik gelebilir ama aslinda tam olarak da durum bu update aninda update edilmemiş alanlara ulaşmak istiyorsaniz birazdan bahsedecegim yöntemi uygulamniz gerekmekte. Peki biz neye neden ulasamiyoruz diye soracak olursaniz aciklayayim. Dynamics CRM’in Create aninda kayit ile ilgili elde ettiği butun bilgileri bize Target’tan türettiğimiz entity içerisinde verir. Asagidaki ekran goruntusunde de bu durumu görebilirsiniz.

Update aninda durum bundan farkli sistem bize sadece (doğal olarak) update edilmiş alanlari vermektedir. Asagidaki ekran goruntusune bakabilirsiniz.

Ben bu contact üzerinde sadece jobtitle alanini güncelledim. Sistem jobtitle ve yaninda ihtiyaç duyulacak birkaç bilgiyi daha Target’a vermekte o kadar.

Simdi konu basligina dönecek olursak iste tam bu update aninda ben update edilmemiş bir alanin değerine ulaşmak istersem ne yaparim? Sistemde bunun için Image yani o kaydin o anki snapshot’ini almamizi sağlayan bir ozellik var.

Herhangi bir plug-in step’i üzerinde sag tuşa basarak “create new image” seçeneğini seçtiğimizde asagidaki ekran karsimiza gelecektir.

Bu ekranda Pre ve Post olarak istediğimiz alanlari parametre olarak seçebilir ve bunlara genel bir isim verebiliriz. Ben Target dedim.

Iste bu ayarlamayi yapdiginizda asagidaki ekran goruntusundeki gibi update aninda değişmeyen ama sizin erişmek istediğiniz alan/alanlar PreEntityImages içerisinde hazir olacaktır.

 

Peki kod tarafında buna nasil ulasacagiz derseniz o da su sekilde olacak;

Once image nesnesine ulaşıyoruz:

Entity image = (Entity)context.PreEntityImages["Target"];

Sonra image içerisinden istediğimiz alana erişiyoruz:

String descriptionMessage = "Old full name: " + image["fullname"];

 

Uzerinde calistigim nesnenin id’si nerede?

Update edilmis ya da post-operation durumdaki bir nesnenin id’sine ihtiyaç duyarsaniz su sekilde elde edebilirsiniz:

Guid id = new Guid(context.OutputParameters["id"].ToString());

Ya da

Guid id = context.PrimaryEntityId;

 

Plug-in’ler arasinda bilgi paylasimi

Eger bir plug-in içinde oluşturduğumuz bir veriyi diğer plug-in’lerin de erişmesini istiyorsak “SharedVariables” yapisini kullanmamiz gerekmekte. SharedVarabiles aslinda bir parametre kolleksiyonu ve içerisinde paylaşmak istediğiniz nesneleri saklayabilirsiniz.

 

Asagida 2 tane plug-in yer almakta. Ilk plug-in (PreEventPlugin)

context.SharedVariables.Add("PrimaryContact", (Object)contact.ToString());


Kodu ile Contact isimli Guid nesnesini “PrimaryContact” adinda SharedVariables içerisinde saklamakta.

 

Ikinci plug-in ise Post-event aninda calismakta ve SharedVariables’den istediği değeri örnekteki gibi almaktadır.

 

Boylece plug-inler arasi veri transferi ve yapilmis olmakta.

 

Guid contact = new Guid((string)context.SharedVariables["PrimaryContact"]);

 

 

    public class PreEventPlugin : IPlugin

    {

        public void Execute(IServiceProvider serviceProvider)

        {

            // Obtain the execution context from the service provider.

            Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)

                serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));

 

            // Create or retrieve some data that will be needed by the post event

            // plug-in. You could run a query, create an entity, or perform a calculation.

            //In this sample, the data to be passed to the post plug-in is

            // represented by a GUID.

            Guid contact = new Guid("{74882D5C-381A-4863-A5B9-B8604615C2D0}");

 

            // Pass the data to the post event plug-in in an execution context shared

            // variable named PrimaryContact.

            context.SharedVariables.Add("PrimaryContact", (Object)contact.ToString());

        }

    }

 

    public class PostEventPlugin : IPlugin

    {

        public void Execute(IServiceProvider serviceProvider)

        {

            // Obtain the execution context from the service provider.

            Microsoft.Xrm.Sdk.IPluginExecutionContext context = (Microsoft.Xrm.Sdk.IPluginExecutionContext)

                serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext));

 

            // Obtain the contact from the execution context shared variables.

            if (context.SharedVariables.Contains("PrimaryContact"))

            {

                Guid contact =

                    new Guid((string)context.SharedVariables["PrimaryContact"]);

 

                // Do something with the contact.

            }

        }

    }