cub-e.net

just coding...

Dynamics CRM 2016 - Alternatif Anahtarlar (Alternate Keys)

Dynamics CRM 2016 icerisindeki guzel ozelliklerden biri de artik bir kaydi tanimlamak icin Guid disinda alternative bir anahtar da tanimlayabiliyor olmamiz. Bu sayede CRM’i baska sistemlerle entegre etmek daha da kolay hale gelmekte. Excel’den veri aktarimi yapmak ya da baska bir uygulamayla entegre ederken diger uygulamanin tanimlayicilarini CRM icersinde tanimlayabilmek bize buyuk esneklik kazandirmakta.

CRM arabiriminde Ayarlar(Settings)->Ozellestirmeler(Customization)->Sistemi Ozellestir(Customize System) adimlarini takip ederek herhangi bir nesne(entity)yi actigimizda anahtar tanimlama ekranina ulasabilmekteyiz.

Bu ekran vasitasiyla tanimlayicilari ekran goruntusunde gosterildigi gibi tanimlayabiliriz.

Burada onemli olan nokta ise gereksinimlerinize gore bir ya da birden fazla alani birlestirerek bir anahtar olusturabiliyorsunuz.

Bir alternative anahtar olusturdugunuzda arka tarafta CRM veritabani uzerinde sorgu performansini artirmak amaciyla bir bir sistem ise calismakta ve bir index olusturulmaktadir. Sistemdeki kayit sayiniza bagli olarak bu islem biraz zaman alabilir.

Bu arada String, Integer, Decimal alanlari bu islem icin kullanabilirsiniz. Olusturdugunuz key’i Update ve Upsert (yani Update or Insert) isleminde kullanabilirsiniz.

            using (var service = new OrganizationService(crmConnection))

            {

                // Use alternate key (accountnumber) field to identify an account record

                Entity account = new Entity("account", "accountnumber", "MWNS-123");

 

                // Set new credit limit;

                account["creditlimit"] = new Money(120000);

 

                // Entity reference using alternate key (emailaddress1) on contact entity

                account["primarycontactid"] = new EntityReference("contact", "emailaddress1", "test@test.com");

 

                UpdateRequest request = new UpdateRequest() { Target = account };

                UpdateResponse response = (UpdateResponse)service.Execute(request);

            }

Bu kullanim seklinin disinda bir de Entity ve Entity Reference siniflari icerisinde KeyAttributes olarak da erisme ve kullanma hakkina sahibiz.

            using (var service = new OrganizationService(crmConnection))

            {

                // Use alternate key (accountnumber) field to identify an account record

                Entity account = new Entity("account")

                {

                    KeyAttributes = new KeyAttributeCollection

                    {

                        {"accountnumber", "MWNS-123" }

                    }

                };

 

                // Set new credit limit;

                account["creditlimit"] = new Money(100000);

 

                // Entity reference using alternate key (emailaddress1) on contact entity

                account["primarycontactid"] = new EntityReference("contact")

                {

                    KeyAttributes = new KeyAttributeCollection

                    {

                        {"emailaddress1", "test@test.com"}

                    }

                };

 

                UpdateRequest request = new UpdateRequest() { Target = account };

                UpdateResponse response = (UpdateResponse)service.Execute(request);

            }

Eger CRM icerisinde talep ettigiginiz key bulunmaz ise asagidaki hatayi alabilirsiniz.

A record with the specified key values does not exist in account entity

Bu linklerden daha detayli bilgi alabilirsiniz.

CRM Workflow Mimarisi

28 Kasim Carsamba günü saat 20:30 - 21:30 arasında bir webcast verecegim. Internet uzerinden yapilacak olan bu yayina herkes katilabilir. Link daha sonra paylasilacaktir.

CRM Semineri

15 KasimPazar günü saat 10:30 - 16:30 arasında Omerd Business Solutions ofisinde "CRM, XRM Kavramları ve Dynamics CRM" konulu bir seminer vereceğim.

CRM Raporlama Mekanizmasi

