SharePoint PDF generator utility from A utility to create a single merged pdf out of uploaded documents in Sharepoint and email it to your customer. Check it out!

I am very excited to announce the new Utility from XrmForYou stable – “SharePoint Document Merger”. Let’ directly jump to the Utility functionality and other details

So what does this Utility address?

You have an opportunity in CRM and you are using the OOB CRM-SharePoint integration to store documents in SharePoint corresponding to the opportunity. And now you need to combine all these documents into a single PDF and send it to your customer or team or anybody, over an email as an attachment

Well if this has bothered you and you are thinking on how to do this, you no longer need to worry. The Utility just does this and it has some other features as well which I am going to explain below. And all these with few configuration steps.

For trial and pricing, please write to us at

How does this work?

The tool comes in the form of managed solution. Once you get hold of the solution, you need to install the managed solution.

Once the solution is installed, open up the solution and navigate to its configuration page. The first section is to enter the license key which would be provided to you by XrmForYou.


You can do your entire Merge configuration by expand the section “Merge Configuration settings”


As you can see from the screenshot above you need to enter some details for the tool to work. The tool does not use a username and password. Instead it leverage OAuth2.0 to authenticate with SharePoint. All you need to do is register this tool as an APP in your Azure Active directory as Web  App/ Web Api.

Once the APP is registered you would need to enter the client_id and client_secret information of the APP here. The client_secret is stored inside CRM and is protected by encryption

Azure Application Url is the URL of the Sharepoint.

MergedFileName is the name of the Output file.

Once you save your merge configuration settings, that’s all you need to do.

Now let’s see it in action.

I have an account below where I have uploaded 4 files.

  • One excel
  • One word
  • One PPT
  • One pdf


Since Merge Configuration has been enabled, a new ribbon item would start appearing in all the entities which has been enabled for Document Management. So in Account entity form I could see the Merge Button.  This would be show automatically and no configuration is required from the customer side.


Once you click on Merge document you would get the below message:


Within a moment you should see the the merged document containing all the contents of the merged file.


Wonderful isn’t it? The PPT, excel, word and the PDF file have merged into a single file. The file will bear the same name as you provided in the configuration. And yes before you ask, it works on the Unified interface as well.

And finally the output file. First page – the word document


Second Page – the excel


Third Page – the powerpoint


Wait the show is not over. We are releasing the utility with two versions. One with the option to generate just the merged file and the other with the option to send the merged file as an attachment over email. So once the merge completes, you can hook in and put in your code to send an email automatically or do anything you like with the generated document.

The content of the document, the record context everything would be available and you can play with it!

What’s not there in this release?

We don’t want our customers to have sudden surprises once they are into using it and duly I present some of the stuffs which we are already working on for the next release but is not there in the current version!

  • Documents are merged in descending order of modified on date.
  • Currently only the specified formats are supported – csv, doc, docx, odp, ods, odt, pot, potm, potx, pps, ppsx, ppsxm, ppt, pptm, pptx, rtf, xls, xlsx.. Going to change very soon with the next release. Stayed tuned for the next update in couple of months time.
  • Support for OOB sharepoint document location only. Next release in the coming 2-3 months support multiple document location merge for each record.
  • Available only for online customers.
  • Output file is only pdf format.

So what’s keeping you waiting. Just drop us a note at to grab your free trial.

Documentation and video to appear in our website by next week. Stay tuned!


Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit or reach out to us at

Our product offerings:

