Showing posts with label Dynamics. Show all posts
Showing posts with label Dynamics. Show all posts

Friday, 21 April 2017

How to read configuration data in plugins using secure configurations?


Recently, we deployed some custom SharePoint integration with Dynamics CRM which required some custom coding. As usual, we wanted to connect to different Dynamics CRM environments (DEV, TEST, UAT, PROD, etc.). Every time we deployed, we didn’t want to change the code so that it can connect to the correct SharePoint site.

To achieve this there are few options available and we used the Secure Configuration feature available with Plugin Registration tool. There you provide all the configurations like site URLs, usernames, passwords, etc., in XML format and you can access them within the constructor of your plugin.

Your plugin registration will look like this; inside secure configurations box you enter your configurations in xml format.
















Your configurations XML would look like this:

<Settings>
  <setting name="siteURL">
    <value>https://xxxx.sharepoint.com/sites/CRM-DEV/Cases/</value>
  </setting>
  <setting name="DocumentLibName">
    <value>CaseDocumentLibrary</value>
  </setting>
  <setting name="SPOUserName">
    <value>SPCRMIntegrationUser@xxxxx.com.au</value>
  </setting>
  <setting name="SPOpassword">
    <value>xxxxx</value>
  </setting>
  <setting name="Case_DocLibPath">
    <value>/sites/CRM-DEV/Cases/CaseDocumentLibrary</value>
  </setting>
  <setting name="Case_Type_Hidden_StaticName">
    <value>g5dc149027cf444eae73dfec7bd07885</value>
  </setting>
  <setting name="ContentTypeId">
    <value>0x012000E8517D690891E149A88FC509298C39B300BA883DF9E383BA47AD69DC71A7712B76</value>
  </setting>
</Settings>

Here in the constructor of the plugin, you can read the settings you set in the Secure Configuration XML.

public OnUpdateOfCase(string unsecureConfig, string secureConfig)
{
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(secureConfig);
            siteURL = SecureConfigHelper.GetConfigDataString(doc, "siteURL");
            DocumentLibName = SecureConfigHelper.GetConfigDataString(doc, "DocumentLibName");
            SPOUserName = SecureConfigHelper.GetConfigDataString(doc, "SPOUserName");
            SPOpassword = SecureConfigHelper.GetConfigDataString(doc, "SPOpassword");
            Case_DocLibPath = SecureConfigHelper.GetConfigDataString(doc, "Case_DocLibPath");
            Case_Type_Hidden_StaticName = SecureConfigHelper.GetConfigDataString(doc, "Case_Type_Hidden_StaticName");
            ContentTypeId = SecureConfigHelper.GetConfigDataString(doc, "ContentTypeId");

}

Tuesday, 18 April 2017

How to read configuration data from an xml web resource via JavaScript?

There are situations where you need to keep some environment specific configuration data (e.g. URLs) in a single location without repeating them in all scripts so that all your form scripts can access them.

This way you need to change those variables in only one location when you go from one environment to the other (i.e. Dev to Test and UAT etc.)

Let’s say you have created an XML web resource named new_ApiConfiguration.xml.
And assume your web resource looks like this:

<SacConsultingApi>
<CreateApiUrl>https://webapi.sacconsulting.com.au/crmdev/api/record?id=</CreateApiUrl>
<UpdateApiUrl>https://webapi.sacconsulting.com.au/crmdev/api/update?recId=</UpdateApiUrl>
<ExpireApiUrl>https://webapi.sacconsulting.com.au/crmdev/api/expire?recId=</ExpireApiUrl>
</SacConsultingApi>

And you can access these configurations inside you custom form scripts by calling the following function.

Declare the variables on top and call the function.

var CreateApiUrl;
var UpdateApiUrl;
var ExpireApiUrl;

function GetWebApiConfigurations() {   
    var serverUrl = Xrm.Page.context.getClientUrl();
    var xmlConfigPath = serverUrl + "/WebResources/new_ApiConfiguration.xml";
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open("GET", xmlConfigPath, false);
    xmlHttp.send();
    var doc = xmlHttp.responseXML;
    CreateApiUrl = doc.getElementsByTagName("CreateApiUrl")[0].textContent;
    UpdateApiUrl = doc.getElementsByTagName("UpdateApiUrl")[0].textContent;
    ExpireApiUrl = doc.getElementsByTagName("ExpireApiUrl")[0].textContent;
}

Remember to change the name of the web resource to your web resource name.


This way when you deploy solutions from one environment to the other you don’t need to go and change your configurations in hundred places.

See this post to know how to achieve this via C# code (Plug-ins of custom workflow activity)

Monday, 20 March 2017

How to debug a CRM Online Plugin?


When you develop plugins for Dynamics CRM unless it is a very simple scenario 9 out of 10 situations you will require to debug your plugin. One way of fulfilling this requirement is using the tracing which is bit easier. But sometimes this is not sufficient. So you have no other choice but debug the plugin!

With Dynamics CRM online debugging a plugin is not very straight forward. With On-Premise environments you can run the remote debugger on the CRM server and attach to the process in you visual studio and proceed. But in the cloud version with the limited access this is not possible. So here is how you do it:

Start Plugin Registration Tool in the SDK and connect to your CRM organisation.

