Wednesday, 22 August 2018


Error connecting to Online Dynamics 365 {Unable to Login to Dynamics CRM OrganizationWebProxyClient is null}


While connecting to online dynamics CRM 365 (Version 1710 (9.0.2.1465)) through  "Microsoft.Xrm.Tooling.Connector"
I got the above error. I  was trying to connect using visual studio 2017.

Below was my code  behind.

             
   var connectionString = ConfigurationManager.ConnectionStrings["Xrm"].ConnectionString;
 CrmServiceClient _crmSvc = new CrmServiceClient(connectionString);
 IOrganizationService crmservice = _crmSvc.OrganizationServiceProxy;

Following is app.conconfig setting

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/>
  </startup>

  <connectionStrings>
    <add name="Xrm" connectionString="Url=https://buildme.crm8.dynamics.com;
AuthType=Office365;
Username=my@buildme.onmicrosoft.com; Password=pass@word1"/>
  </connectionStrings>


</configuration>
I used following approaches to resolve the issue.But nothing worked and error 
continued to occur.
1. I used latest SDK dll
2. I used (ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;)
 before instantiating CrmServiceClient .
3.I used unique organization name in connection string.
4.I moved to .Net framework Version=v4.6.2.
Error Resolution:
I tried connecting CRM with Xrmtoolbox and i saw below error in log file.
"Error : The security timestamp is stale because its expiration time 
('2018-08-22T15:59:40.256Z') is in the past.
 Current time is '2018-08-24T18:52:45.924Z' and allowed clock skew is '00:05:00'"
Solution:
I have updated my system time which was ahead with the CRM online user Timezone.
This fixed the crm connection issue and i was able to connect.
Hope it helps.


Monday, 31 October 2016

Multiselect Picklist control for MS CRM 2016/2015/2013

This is the feature which is missing in CRM. Althogh  CRM has  this  inbuilt feature and they use this in Advanced find.
Now they are planning to introduce this option in crm 365 .
I am working on a HTML 5 control which imitates CRM multi-select control.

What it does?

It takes a option set field and renders it in the control.User can select the values from the available values.Selected values are shown in custom field.Just save the CRM form. Thats All  :)

Demo is shown below.


Wednesday, 17 February 2016

Get All fields available on MS CRM form using c#

If you want to get all the fields available on a MS CRM form.
You can use below C# code to get  all attributes.

Below code requires entity logical name and formid.

To get the formid open the record in MS CRM form editor and press  F12 (developer tools) use Chrome for better experience, Search formId in Elements tab.

You will get following results.

<input name="formId" type="hidden" value="{b053a39a-041a-4356-acef-ddf00182762b}">

OR

Mscrm.FormEditorVariables.currentFormId = '\x7bb053a39a-041a-4356-acef-ddf00182762b\x7d'

Take this FormId as you wish :) and proceed for the our custom application.

           // Obtain an organization service proxy.
           .
            using (var _orgService = new OrganizationService(connection))
            {

                string formId = "{b053a39a-041a-4356-acef-ddf00182762b}";

                XmlDocument form = RetrieveEntityForms("account", formId, _orgService);

                XmlNodeList nodeList = (form.SelectNodes("//control"));

                StringBuilder sbAttributes = new StringBuilder();;
                                 

                foreach (XmlNode elem in nodeList)
                {
                    if (elem.Attributes["datafieldname"] != null)
                    {
                        string strValue = elem.Attributes["datafieldname"].Value;

                        sbAttributes.AppendLine(strValue);
                    }


                }                

                Console.WriteLine(sbAttributes.ToString());
                
                Console.Write("DONE!!");
                Console.ReadKey();
                

            }

          
 public static XmlDocument RetrieveEntityForms(string logicalName,string formid, IOrganizationService oService)
        {
            QueryByAttribute qba = new QueryByAttribute("systemform");
            qba.Attributes.AddRange("objecttypecode", "type","formid");
            qba.Values.AddRange(logicalName, 2, formid);
            qba.ColumnSet = new ColumnSet(true);

            EntityCollection ec = oService.RetrieveMultiple(qba);

            StringBuilder allFormsXml = new StringBuilder();
            allFormsXml.Append("");

            foreach (Entity form in ec.Entities)
            {
                allFormsXml.Append(form["formxml"]);
            }

            allFormsXml.Append("");

            XmlDocument docAllForms = new XmlDocument();
            docAllForms.LoadXml(allFormsXml.ToString());

            return docAllForms;
        }

