Dynamics 365 Tools - CRM Dev Tools (Google Chrome)

Bu tool ile basit işlemleri kolaylakla yapabilirsiniz. 

Örneğin , login olan kullanıcının bilgilerini bir kaç tıklamayla öğrenebilirsiniz.


Buradan Google Chrome a ekleyebilirsiniz.



Google Chrome üzerinde F12 tuşuna basılarak Developer Tool açılır . Yukarıdaki eklentiyi ekledikten sonra Developer Tools da CRM Dev Tools tabı görünecektir.


Bu taba tıklanarak kullanacağımız ekranlar bulabiliriz.

USER
Buradan CRM e login olan kullancı hakkında bilgilere ulaşabiliriz.



FIND

FETCH


PLUGINS



DEBUG


Daha fazla bilgi için tıklayınız.

Dynamics 365 SQL - Global OptionSet Sorgulama



SQL Sorgu

SELECT OS.NAME, L.LABEL, AV.VALUE
FROM AttributePicklistValueAsIfPublishedLogicalView AV
JOIN OptionSetAsIfPublishedLogicalView  OS
ON AV.OptionSetId = OS.OptionSetId
JOIN LocalizedLabelAsIfPublishedLogicalView  L
ON L.OBJECTID = AV.AttributePicklistValueId
WHERE OS.ISGLOBAL = 1 AND OS.IsCustomOptionSet = 1
AND L.OBJECTCOLUMNNAME = 'DISPLAYNAME'
AND OS.NAME ='<Provide Global OptionSet Schema Name>'

Dynamics 365 - Müşteri Veri Tipi (Customer Data Type)


Firma ve ilgili kişi varlıklarının kombinasyonundan oluşmaktadır . Her iki varlıktan tek bir değer setlenebilir.


Firma ve İlgili Kişi için oluşacak relationlara alan oluşturulmadan değer verebiliriz.


Form üzerinden alana veri girişinde hangi varlık altından veri gireceksek o varlığı seçmemiz gerekir.



Not : Microsoft Dynamics CRM 2016 ve sonraki versiyonlarda kullanılmaktadır.


Microsoft Dynamics CRM 2016 Certifications list

Dynamics 365 - Varlığın Guid Değerini Alma (Form Üzerinden)

Çoğu zaman işlemlerimizi yaparken ilgili kaydımızın guid değerine ihtiyacımız  olmaktadır. Bunu öğrenmenin yollarından biri , formdaki AÇILIR PENCERE butonuna basarak açılan formun linkinden öğrenebiliriz.



Açılan formun url ini alalım.


id=%7b ( { ) ile %7d ( } ) arasındaki 32 haneli değer varlığın guid değerini içerir.

http://hostname/orgname/main.aspx?etc=2&extraqs=&histKey=561271371&id=%7b3B6C4759-BCFD-E611-8F1E-00155D005200%7d&newWindow=true&pagetype=entityrecord#696644333

Not : Eğer bir kaydın guid değerini biliyorsak ve crm üzerinde görüntülemek istiyorsak ,  aynı varlığa ait farklı bir kayıt açılır ve linkteki  ilgili değer ile elimizdeki guid değeri değiştirilir ve o kaydın formuna erişilir.


Dynamics 365 - Organizasyon Bilgilerini Alma ( RetrieveCurrentOrganizationRequest )


Organizasyon hakkında bilgiler edinmek için kullanılan bir metotdur.Alttaki ekran görüntüsündeki gibi bilgilere ulaşabilirsiniz.



C# Kodu

  CrmServiceClient crmServ = CrmManagerStatic.GetCrmServiceClient();

            RetrieveCurrentOrganizationRequest req = new RetrieveCurrentOrganizationRequest();


            RetrieveCurrentOrganizationResponse res = (RetrieveCurrentOrganizationResponse)crmServ.Execute(req);



Daha fazla bilgi için tıklayınız.

Not : CRM 2015 ve sonraki versiyonlarda kullanılmaktadır.

Dynamics 365 Javascript – Editable Grids


İlgili makaleye buradan ulaşabilirsiniz.


Dynamics 365 Code - App.Config Dosyasından ConnectionString Verisini Okuma (To Read Connection Strings From App.Config)