12 Kasim Carsamba günü saat 20:30 - 21:30 arasında bir webcast verecegim. Internet uzerinden yapilacak olan bu yayina herkes katilabilir. Link daha sonra paylasilacaktir.

CRM Semineri Duyurusu

11Temmuz Cumartesi günü saat 10:30 - 12:30 arasında Bahçeşehir Üniversitesinde "CRM, XRM Kavramları ve Dynamics CRM" konulu bir seminer vereceğim. İçerik ise şu şekilde olacak; Dünya’da uzun yıllardır konuşulan CRM “Müşteri İlişkileri Yönetimi” kavramı müşterimizin neleri sevdiğini, neye para harcadığını ve neleri yapmaktan hoşlandığını kısacası bize müşterimizin kim olduğu gösteren temeller üzerine oturmuştur. XRM sadece müşteri değil onun haricinde dış dünyada yönettiğimiz varlıkların bize kim/ne olduğunu  göstermektedir. İşte bu seminerde Microsoft Dynamics CRM’in bu iki kavramın ortasına nasıl oturduğunu ve programatik olarak nasıl geliştirilebileceği anlatılacaktır.

Microsoft Dynamics CRM, adındaki CRM ibarisi nedeniyle sadece Müşteri İlişkileri departmanlarını ilgilendiren bir yazılım olarak anlaşılmaktadır. Aslında Dynamics CRM bir platfomdur ve üzerinde sizin şekillendirdiğimiz bir çok altyapıya destek verebilir.

Dynamics CRM ve Application Insights Entegrasyonu

Bircok Microsft Azure servisini Dynamics CRM ile entegre edebilmekteyiz. Bunlardan en guzel orneklerden birisi Application Insights ve Dynamics CRM birlikteligi. Bu makalede bu Application Insights ile Dynamics CRM'i nasil konusturacagimizi gorecegiz. Oncelikle Application Insights'in ne olduguyla baslayalim isterseniz. 
Visual Studio Application Insight bir telemetri servisidir yani bir sistemi detayli olarak incelemek sitediginizde ona veri gonderdginiz ve bu verileri detaylari bir sekilde grafikler ve tablolar halinde izlediginiz sonucunda rapolar alarak sisteminizin durumu hakkinda bilgiler edindiginiz bir hizmettir. Kisacasi size sisteminizin saglikli calisip calismadigi hakkinda olceklenebilir bilgiler vermektedir.
Dynamics CRM ise bir web tabanli uygulama oldugundan IIS uzerinde olusan web sayfasi goruntuleme taleplerini bunlarin suresini ve bu taleplerin kimden geldigini, hangi sayfalara bakildigini detayli olarak Application Insights'a aktarabiliriz.
Hadi baslayalim.

Azure icinde Application Insights kaynagi olusturalim

Azure hesabiniz yoksa bu adresten olusturabilirsiniz. Sisteme giris yaptiktan sonra Browse'a tikladiktan sonra Application Insights'i secenegini ile olusturma penceresini aciyoruz burada tek dikkat etmeniz gereken nokta Application Type seceneginde Asp.Net'i secmeniz gerekmekte. Gerekli bilgileri doldurdukran sonra Create dugmesiyle kendi Application Insights'inizi olusturabilirsiniz.



Bu noktadan sonra ekrandaki grafiklere tiklayarak her bir grafik bolumunun icinde o bolume nasil veri atabileceginize dair ornekler yer almakta.


JavaScript ile CRM icerisinden veri gonderelim

Dynamics CRM'i acip Ayarlar(Settings)>Ozellestirme(Customization)>Customize the System(Sistemi Ozellestir) bolumunden yeni Web Resource(Web Kaynagi) ekliyoruz.


Ben asagidaki kod parcasini kullaniyorum bu kod parcasi ile CRM icerisinden kullaniciyi ve islem yapilan entity'i(nesne) parametre olarak gonderiyorum.

var UserName;
var Alias;
var serverUrl;