Friday, 15 January 2016

MS CRM 2016 Web API - Retrieve

This example returns data for an account entity with the primary key value equal to 9C33D98E-2FAD-E511-80DE-6C3BE5A8380C. This query also expands data from the related opportunities of Account and related tasks using the respective single-valued and collection-valued navigation properties: opportunity_parent_account and Account_Tasks. To identify the appropriate properties and navigation property names to use for the account entity, see the account EntityType

function RetrieveAccountData()
{
var organizationUrl = Xrm.Page.context.getClientUrl();

var query = "accounts(9C33D98E-2FAD-E511-80DE-6C3BE5A8380C)?$select=accountcategorycode,accountnumber,creditonhold,createdon,numberofemployees,name,revenue&$expand=opportunity_parent_account($select=createdon,name),Account_Tasks($select=subject,scheduledstart)";
var req = new XMLHttpRequest();
req.open("GET",organizationUrl + "/api/data/v8.0/" + query, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
    if (this.readyState == 4) {
        req.onreadystatechange = null;
        if (this.status == 200) {
  
    var RetrievedAccount = JSON.parse(this.response);
    console.log(RetrievedAccount);
          alert(RetrievedAccount.name);
        } else {
            var error = JSON.parse(this.response).error;
            alert(error.message);
        }
    }
};
req.send();
}

Monday, 4 January 2016

MS CRM 2016 Web API Operations - Delete a single property value

Delete a single property value:

To delete the value of a single property use a DELETE request with the property name appended to the Uri of the entity.

The following example deletes the value of the fax property of an account entity.
function UpdatAccountSingleValueUsingDELETE() {

debugger;
var clientURL = Xrm.Page.context.getClientUrl();
var AccountId =  "B3A2B300-A8AF-E511-80DD-6C3BE5A878BC";

//Single Property value  which you want to delete
var Property ="fax";

UpdatAccountSingleValue(AccountId,clientURL,Property);


}
 

function UpdatAccountSingleValue(AccountId,clientURL,Property)
{
 
var req = new XMLHttpRequest();
req.open('DELETE', clientURL + "/api/data/v8.0/accounts(" + AccountId + ")/"+Property, true);
req.setRequestHeader("Content-type","application/json");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");

req.onreadystatechange = function () {
 if (this.readyState == 4 /* complete */) {
  req.onreadystatechange = null;
  if (this.status == 204) {   
   console.log("Updated account with ID: "+ AccountId)
  }
  else {
   var error = JSON.parse(this.response).error;
   console.log(error.message);
  }
 }
};

req.send();
 

}

MS CRM 2016 Web API Operations - Update a single property value


Update a single property value :

When you want to update only a single property value use a PUT request with the property name appended to the Uri of the entity.

Whenever you want to update single attribute of an entity it can be done by using PUT verb.

Note : while creating object use "value"  property to accommodate the Updated value of attribute.


function UpdatSinglePropertyAccountByPUT() {

debugger;
var clientURL = Xrm.Page.context.getClientUrl();
var AccountId =  "B3A2B300-A8AF-E511-80DD-6C3BE5A878BC";

//Attribute which you want to update e.g Name
var Property ="name";

var AccountTobeUpdated ={};
AccountTobeUpdated["value"] ="My first Update On Account by API using PUT";

UpdatAccountByPUT(AccountId,clientURL,AccountTobeUpdated,Property)


}

 