Projemize System.Configuration referansını eklememiz gerekir.




    private String GetServiceConfiguration()
        {
            // Get available connection strings from app.config.
            int count = ConfigurationManager.ConnectionStrings.Count;
            // Create a filter list of connection strings so that we have a list of valid
            // connection strings for Microsoft Dynamics CRM only.
            List<KeyValuePair<String, String>> filteredConnectionStrings =
            new List<KeyValuePair<String, String>>();
            for (int a = 0; a < count; a++)
            {
                if (isValidConnectionString(ConfigurationManager.ConnectionStrings[a].ConnectionString))
                    filteredConnectionStrings.Add
                    (new KeyValuePair<string, string>
                    (ConfigurationManager.ConnectionStrings[a].Name,
                    ConfigurationManager.ConnectionStrings[a].ConnectionString));
            }
            // If one valid connection string is found, use that.
            if (filteredConnectionStrings.Count == 1)
            {
                return filteredConnectionStrings[0].Value;
            }
            return null;
        }

        private Boolean isValidConnectionString(String connectionString)
        {
            // At a minimum, a connection string must contain one of these arguments.
            if (connectionString.Contains("Url=") ||
            connectionString.Contains("Server=") ||
            connectionString.Contains("ServiceUri="))
                return true;
            return false;
        }

Dynamics 365 - CrmService Kullanımı (Microsoft.Xrm.Tooling.Connector)





CrmServiceClient crmServ = GetCrmServiceClient();


  public CrmServiceClient GetCrmServiceClient()
        {
            CrmServiceClient crmSvc = new Microsoft.Xrm.Tooling.Connector.CrmServiceClient(@"AuthType=AD;Url=https://crmdev.gkhnmnts.com/CRMDEV; Domain=gkhn; Username=crmadmin; Password=password");

            return crmSvc;
        }


Dynamic 365 Code - İki Varlık Arasındaki Eşlenmiş Alanları Çekme - GetAttributesMap (Mapping)


Aşağıdaki kod ile lead ve account arasındaki mapping edilen kolonları çekebiliriz.


 EntityCollection attributeMaps = GetAttributesMap(crmService, "lead", "account");

                            Entity account = new Entity("account");

                            foreach (var item in attributeMaps.Entities)
                            {
                                string sourceAttributeName = item.GetAttributeValue<string>("sourceattributename");
                                string targetAttributeName = item.GetAttributeValue<string>("targetattributename");
                                if (lead.Attributes.Contains(sourceAttributeName))
                                {
                                    if (sourceAttributeName.ToLower() == "leadid")
                                        account[targetAttributeName] = new EntityReference("lead", lead.Id);
                                    else
                                        account[targetAttributeName] = lead[sourceAttributeName];
                                }
                            }

                            //account["name"] = companyname;

                            accountid = crmService.Create(account);




 private EntityCollection GetAttributesMap(IOrganizationService serv, string sourceentityname, string targetentityname)
        {
            QueryExpression query = new QueryExpression()
            {
                EntityName = "attributemap",
                ColumnSet = new ColumnSet("sourceattributename", "targetattributename"),
                LinkEntities =
                     {
                         new LinkEntity
                          {
                              LinkFromEntityName="attributemap",
                              LinkFromAttributeName="entitymapid",
                              LinkToEntityName = "entitymap",
                              LinkToAttributeName = "entitymapid",
                              LinkCriteria = new FilterExpression
                                    {
                                        FilterOperator = LogicalOperator.And,
                                        Conditions =
                                        {
                                            new ConditionExpression("sourceentityname",ConditionOperator.Equal,sourceentityname),
                                             new ConditionExpression("targetentityname",ConditionOperator.Equal,targetentityname)
                                        }
                                    }
                          }
                     },
                Criteria = new FilterExpression
                {
                    FilterOperator = LogicalOperator.And,
                    Conditions =
                                        {
                                            new ConditionExpression("parentattributemapid",ConditionOperator.Null),
                                            new ConditionExpression("sourceattributename", ConditionOperator.NotNull),
                                            new ConditionExpression("targetattributename", ConditionOperator.NotNull)
                                        }
                }

            };


            return serv.RetrieveMultiple(query);

        }