Role based views for Dynamics 365 (

CRM-Sharepoint Attachment uploader and metadata manager (

Record Cloner for Dynamics 365 (

Multiselect picklist for Dynamics 365 (




Xrm.Page is deprecated. How do I use formContext in inline HTML WebResources in Dynamics V9.0 to access form data?

Xrm.Page is deprecated. We all know and we have already started revamping our form scripts and replacing Xrm.Page with formContext and gridContext as suggested by Microsoft.

But the ordeal does not end here. And recently I was faced with another challenge. Customers had HTML webresources embedded in their form where they are playing with the form controls using parent.Xrm.Page.getAttribute and parent.Xrm.Page.getControl.

So we thought of removing Xrm.Page from within inline HTML webresources as well. But wait, there is a problem here. How do we get formContext here.

Searched the heck out in Microsoft Docs but could not find a way. Came across this documentation in Microsoft Docs which I think everybody know anyways. It still asks to use parent.Xrm.Page. But our customer wanted to remove all traces of Xrm.Page at one go.


Then how to proceed. First things first. Is there a way to access the formContext inside HTML webresources?

I could not find any. But I believe you can solve so many things by a good design. And I implemented one of it here to solve the problem. My customer liked it and I hope you would like it too.

So I have this custom entity inside which contains a HTML webresource embedded within it. The first thing I did is to store the formContext in a global variable. So I registered a library on form onload of the test entity. Below is the code for the same. I am using namespaces here for better coding convention

// JavaScript source code
if (typeof (ibtrng) == "undefined") {
    ibtrng = { __namespace: true };

ibtrng.formevents = {
    fContext: null,

    onload: function (e) {
         var fContext = e.getFormContext();

Xrm.getParentAttribute = function (attrName) {
            return fContext.getAttribute(attrName);

        Xrm.getParentControl = function (attrName) {
            return fContext.getControl(attrName);



The code highlighted in yellow just sets the formContext in a global variable.

Check for the code highlighted in green! What am I doing here? Well from the screenshot of Microsoft Docs, it is evident that within the embedded HTML page you can get hold of the Xrm context using parent.Xrm.

So in the parent scope, during from onload, I registered two custom functions in Xrm namespace – getParentAttribute and getParentControl which is internally using the formContext only.

You can define as many custom functions as you want in the parent scope of Xrm namespace.

And now when the HTML page loads, I can get access to the form data. For the sake of this demo I just populate the textbox field on my HTML with the data of the form. Below is the code on load of my HTML Page

function onHtmlPageLoad() {

            var attrName = parent.Xrm.getParentAttribute("ibtrng_name");
            var attrValue = attrName.getValue();

            document.getElementById("txtName").value = attrValue;



And voila! I can access data without even any trace of Xrm.Page.

Now the bigger challenge – Does it work on UCI? No solution is complete these days if it does not work on UCI.

Works like a charm in UCI too!



Hope you liked it!

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit or reach out to us at

Our product offerings:

Role based views for Dynamics 365 (

CRM-Sharepoint Attachment uploader and metadata manager (

Record Cloner for Dynamics 365 (

Multiselect picklist for Dynamics 365 (

{Solved} Object reference error while connecting to Dynamics CRM Plugin Registration tool

To be honest, I have been getting this error for quite some time now, every now ever since I started working with Dynamics 365 SDK. And believe me it can give you a nightmare.

Plugin registration tool is one such utility which we use everyday without much notice but as soon as it stops working, life of a CRM consultant becomes a living hell. And I find lot of consultants facing this recently.

No worries you are on the right page towards solving. All you need to do is go ahead and delete the contents of the folder – C:\Users\<username>\AppData\Roaming\Microsoft\PluginRegistration and you should be good to go.

Hope this helps!

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit or reach out to us at

Our product offerings:

Role based views for Dynamics 365 (

CRM-Sharepoint Attachment uploader and metadata manager (

Record Cloner for Dynamics 365 (

Multiselect picklist for Dynamics 365 (

Execute WorkFlow using Xrm.WebApi in Dynamics CRM Version 9.0

A very interesting read from my colleague

Chandana's CRM Blog

It has been a long time that I have contributed to the blog posts :(. Well I have started again to tell some interesting things. Recently I started working on Xrm.WebApi CRUD operations wherein I have a requirement to send email when invoking a custom ribbon button.

So to implement the same I have created an on demand workflow on account entity as shown here


Now I tried to invoke my workflow from the custom ribbon button using

Xrm.WebApi.execute(request).then(successCallback, errorCallback);

Prepare request object similar to this to execute your workflow as shown below

var request = {};

//pass workflow Id and entityType as worflow
request.entity = { id: “cd78cbcc-080a-4a48-8b9d-46555b655c02”, entityType: “workflow” };

//pass record Id of type Guid ,here my workflow is on “Account” entity

request.EntityId = { guid: “A16B3F4B-1BE7-E611-8101-E0071B6AF231” };
request.getMetadata = function () {
return {
boundParameter: “entity”, /
operationType: 0,

//operation name is always “Execute Workflow” independent of…

View original post 115 more words

{KNOWHOW} How to invoke Azure relay Hybrid connections from Dynamics 365 Plugin programmatically without using Service Endpoint

Recently I have been working on Azure integration with CRM a lot and frequently I see azure relay hybrid connection integration with Dynamics 365. And in most of the case, it is through registering the Service Endpoint in Plugin registration tool.

While the above works really great for most of the scenarios, sometimes it becomes necessary for us to post something else apart from CRM context information. Sometimes it’s not even important for us to have the whole context information pass through but some custom values to the listener based on some business logic.

Since I have been queried about that a lot, I decided to pen this one down for the benefit of my readers.

I am  not going to show here how to set up a relay with Hybrid connection enabled. There are awesome articles which explains these. Just as a pre-requisite I am assuming

  • Azure relay with Hybrid connection is set-up
  • The Hybrid connection is set for authorization
  • You have the Send and Listen shared access policies set up for the Hybrid connection

Screenshots of my Hybrid connection with sender and listener profiles with CRM acting as the sender.


image                             image

Now coming to code.

The first thing is I set-up a plugin which will fire on create of account. To call the Relay Hybrid connection from my plugin, I use the awesome Microsoft.Azure.Relays Nuget package which I think is simple awesome.


Below is the code I write to invoke my Hybrid connection from my plugins.

public void Execute(IServiceProvider serviceProvider)
             var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));


        private async Task SendToRelay(IPluginExecutionContext context)
            var hybridConnectionName = "<hybrid connection name>";
             var relayUrl = "";’>https://<your relay name>"; // put your relay URL without the hybrid connection name
            var connectionKey = "<primary key for the sender profile>";// put your primary key for the sender profile
            var keyName = "Sender";

            var token = TokenProvider.CreateSharedAccessSignatureTokenProvider(keyName, connectionKey);
            var uri = new Uri($"{relayUrl}/{hybridConnectionName}");

            var relayToken = await token.GetTokenAsync(uri.AbsoluteUri, TimeSpan.FromMinutes(30));

            HttpClient client = new HttpClient();

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
            request.Content = new StringContent($"{context.PrimaryEntityName}", Encoding.UTF8, "application/json");

            request.Headers.Add("ServiceBusAuthorization", relayToken.TokenString);
            request.Headers.Add("CrmMessageName", context.MessageName);


You would need to replace the one highlighted in yellow with appropriate values from your azure environment. As you can see from the above code I can pass my own data in the body of the request as well as pass some custom data in the headers collection. And as I using the Microsoft.Azure.Relay assemblies I need to do ILMERGE to merge this assembly with the plugin dll. For this I again use the wonderful MsBuild.IlMerge task available in Nuget


I am not awaiting for the result to come back since my relay can perform some lengthy operations. However in case I want to get the return values from my relay listener, I can just change the last few lines like this.

var responseMessage = await client.SendAsync(request);
            var content = await responseMessage.Content.ReadAsStringAsync();

Now coming to the listener, I just create a console application and keep it running. Below is the sample code for a listener. The code is courtesy Microsoft Docs and is also using Microsoft.Azure.Relays Nuget package.

static async Task RelayListener()
            // create a connection string with the listener profile
            HybridConnectionListener listener = new HybridConnectionListener("<put the connecting string of Hybrid listener>");

            listener.Connecting += (o, e) => { Console.WriteLine("Listener is connecting to Azure…"); };
            listener.Offline += (o, e) => { Console.WriteLine("Listener is about to go offline…"); };
            listener.Online += (o, e) => { Console.WriteLine("Listener is online…"); };

            listener.RequestHandler = (context) =>
                 StreamReader streamReader = new StreamReader(context.Request.InputStream);
                // reading the body
                 var requestContent = streamReader.ReadToEnd();

                // reading the headers
                foreach(var header in context.Request.Headers)
                    //Console.WriteLine($"Header Key: {header}, Header Value:{context.Request.Headers[0]}")

            await listener.OpenAsync();

            await Console.In.ReadLineAsync();

            await listener.CloseAsync();

And finally with my console running, if I create an account, the relay listener immediately catches this.


Wonderful isn’t it?

Hope this helps

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit or reach out to us at

Our product offerings:

Role based views for Dynamics 365 (

CRM-Sharepoint Attachment uploader and metadata manager (

Record Cloner for Dynamics 365 (

Multiselect picklist for Dynamics 365 (

(Quick Tip) Solution History in Dynamics 365

Another wonderful and utility post from my friend and fellow MVP Deepesh Somani


One of the pain points in Dynamics 365 Solution management was that developers or customizers would not have a trail of Solution history.

Well not any more. Dynamics 365 now provides solution history.

Lets first do some things and see the log which will remain

  1. Created a custom solution named Test and then deleted it:

Navigate to Settings-> Under Customization Select Solution History:

The log is being maintained as follows:

  1. Now lets try to export a solution named Test. The log is maintained as follows:

3. Lastly trying to import a solution named Test. The log is maintained here also:

Hope it helps and happy 365ing!

Any problem in CRM – end user,Microsoft  partner or an individual?

Problem Area – Technical, Functional, Training, Development or consulting?

I am here to help, get in touch here: Click here




Google Play Store:

View original post

How do I move my word template for custom entity across environments in Dynamics 365? How can I make the changes manually? – A deep dive into inner workings

It was just another day at my office and my client’s developer just walked up to me and asked – “How do I move my document templates to one environment to another?”. He seems to have manually uploaded in the target environment but that is not showing up the data in the target environment environment when then word template is downloaded.

If you have worked on word templates, you know that this will not work as the custom entity object type codes are different between the source and the target environment. If you are new to word templates, please remember that the entity in your word templates are reference by their object type codes instead of their logical name. So even though you migrated the solution, the object type code of the custom entity will most probably be different and hence this would not work out in the target environment.

So I asked him to use the wonderful XRM toolbox which has the ability to do the same.


Worked like a charm like all other XRM toolbox plugins.

But the ordeal does not end here. Every now and  then I get a question – “Can you explain what’s happening underneath? Can I do it without using a tool? Can you tell me where the changes are being made”.

Honestly I am not in favour of not using an utility when it is available. But if you want to dig deep, continue reading. Or may be you are getting an error with the tool and this might just save your day.

We all know the word and the excel files are essentially zip files. I just save my word template with .zip extension.


Now since its a .zip file, I can unzip the same.


In the folder I search for the object type code which in my case is 10426


I just open the three files in a XML editor of my choice and then replace my the object type code 10426 with the new objectypecode of the custom entity in the target environment – 10341

I save the files. And then i select all the contents and then re-zip it.


And then change the .zip extension to .docx extension.

And finally when you upload the template in the target environment, it just works fine.

I am not sure when you would do this manually but if you want to really do it and go under the hood, here it is for you.

And sometimes when you get an error, this way may just help you out.

Debajit Dutta

(Dynamics MVP)

For consultation/ corporate training visit or reach out to us at