function Getinfo() {
    var context;
    var UserID;
    var ODataPath;
    var selectFields = "$select=DomainName,FullName";

    context = Xrm.Page.context;
    serverUrl = context.getClientUrl();
    UserID = context.getUserId();
    ODataPath = serverUrl + "/XRMServices/2011/OrganizationData.svc";

    var retrieveUserReq = new XMLHttpRequest();
    retrieveUserReq.open("GET", ODataPath + "/SystemUserSet(guid'" + UserID + "')?" + selectFields, false);
    retrieveUserReq.setRequestHeader("Accept", "application/json");
    retrieveUserReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    retrieveUserReq.onreadystatechange = function () {
        retrieveUserReqCallBack(this);
    };
    retrieveUserReq.send();
}

function retrieveUserReqCallBack(retrieveUserReq) {
    if (retrieveUserReq.readyState == 4 /* complete */) {
        if (retrieveUserReq.status == 200) {
            var retrievedUser = JSON.parse(retrieveUserReq.responseText).d;
            if (retrievedUser.FullName != null) {
                UserName = retrievedUser.FullName;
                Alias = retrievedUser.DomainName;
            }
        }
    }
}

function captureTelemetry() {
    var appInsights = window.appInsights || function (config) {
        function s(config) { t[config] = function () { var i = arguments; t.queue.push(function () { t[config].apply(t, i) }) } } var t = { config: config }, r = document, f = window, e = "script", o = r.createElement(e), i, u; for (o.src = config.url || "//az416426.vo.msecnd.net/scripts/a/ai.0.js", r.getElementsByTagName(e)[0].parentNode.appendChild(o), t.cookie = r.cookie, t.queue = [], i = ["Event", "Exception", "Metric", "PageView", "Trace"]; i.length;) s("track" + i.pop()); return config.disableExceptionTracking || (i = "onerror", s("_" + i), u = f[i], f[i] = function (config, r, f, e, o) { var s = u && u(config, r, f, e, o); return s !== !0 && t["_" + i](config, r, f, e, o), s }), t
    }({
        instrumentationKey: "Burayi degistirin"
    });

    window.appInsights = appInsights;
    appInsights.trackPageView(Xrm.Page.data.entity.getEntityName(), serverUrl, { User: Xrm.Page.context.getUserName(), DomainName: Alias });
    appInsights.trackEvent(Xrm.Page.data.entity.getEntityName());
}

function startPoint() {
    Getinfo();
    captureTelemetry();
}

Kodun icerisindeki "instrumentationKey: "Burayi degistirin"" bolumundeki instrumentationKey "Essentials" altinda bulabilirsiniz. 

Ben yukaridaki kodu Account(Firma) ve Contact(Contact) entity'lerinin onLoad event'lerine yerlestirdim.


Bunu yapmak icin form uzerindeki uc noktaya tikiiyoruz ve form duzenleyicisini aciyoruz. Form duzenleyicisi uzerinden Form Ozelliklerini aciyoruz ve biraz once eklemis oldugumuz js web kaynagini buradan seciyoruz ve ekliyoruz.


Yapmis oldugumuz degisiklikleri kaydedip formu yayinliyoruz,
Artik form her acildiginda  Application Insights'e veriler gidecektir. Benim demo sistemimden elde ettigim ekran goruntuleri asagidaki gibidir. AppInsights'a ilk girdigimde asagida goruldugu gibi bir ekran bizi karsilamakta. Sirasiyla bu kutucuklara tiklafdigimda detayli bilgileri almaktayim.


Request ve Response zamanlarini;

Kullanicinin sayfalari ne zaman hangi cihazdan cagirdigi ve yuklenme surelerini;


hangi formlarin ne kadar cagrildigini;


ve metadata bilgilerine;


yukarida goruldugu gibi ulasabilmekteyim. Bunun haricinde formlarda olusan hatalari ve kullanici detaylarini(geolocation gibi) da almaktayim. 

Application Insights hakkinda daha fazla bilgiye buradan ulasabilirsiniz.

CRM Plugini Yaziyoruz :)

23 Eylul Carsamba günü saat 20:30 - 21:30 arasında bir webcast verecegim. Internet uzerinden yapilacak olan bu yayina herkes katilabilir. Link daha sonra paylasilacaktir.

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;

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.