function UpdatAccountByPUT(AccountId,clientURL,AccountTobeUpdated,Property)
{
 
var req = new XMLHttpRequest();
req.open('PUT', clientURL + "/api/data/v8.0/accounts(" + AccountId + ")/"+Property, true);
req.setRequestHeader("Content-type","application/json");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");

req.onreadystatechange = function () {
 if (this.readyState == 4 /* complete */) {
  req.onreadystatechange = null;
  if (this.status == 204) {   
   console.log("Updated account with ID: "+ AccountId)
  }
  else {
   var error = JSON.parse(this.response).error;
   console.log(error.message);
  }
 }
};
req.send(JSON.stringify(AccountTobeUpdated));
 

}


Thursday, 31 December 2015

MS CRM 2016 Web API Operations - Basic Update



Basic Update:

In the last post I have created an Account using Web API call. Here we will update the created Account. Update operations use the HTTP PATCH verb. Pass a JSON object containing the properties you want to update to the URI that represents the entity. A response with a status of 204 will be returned if the update is successful.

Note: 

When updating an entity, only include the properties you are changing in the request body. Simply updating the properties of an entity that you previously retrieved, and including that JSON in your request, will update each property even though the value is the same. This can cause properties to appear to have been updated in auditing data when in fact they haven’t actually changed.


function UpdatAccount(AccountId,clientURL,AccountTobeUpdated)
{
 
var req = new XMLHttpRequest();
req.open('PATCH', clientURL + "/api/data/v8.0/accounts(" + AccountId + ")", true);
req.setRequestHeader("Content-type","application/json");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");

req.onreadystatechange = function () {
 if (this.readyState == 4 /* complete */) {
  req.onreadystatechange = null;
  if (this.status == 204) {   
   console.log("Updated account with ID: "+ AccountId)
  }
  else {
   var error = JSON.parse(this.response).error;
   console.log(error.message);
  }
 }
};
req.send(JSON.stringify(AccountTobeUpdated));
 

}

//This method will update an existing record.
function UpdateAccountUsingWebAPI() {

debugger;
var clientURL = Xrm.Page.context.getClientUrl();
var AccountId =  "B3A2B300-A8AF-E511-80DD-6C3BE5A878BC";

var AccountTobeUpdated ={};
AccountTobeUpdated["name"] ="My first Update On Account by API";
AccountTobeUpdated["accountnumber"] = "841843";
AccountTobeUpdated["fax"] ="9738310781";


UpdatAccount(AccountId,clientURL,AccountTobeUpdated)


}

MS CRM 2016 Web API Introduction


Introduction :

Microsoft CRM 2016 introduced a new Web API concept. This will make it easier to create applications across a wide variety of platforms, devices, and programming languages.
You can perform all operations using HTTP requests with the Web API located at 
[organization uri]/api/data/v8.0/. The Web API implements OData version 4.0, an open standard for data access.

We can perform following operations using web API

            ·        Create
·         Update
·         Delete
·         Retrieve
·         Retrieve multiple( using odata query and fetch)
·         Execute Web API functions
·         Execute Web API Actions
·         Execute Web API Query Functions