If this is the first time someone is going to debug a plugin in this organisation you will see the button “Install Profiler” in the menu bar. (Otherwise profiler will be installed already) Click on it and it will start installing profiler. 





Then register you plugin and the steps. Select the step which you want to debug and click "Start Profiling".


































Here you select the option “Exception” and click Ok.


Now in CRM perform the operation where your plugin is supposed to trigger. (In this example it triggers when multiple accounts are retrieved. So I open the Accounts view).

You will get a business process error. Click Download Log File and save the log file into your local drive.














Then open your plugin code in visual studio; set the break points; click Attach to process under the debug menu. Select the PluginRegistration.exe from the available processes and click attach.


Then in the plugin registration tool click “Debug” from the menu.
For the Profile browse to the downloaded error log file and in the previous step and select it.
Select your plugin dll for the Assembly location and then the plugin.

Then click Start Execution.




Debugger will hit your breakpoints you had set up in Visual Studio and you can continue debugging your code with pressing F10.

Once you are done with debugging make sure you go back to the plugin registration tool; select the step in your plugin and click “Stop Profiling”; otherwise you will always get business process error when you perform your operation!


Happy debugging J 



How to call a plugin from a JavaScript or a ribbon button?


Sometimes there are situations where you need to call a plugin from a JavaScript or click of a ribbon button. With the help of actions and latest web API this is easily achievable.

Step 1

Under Processes create a new Process with Category selected as Action; give a name and select the entity. In this example I have selected Account as the entity. It’s just a blank action with no arguments or steps.



Step 2

Create your plugin and register your plugin on that action you created. Make sure you have activated your action and published. Otherwise you will not see the newly created action in the plugin registration tool. If you still don’t see your action name in messages in plugin registration tool close the plugin registration tool and open again. It should resolve this.



Step 3

In your JavaScript on account form use following code; replace the action name with the unique name of your action.
In this example replace new_AccountAction with your unique name.
function CallAction() {   
    var currentRecordIdString = Xrm.Page.data.entity.getId();
    var currentRecordId = currentRecordIdString.replace("{", '').replace("}", '');
    var query = "accounts(" + currentRecordId + ")/Microsoft.Dynamics.CRM.new_AccountAction";
    var req = new XMLHttpRequest();
    var url = Xrm.Page.context.getClientUrl() + "/api/data/v8.0/" + query;
    req.open("POST", Xrm.Page.context.getClientUrl() + "/api/data/v8.0/" + query, false);
    req.setRequestHeader("OData-MaxVersion", "4.0");
    req.setRequestHeader("OData-Version", "4.0");
    req.setRequestHeader("Accept", "application/json");
    req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
    req.onreadystatechange = function () {
        if (this.readyState == 4) {
            req.onreadystatechange = null;
            if (this.status == 204) {
                //Xrm.Utility.alertDialog("Action Called");
            }
            else {
                var error = JSON.parse(this.response).error;
                Xrm.Utility.alertDialog(error.message);
            }
        }
    };
    req.send();
}


That’s all. Then you can call this function from your ribbon button if you need to.



Connect to CRM via a console application


Connect to CRM via a console application.

If you are writing some complicated business logic inside your custom workflow activity or a plugin there is a high chance of your code throwing exception once you have registered them and started testing.

What I do is I create a simple Visual Studio C# console application and connect to CRM. Then debug the business logic in the console application first and make sure everything is working well before I insert the code into the plugin or workflow activity skeleton. This saves lot of time as debugging plugins and custom workflow activities is not very straight forward.

Creating a Console application is very easy and once created you can use it for multiple projects as you need to change only few variables.

Step 1:
Open visual studio and create a new project of type Console Application as below:

 


Step 2:
Under solution explorer right click on the project created and click properties. Then under the Application tab change the Target Framework to .Net Framework 4.5.2
If you don’t have this version of .net installed in your computer download it from Microsoft site and install.


















Step 3:
Refer the following assemblies. CRM dlls can be found under the bin folder in CRM SDK. You can download the SDK from Microsoft site.

























Update your Program.cs class like below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using System.ServiceModel.Description;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Sdk.Query;

namespace CRM2016ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        { 
            #region credentials
            string SoapOrgServiceUri = "https://CRMUrl/OrganizationName/XRMServices/2011/Organization.svc";
            ClientCredentials credentials = new ClientCredentials();
            credentials.UserName.UserName = "username";
            credentials.UserName.Password = "password";
            #endregion                     

            Uri serviceUri = new Uri(SoapOrgServiceUri);
            OrganizationServiceProxy proxy = new OrganizationServiceProxy(serviceUri, null, credentials, null);
            proxy.EnableProxyTypes();
            IOrganizationService orgService = (IOrganizationService)proxy;
            XrmServiceContext serviceContext = new XrmServiceContext(orgService);

        }
    }
}

Update username, password and crm url.




Now you have OrganizationService instance and if you have built your early bound classes then you have access to the ServiceContext too. In this example they are orgService and serviceContext respectively.

Now you can build your CRM queries with hard coded GUIDs to test your business logic. Once all tested and good to go move them to your plugins. J

How to tackle Concurrent Business Process flows

Dynamics 365 has introduced the new feature of Concurrent Business Process Flows. Here is a couple of good articles on that: http://dev...