Dynamics 365 - SecureString Kullanımı



 public static CrmServiceClient GetCrmServiceClient()
        {
            CrmServiceClient crmSvc = new Microsoft.Xrm.Tooling.Connector.CrmServiceClient("username", ConvertToSecureString("password"), "NorthAmerica", "orgname", isOffice365: true);

            return crmSvc;
        }

        private static SecureString ConvertToSecureString(string password)
        {
            if (password == null)
                throw new ArgumentNullException("missing pwd");

            var securePassword = new SecureString();
            foreach (char c in password)
                securePassword.AppendChar(c);
            securePassword.MakeReadOnly();
            return securePassword;
        }

Not : Dynamics 365 kullanıyorsanız , SDK versiyonunuz 8.2 olmalıdır. CRM 2016 için SDK versiyonu 8.0 veya 8.1 olmalıdır.

Dynamics 365 Code - Fırsat Kazanma - Kaybetme (C#)


Fırsat Kazanma

            IOrganizationService crmService = CrmManagerStatic.GetCrmServiceCredential(CRMOrganization.CRM);

            Entity OpportunityClose1 = new Entity("opportunityclose");
            OpportunityClose1["opportunityid"] = new EntityReference("opportunity", new Guid("Opportunity GuId "));
            OpportunityClose1["subject"] = "Won the Opportunity";
            crmService.Create(OpportunityClose1);

            WinOpportunityRequest winQuoteRequest = new WinOpportunityRequest()
             {
                 OpportunityClose = OpportunityClose1,
                 Status = new OptionSetValue((int)OpportunityState.Won)
             };
            crmService.Execute(winQuoteRequest);


Fırsat Kaybetme

 IOrganizationService crmService = CrmManagerStatic.GetCrmServiceCredential(CRMOrganization.CRM);

            Entity OpportunityClose1 = new Entity("opportunityclose");
            OpportunityClose1["opportunityid"] = new EntityReference("opportunity", new Guid("Opportunity GuId "));
            OpportunityClose1["subject"] = "Lose the Opportunity";
            crmService.Create(OpportunityClose1);
            LoseOpportunityRequest request = new LoseOpportunityRequest()
              {
                  OpportunityClose = OpportunityClose1,
                  Status = new OptionSetValue((int)OpportunityState.Lost)
              };
            crmService.Execute(request);

Dynamics 365 - Virtual Entities



Dynamics 365 Temmuz 2017 Güncellemesi  ile gelen özellik olan  sanal varlıklar, veriyi Dynamics 365'te varlıklar olarak sorunsuz bir şekilde temsil ederek, veri replikasyonu yapmadan ve genellikle özel kodlamasız olarak harici sistemlerde bulunan verilerin entegrasyonunu mümkün kılar.



İlgili makaleye buradan ulaşabilirsiniz.


Dynamics 365 Plugin - Rest Web Service Kullanımı (HOW TO CALL REST WEB SERVICE IN PLUG-IN)


Son zamanlarda SOAP kullanmadan REST web hizmetini nasıl kullanacağımı öğrenmek istedim. CRM'de bir kayıt oluşturulduğunda, her seferinde diğer sistemlere veri gönderen bir web servisi yazmak zorunda kalıyordum.

Bildiğiniz gibi, REST hizmeti bir istemci taban yapısına sahiptir ve bu nedenle SOAP'tan biraz farklıdır. Artık referans hizmeti eklemiyoruz ve bunun yerine RestRequest sınıfını kullanıyoruz. Nasıl yapılacağını aşağıdaki kod anlatıyor.

RestSharp ı buradan indirebilirsiniz veya Package Manager Console  ile projenize yükleyebilirsiniz.






C# Code




    RestClient client = new RestClient("url/api/");
            var request = new RestRequest("ControllerName/MethodName", Method.POST);

            //here I preferred to send data in Json  format
            request.AddJsonBody(
                    new
                    {
                        //parameter is the requiring method variable name
                        //value is your data that you want to post
                        parameter1 = "value1",
                        parameter2 = "value1"
                    });
            request.RequestFormat = DataFormat.Json;
            var result = client.Execute(request);
            if (result.StatusCode == System.Net.HttpStatusCode.OK)
            {
                //success

            }

Dynamics 365 - Microsoft Dynamics 365 SDK & UII İndirme



Microsoft Dynamics 365 SDK veUII yı buradan indirebilirsiniz.






Name
Size
Description
MicrosoftDynamics365SDK.exe
83.9MB
Microsoft Dynamics 365 Software Development Kit (SDK) for Dynamics 365 Online and on-premises Dynamics 365
MicrosoftDynamicsCRM2016UII.exe
58.3   MB
User Interface Integration (UII) solution framework, which includes a deployment guide, development guide and api reference for Unified Service Desk.

Dynamics 365 - Silinmiş Kayıtları Geri Getirme Yöntemi (AUDIT)

Bugün müşterilerimizden biriyle telefon görüşmesi yaptım ve önemli kayıtlarından ikisinin bulunmadığını, bulamadığını ve önemli kayıtlar olduğunu söyledi.

İlk başta onun deaktive ettiğini ve bir şekilde bunu göremediğini düşündüm ancak daha sonra denetleme geçmişi sayesinde onları sildiklerini anladım. Sonra kayıtları tekrar kurmanın bir yolunu aramaya başladım. Şimdilik, kayıtları geri yükleme yolunu paylaşacağım ancak ilişkileri paylaşmayacağım.

C# Kodu

            CrmServiceClient crmServ = CrmManagerStatic.GetCrmServiceClient();

            // deleted record's audit id which you want to restore
            Guid auditId = new Guid("deleted_record's_audit_guid");
            // create RetrieveAuditDetailsRequest object          
            var request = new RetrieveAuditDetailsRequest { AuditId = auditId };
            // execute request and retrieve response        
            var response = (RetrieveAuditDetailsResponse)crmServ.Execute(request);
            // create auditDetail object and assign response's auditdetail value
            AuditDetail auditDetail = response.AuditDetail;
            // cast audtitDetail as AttributeAuditDetail which contains record's attributes            
            AttributeAuditDetail attributeAuditDetail = auditDetail as AttributeAuditDetail;
            // recreate the deleted record with the same guid
            if (attributeAuditDetail != null)
                crmServ.Create(attributeAuditDetail.OldValue);

Dynmics 365 Javascript - Formdaki Zorunlu Alan Kontrolü

Formdaki gerekli olan alanların dolu olup olmadığını kontrol etmek için aşağıdaki script metodunu kullanabilirsiniz. Getiye dönüş olarak True veya false değer dönecektir.


Javascript

function CheckMandatoryFields() {
    var populated = true;
    Xrm.Page.getAttribute(function (attribute, index) {
        if (attribute.getRequiredLevel() == "required") {
            if (attribute.getValue() === null) {
                populated = false;
            }
        }
    });
    return populated;
}

Dynamics 365 Javascript - Email Format Script



function EmailFormat(field) {
    try {
        var fieldName = field.getEventSource().getName();
        var email = GetValue(fieldName);

        if (email != null) {
            email = ReplaceFromTurkishChar(email);

            SetValue(fieldName, email);
        }
    }
    catch (e) {
        CommonAlert("An error occured in EmailFormat Function.\nError: " + e.message);
    }
}

function ReplaceFromTurkishChar(text) {

    var normal = new Array("i", "s", "u", "c", "o", "g", "C", "S", "O", "U", "G", "I");
    var turkish = new Array("ı", "ş", "ü", "ç", "ö", "ğ", "Ç", "Ş", "Ö", "Ü", "Ğ", "İ");

    for (var i = 0; i < text.length; i++) {
        for (var j = 0; j < 12; j++) {
            if ((text.charAt(i)) == turkish[j]) {

                text = text.replace((text.charAt(i)), normal[j]);
            }
        }
    }

    return text;
}

NOT
Email alanımıza functionımızı eklerken Pass execution context as first parameter checkboxını seçmemiz gerekecektir.



Dynamics 365 Javascript - Telefon Formatlama Örnek Script


Aşağıdaki örnek kod üzerinde hem Türkiye hem de Türkiye dışındaki ülkeler için telefon formatlama yöntemini bulabilirsiniz.


function TelephoneFormat(fieldName, ulkefieldname,ulkekoduname) {
    try {
        var langId = Xrm.Page.context.getUserLcid();
        if (langId != 1055)
            langId = 1033;

        var oField = GetAttribute(fieldName);

        if (GetValue(fieldName) != null && GetValue(fieldName) != "") {
            var ulke = GetValue(ulkefieldname);
            var _ulkeid = null;

            if (ulke != null && ulke[0] != null && ulke[0].id != null)
                _ulkeid = ConverttoStringFromGuid(ulke[0].id);

            if (_ulkeid != null) {
                var sTmp = oField.getValue().replace(/[^0-9]/g, "");

                if (_ulkeid == GetTurkiyeId()) {
                    switch (sTmp.length) {
                        case 13:
                            oField.setValue("+" + sTmp.substr(0, 3) + " " + sTmp.substr(3, 3) + " " + sTmp.substr(6, 7));
                            break;
                        case 12:
                            oField.setValue("+" + sTmp.substr(0, 2) + " " + sTmp.substr(2, 3) + " " + sTmp.substr(5, 7));
                            break;
                        case 11:
                            oField.setValue("+9" + sTmp.substr(0, 1) + " " + sTmp.substr(1, 3) + " " + sTmp.substr(4, 7));
                            break;
                        case 10:
                            oField.setValue("+90 " + sTmp.substr(0, 3) + " " + sTmp.substr(3, 7));
                            break;
                        case 7:
                            oField.setValue("+90 232 " + sTmp.substr(0, 3) + sTmp.substr(3, 4));
                            break;
                        default:
                            alert('2324440011 şeklinde en az 10 haneli bir telefon numarası giriniz.');
                            SetValue(fieldName, null);
                            break;
                    }
                }
                else {
                    TelephoneFormat2(fieldName, ulkekoduname);
                }
            }
            else {
                if (langId == 1055)
                    CommonAlert("Telefon numarası girmek için ilk önce ülke seçilmelidir.");
                else
                    CommonAlert("Please , firstly select country.");


                setTimeout(function () {
                    SetValue(fieldName, null);
                }, 200);
             
            }
        }
    }
    catch (e) {
        CommonAlert("An error occured in TelephoneFormat Function.\nError: " + e.message);
    }
}

function TelephoneFormat2(fieldadi, ulkekoduname) {
    try {
        var value = GetValue(fieldadi);

        if (typeof (value) != "undefined" && value != null) {
            value = FormatPhoneNumber(value, ulkekoduname);
        }

        SetValue(fieldadi, value);
    }
    catch (e) {
        alert('TelephoneFormat2 error');
    }
}

function FormatPhoneNumber(phoneNo, ulkekoduname) {
    var formattedPhone = phoneNo;
    var ulkekodu = GetValue(ulkekoduname);
    ulkekodu = ulkekodu != null ? ulkekodu : "";

    if (phoneNo.length < 5) {
        if (langId == 1055)
            CommonAlert("Telefon numarası 5 karakterden az girilemez");
        else if (langId == 1055)
            CommonAlert("PhoneFormat error.");

        formattedPhone = "";

        return formattedPhone;
    }

    if (phoneNo.length == 5)
        formattedPhone = phoneNo.replace(/(\d{3})(\d{2})/, "+" + ulkekodu + ' $1 $2');
    else if (phoneNo.length == 6)
        formattedPhone = phoneNo.replace(/(\d{3})(\d{3})/, "+" + ulkekodu + ' $1 $2');
    else if (phoneNo.length == 7)
        formattedPhone = phoneNo.replace(/(\d{3})(\d{4})/, "+" + ulkekodu + ' $1 $2');
    else if (phoneNo.length == 8)
        formattedPhone = phoneNo.replace(/(\d{3})(\d{3})(\d{2})/, "+" + ulkekodu + ' $1 $2$3');
    else if (phoneNo.length == 9)
        formattedPhone = phoneNo.replace(/(\d{3})(\d{3})(\d{3})/, "+" + ulkekodu + ' $1 $2$3');
    else if (phoneNo.length == 10)
        formattedPhone = phoneNo.replace(/(\d{3})(\d{3})(\d{4})/, "+" + ulkekodu + ' $1 $2$3');
    else if (phoneNo.length == 11)
        formattedPhone = phoneNo.replace(/(\d{2})(\d{3})(\d{3})(\d{3})/, "+" + ulkekodu + '$1 $2 $3$4');
    else if (phoneNo.length > 11)
        formattedPhone = phoneNo.replace(/^\(?([0-9]{2})?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})?([0-9]*)$/, "+" + ulkekodu + " $1($2) $3-$4 x$5");

    return formattedPhone;
}