Let’s check where the web API is located. I am using online ms crm 2016


 It showed me some JSON object like below
 {
  "@odata.context":"https://bareillly.crm.dynamics.com/api/data/v8.0/$metadata","value":[
    {
      "name":"accountleadscollection","kind":"EntitySet","url":"accountleadscollection"
    },{
      "name":"accounts","kind":"EntitySet","url":"accounts"
    }




 Explanation :

  name : This is the name of the entity set.
  kind :  For the web API only Entity sets are listed.
  url :  It represents the part of the resource path to retrieve data for the entity.


How to use Web API:

We can use XMLHttpRequest object to perform all the above operation with Web API.


Example:   Create an Account using Web API:
function CreateRecord(clientURL,entityType,entityData)
{
var req = new XMLHttpRequest()

req.open("POST",encodeURI(clientURL + "/api/data/v8.0/" +entityType), true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
 if (this.readyState == 4 /* complete */) {
  req.onreadystatechange = null;
  if (this.status == 204) {
   var accountUri = this.getResponseHeader("OData-EntityId");
   console.log("Created account with URI: "+ accountUri)
  }
  else {
   var error = JSON.parse(this.response).error;
   console.log(error.message);
  }
 }
};
req.send(JSON.stringify(entityData));

}
// This function Creates an Account
function CreateAccountUsingWebAPI() {

debugger;
var entityType ="accounts"
var clientURL = Xrm.Page.context.getClientUrl();
var Account ={};
Account["name"] ="My first Account by API";
Account["accountnumber"] = "9211";
Account["fax"] ="0581-231383";

CreateRecord(clientURL,entityType,Account)


}



Thursday, 29 October 2015

Clear jQuery Table records tip

To Clear a dynamic HTML Datatable using JQuery is very easy using following approach

while creating dynamic  table rows just append some unique Class name to the row element e.g.


 var divMain = $('<div>').addClass(' DynamicActivityRow').attr('id', 'div_activity' + i);

If you want to clear the table just do this.

  $(".DynamicActivityRow").remove();


Hope it helps.

Saturday, 27 December 2014

Microsoft Dynamics CRM 4.0 to 2011/2013 Plugins Migration

Below table consists of major code change while migrating plugins from CRM 4.0 to CRM 2011/CRM2013.

Data type
Description
Microsoft Dynamics CRM 4.0 version
Microsoft Dynamics CRM  2011/2013 version
Dynamic Entity
DynamicEntity has been changed to Entity
   
    

if (context.InputParameters.Properties.Contains("Target") &&     context.InputParameters.Properties["Target"] is DynamicEntity)
if (context.InputParameters.Contains("Target") &&
    context.InputParameters["Target"] is Entity)
CrmService
ICrmService has been changed to IOrganizationService
ICrmService sdk = context.CreateCrmService(true);
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService sdk = factory.CreateOrganizationService(context.UserId);
Lookup
Lookup classes change to EntityReference
Lookup entity = (Lookup) context.InputParameters.Properties["Target"];
Microsoft.Xrm.Sdk.EntityReference entity = (EntityReference) context.InputParameters["Target"];
Moniker
Moniker classes change to EntityReference
Moniker entity = (Moniker) context.InputParameters.Properties["Target"];
Microsoft.Xrm.Sdk.EntityReference entity = (EntityReference) context.InputParameters["Target"];
GetProperties / PropertyAccess
Properties property of DynamicEntity no longer exists.
Getting and Setting values no longer use Property classes.

if (context.InputParameters.Properties.Contains("Target") &&     context.InputParameters.Properties["Target"] is DynamicEntity)
if (context.InputParameters.Contains("Target") &&
    context.InputParameters["Target"] is Entity)
BusinessEntityCollection
BusinessEntityCollection has been changed to Entity]


Picklist
Picklist in CRM 4.0 has been changed to OptionSetValue in CRM 2011
Var pick =  new Picklist(1);
Var options = new OptionSetValue(1);
Key
Key is no longer a separate thing in CRM 2011, it’s just a System.Guid
Var key = new Key(“<value>”);
Var key = new System.Guid(“<value>”);
SoapException
SoapException has been changed to FaultException in CRM 2011
Catch(SoapException ex){
}
catch (FaultException<OrganizationServiceFault> ex){
        // Handle the exception.
            }

CrmSdk
Namespace change from Microsoft.Crm.Sdk to Microsoft.Xrm.Sdk
public class ClassName : Microsoft.Crm.Sdk.IPlugin
public class ClassName : Microsoft.Xrm.Sdk.IPlugin
IPluginExecutionContext
IPluginExecutionContext change
public void Execute(IPluginExecutionContext context)
public void Execute(IServiceProvider serviceProvider)
IPluginExecutionContext
To get a reference to the IPluginExecutionContext you now need to call the GetService method of the IServiceProvider interface.
public void Execute(IPluginExecutionContext context)
Microsoft.Xrm.Sdk.IPluginExecutionContext context =(Microsoft.Xrm.Sdk.IPluginExecutionContext)
    serviceProvider.GetService(typeof(Microsoft.Xrm.Sdk.IPluginExecutionContext)
Customer/Owner
Customer/Owner changed to Lookup


CrmDateTime -> Datetime

CrmBoolean-> Boolean

CrmDecimal->Decimal

CrmNumber->Integer
Crm types change to generic types
attributeValue = ((Microsoft.Crm.Sdk.CrmBoolean)propertyCollection[attribute]).Value.ToString();
attributeValue = ((bool)propertyCollection[attribute]).Value.ToString();




Hope this helps,
Yusuf

Thursday, 18 December 2014

MS 2013 Custom Application not working under CRMAPPPOOL

Recently I faced an Issue in MS CRM2013 while migrating application form other ports to default PORT under MS CRM website (under crmapppool).

Some applications were not working at all.After some analysis I came to know that controls view state was not preserving for the application(I do not know why).

By enabling the viewstate at Page level resolved this issue.
EnableViewState="true"

Example :
<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeFile="Default.aspx.cs" Inherits="_Default"  EnableViewState="true" %>

Hope this helps,

Wednesday, 1 October 2014

Create a new log file When the Size of Current log file Crosses size limit

Logging messages is always a good practice in development.You can check the log file to know where the application is breaking.Sometimes a log file becomes huge in size and takes some time to open.

Below is C# code to create a new log file When the Size of Current log file Cross size limit.You can define your maximum size of file say 5 MB.
       

          public static void writeLog(string text)
        {
            try
            {
                long length = 0;
                string fileName = "My_Logger_1" + "_" + DateTime.Now.Year.ToString("0000") + "_" + DateTime.Now.Month.ToString("00") + "_" + DateTime.Now.Day.ToString("00") + ".log";
                string filePath = string.Empty;
                string[] logfileVersion = new string[] { };

                string date = System.DateTime.Now.Year.ToString() + "_" + System.DateTime.Now.Month.ToString() + "_" + System.DateTime.Now.Day.ToString();
                string logpath = @"D:\Logger";
                int MAX_FILE_SIZE = 5242880;//5MB

                filePath = logpath + "\\" + fileName;



                if (File.Exists(filePath))
                {
                     List<String> files = getTodaysFiles(logpath);

                    length = new System.IO.FileInfo(files[files.Count - 1]).Length;
                    logfileVersion = Path.GetFileName(files[files.Count - 1]).Split('_');
                    filePath = files[files.Count - 1];
                }


                StreamWriter LogWriter = new StreamWriter(new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Read));

                if (length > MAX_FILE_SIZE)
                {
                   
                    int nextVersion = Convert.ToInt32(logfileVersion[2]) + 1;
                    LogWriter.Close();

                    LogWriter = new System.IO.StreamWriter(new FileStream(string.Format(
                    logpath + "\\My_Logger_{0}" + "_" + DateTime.Now.Year.ToString("0000") + "_" + DateTime.Now.Month.ToString("00") + "_" + DateTime.Now.Day.ToString("00") + ".log", nextVersion), FileMode.Append, FileAccess.Write, FileShare.Read));

                }
                LogWriter.WriteLine(DateTime.Now.ToString() + "  -  "+text);
                LogWriter.Close();


            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static List<String> getTodaysFiles(String folderPath)
        {
            List<String> todaysFiles = new List<String>();
            foreach (String file in Directory.GetFiles(folderPath))
            {
                DirectoryInfo di = new DirectoryInfo(file);
                if (di.CreationTime.ToShortDateString().Equals(DateTime.Now.ToShortDateString()) && di.Name.Contains("My_Logger"))
                {
                    todaysFiles.Add(file);

                }

            }
            return todaysFiles;
        }
       
 


Friday, 19 September 2014

MS CRM 2013 Showing a Specific Process Stage

Suppose you have a Business Process Flow with multiple Stages on entity Opportunity say

1.Quality
2.Develop
3.Propose
4.Close

Now I want to create the opportunity from Stage 3(Propose).Using JavaScript you can easily achieve this.

Solution: We should get the ProcessID and StageID for the Given Business Process Flow.

Get the ProcessID and  use ProcessStage table to get the Stages  where ProcessID equals same.it will display StageID for all the stages. Get the Propose StageID.

Use JavaScript to open the new record :

var parameters = {};
parameters["formid"] = "A837E4A7-01B8-4F82-A475-BE9ABD67E667";//Specific form id
parameters["stageid"] = "1B015DCA-9790-D8D0-0425-54EECEE24900"; // Stage ID for a specific Stage say "Propose"
Xrm.Utility.openEntityForm("opportunity", null, parameters);

Result:


 


Hope it helps,
Yusuf




MS CRM 2011 and 2013 not working properly with Chrome.

One day while opening MS CRM 2011 in chrome browser I found out that it is not showing  modal dialog. Although it was working fine in IE.I thought there is some bug in application.

Some other day I was working on CRM 2013 and I noticed some functionalities are broken in Chrome.

1.Button Click events were not working for a dynamatically created HTML DIV.
2.On Form customization I faced some issues.

Later I found out that it is due to update of Chrome browser (37).They removed  number of API which results in such issues.

Below is the explanation  and workaround of this  issue.
http://xrmrocks.com/2014/09/08/chrome-37-breaks-crm-2011-functionality/

http://www.crmanswers.net/2014/09/google-chrome-registry-fix-for-dynamics.html


Hope this helps,

Yusuf





Thursday, 12 December 2013

Get the record ID from the URL

As a developer, you will find yourself extracting record ID from the URL.Most of the time we open the notepad and using our  ID extracting skills we strip out the ID from the URL.To make this task more easier just use URL Decoder/Encoder


1. Copy and paste your URL in the textbox
2. Press Decode button two times.
3.Your URL is decoded you can easily copy the ID.



Hope this helps.

Wednesday, 14 August 2013

Showing only selected Tab on the MS CRM 2011 Form

When you open any form it loads all the tabs on the form.Suppose you want to display the selected tab on the form at a time.Here is a JavaScript function to hide the other tabs.This function can be called on the Form OnLoad and TabStateChange events.

1.JavaScript Function:

function ToggleTabDisplayState(name) {
 
    var currentTab = Xrm.Page.ui.tabs.get(name);
    if (currentTab != null && currentTab.getDisplayState() == "expanded") {
        var currentTabId = currentTab._control.get_id();
        var tabs = Xrm.Page.ui.tabs.get();
        for (var i in tabs) {
            var tab = tabs[i];
            var tabId = tab._control.get_id();
            if (tabId != currentTabId) {
                if (tab.getDisplayState() == "expanded") {
                    tab.setDisplayState("collapsed");
                }
                document.getElementById(tabId).style.display = "none";
            }
        }
    }
}
2.Before Calling the Function :
Form shows all the tabs before calling the above function Form OnLoad event.
 
 
 
 3.Calling the Function :
 
3.1 Call on Form OnLoad event :
 
Suppose on Form OnLoad event I want to show only "General" tab and hide other tabs then call the above function as below.
 
function Form_OnLoad() {
    ToggleTabDisplayState("general"); //"general" is the name of the tab
}
 
3.2 Call on TabStateChange event:
 
Call the same function on the TabStateChange event 
 
Go to Form Properties =>Select Control as tab name=>Add Handler =>Select Library=>add function as ToggleTabDisplayState =>Provide name of the tab in Comma separated parameters list for example 
"contacts" => Save and publish


4.After Calling the Function :
Form shows only selected tab after calling the above function Form OnLoad event.
 
 










Hope it helps,
Regards,
Yusuf