function SetValue(field, value) {
    var attribute = GetAttribute(field);
    if (attribute != null) {
        return attribute.setValue(value);
    }
    return null;
}

function GetValue(field) {
    var attribute = GetAttribute(field);
    if (attribute != null) {
        return attribute.getValue();
    }
    return null;
}

function GetAttribute(field) {
    return Xrm.Page.getAttribute(field);
}

Dynamics 365 Javascript - İki Kere Alert Verme Sorunu

Bazı durumlarda alan kontrolü yaparken kullanıcıya uyarı veririz ve alanın değerini de null yaparız. Bu gibi durumlarda ekrana verilen uyarının iki kere geldiğini görürüz . Javascript kodumuzu debug ettiğimizde düzgün çalıştığını ama normal durumda iki kere alert verdiğini farkederiz.

Örnek vermek gerekirse ,  telefon alanları için formatlama yapalım . Belli durumlar haricinde ekrana "2124440011 şeklinde en az 10 haneli bir telefon numarası giriniz" alertini verelim ve  telefon alanının değerine null atayalım. İşte bu durumda  ekrana verilen "2124440011 şeklinde en az 10 haneli bir telefon numarası giriniz" alerti 2 kere görünecektir..

Örnek Kod Parçası

 alert('2324440011 şeklinde en az 10 haneli bir telefon numarası giriniz.');
 Xrm.Page.getAttribute("fieldname").setValue(null);

function TelephoneFormat(fieldName, ulkefieldname) {
    try {
        var langId = Xrm.Page.context.getUserLcid();
        if (langId != 1055)
            langId = 1033;

        var oField = GetAttribute(fieldName);

        if (GetValue(fieldName) != null && GetValue(fieldName) != "") {
            var ulke = GetValue(ulkefieldname);
            var _ulkeid = null;

            if (ulke != null && ulke[0] != null && ulke[0].id != null)
                _ulkeid = ConverttoStringFromGuid(ulke[0].id);

            if (_ulkeid != null) {
                var sTmp = oField.getValue().replace(/[^0-9]/g, "");

                if (_ulkeid == GetTurkiyeId()) {
                    switch (sTmp.length) {
                        case 13:
                            oField.setValue("+" + sTmp.substr(0, 3) + " " + sTmp.substr(3, 3) + " " + sTmp.substr(6, 7));
                            break;
                        case 12:
                            oField.setValue("+" + sTmp.substr(0, 2) + " " + sTmp.substr(2, 3) + " " + sTmp.substr(5, 7));
                            break;
                        case 11:
                            oField.setValue("+9" + sTmp.substr(0, 1) + " " + sTmp.substr(1, 3) + " " + sTmp.substr(4, 7));
                            break;
                        case 10:
                            oField.setValue("+90 " + sTmp.substr(0, 3) + " " + sTmp.substr(3, 7));
                            break;
                        case 7:
                            oField.setValue("+90 232 " + sTmp.substr(0, 3) + sTmp.substr(3, 4));
                            break;
                        default:
                            alert('2324440011 şeklinde en az 10 haneli bir telefon numarası giriniz.');
                            SetValue(fieldName, null);
                            break;
                    }
                }
                else {
                    TelephoneFormat2(fieldName);
                }
            }
            else {
                if (langId == 1055)
                    CommonAlert("Telefon numarası girmek için ilk önce ülke seçilmelidir.");
                else
                    CommonAlert("Please , firstly select country.");

                SetValue(fieldName, null);
            }
        }
    }
    catch (e) {
        CommonAlert("An error occured in TelephoneFormat Function.\nError: " + e.message);
    }
}


Çözüm 

Çözüm için alanın değerini null yaptığımız satırı setTimeout ile kullanalım . Bu şekilde ekrana uyarı 1 kere gelecektir.

 alert('2324440011 şeklinde en az 10 haneli bir telefon numarası giriniz.');
 setTimeout(function () {
                    Xrm.Page.getAttribute("fieldname").setValue(null);
                }, 200);