Using ILMerge for Plugin in CRM

If we make use of external assembly in our Plugin (sandboxed) we will get the exception of FileNotFound.

So here we can make use of ILMerge which basically merges the assembly referenced and the plugin into a single assembly.

Install the following NuGet Package.

This adds the following files in our Plugin project.

We need to set Copy Local as true for all our referenced assembly that we want to merge with our plugin.

We need to set Copy Local as false for all other assemblies that we do not want to be merged with plugin.

Just build the project and we are done.

The assembly inside Reflector: –

Hope it helps.

Caching Issue in The Portal Connector (TPC)

We had products configured from CRM to E Commerce settings in TPC. However, what we observed that any update that we are making to prices in the product is not reflecting to the end user using the Portal.

We cleared the cache, deleted the product form TPC did full synchronization etc. but still we were getting the same price for the products in the Product List.

In Product List

The price for the product (the same was the value in CRM)

However, for the end user in the portal the value was showing up the old value.

Eventually we ended up cloning up i.e. creating a new Product with exact same details and doing full synchronization inside TPC.

This worked.

Hope it helps..

Missing Price for Products in The Portal Connector – E Commerce Settings – Dynamics CRM.

Recently we configured products from CRM to e-commerce setting of The Portal Connector and found that the price for the product was missing.

The way to fix this issue is to Open the product form in CRM and add the list price field on the product form and specify the value there.

Once value is specified, go to administration – portal connector configuration and click on Resynchronize to update the product record in the portal.

Once synchronization is done, we can see the values updated in the portal.

Hope it helps..

Configuring CRM Form inside The Portal Connector for Dynamics CRM / Dynamics 365

The Portal Connector makes it easy to quickly setup a portal that interacts with CRM.

Here let us look at a simple example of setting up Lead form in Insert Mode, which creates lead record in CRM.

Open the Dashboard

Go to CRM Entities and click on Create a CRM Entity.

Here we are creating Lead entity.

Once our lead is setup, we’d create the form.

Go to Contents – Forms.

Click on Create a form.

Inside form, first go to Layout and select TPC Form Layout.

Then go to Content tab, and add Form Configuration

Click on Edit inside Form Configuration and specify the Lead entity we just created.

Drag and add two text fields, one we will configure against first name and other with last name.

Do the same for Last Name text box and publish the form.

Next we need to create a Page wherein we’d display this form. Go to Pages and click on Create a page.

We have created a page named Lead.

Drag TPC Form Manager in the page content.

Configure it and specify our newly created My Lead form.

Select Insert Only check box.

Publish the page and test it. Specify the values and click on Submit.

We’d get the following message.

The lead record created in CRM.

Hope it helps..

Fixed – Workflow must be in Published State error while converting Case to Work Order in CRM

Recently, while trying to convert a case to work order we got the below error.

The immediate thought was to check all the workflow associated to work order and case and see if they all are published, which in fact they were.

Then as suggested here

http://ms-crm-2011-beta.blogspot.ae/2016/11/workflow-must-be-in-published-state.html

we deactivated and activated one of our SLA written against the Work Order entity and it fixed the issue.

Hope it helps..

Sample code to upload file to Azure Blob Storage from CRM Online Plugin

Sharing a sample code which we can use to upload files to Azure Blog Storage from within a CRM Online Plugin. Here we’d be making use of the REST API to simplify things (instead of using Windows Azure Storage library) in our Plugin.

First, we will be creating a storage account of type blob storage and a container inside it.

Log in to Azure Portal

https://portal.azure.com

Click on Add to add a new storage account.



Create a new container in it to store the blob files



In Azure Portal – Storage Account, go to Access Keys and copy the key


And also note down the storage account name and container name which will be used to construct the URL.


We can also go to container, select its properties and copy the url.


Here we have written the plugin on Create of Annotation, which then retrieves the attachment and uploads its content to the container.

Let us first see it in action.

We have created a new note and attached a text file to it.


Going back to our portal, we can see the file in our container.


The sample code for the plugin.

using Microsoft.Xrm.Sdk;
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace MyTestPlugin
{

public class UploadFile : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
try
{
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

// The InputParameters collection contains all the data passed in the message request.
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
{
// Obtain the target entity from the input parameters.
Entity noteEntity = (Entity)context.InputParameters["Target"];
byte[] doumentBody = Convert.FromBase64String(noteEntity.Attributes["documentbody"].ToString());
string content = Encoding.UTF8.GetString(doumentBody);
string fileName = noteEntity.Attributes["filename"].ToString();

// Upload the attached text file to Azure Blog Container
UploadFileToAzureBlobStorage(content, fileName);

}
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException(ex.Message);
}
}

void UploadFileToAzureBlobStorage(string content, string fileName)
{

string storageKey = "storagekey";
string storageAccount = "storageaccountname";
string containerName = "strogaecontaninername";
string blobName = fileName;

string method = "PUT";
string sampleContent = content;
int contentLength = Encoding.UTF8.GetByteCount(sampleContent);

string requestUri = $"https://{storageAccount}.blob.core.windows.net/{containerName}/{blobName}";

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);

string now = DateTime.UtcNow.ToString("R");

request.Method = method;
request.ContentType = "text/plain; charset=UTF-8";
request.ContentLength = contentLength;

request.Headers.Add("x-ms-version", "2015-12-11");
request.Headers.Add("x-ms-date", now);
request.Headers.Add("x-ms-blob-type", "BlockBlob");
request.Headers.Add("Authorization", AuthorizationHeader(method, now, request, storageAccount, storageKey, containerName, blobName));

using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(Encoding.UTF8.GetBytes(sampleContent), 0, contentLength);
}

using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse())
{
if(resp.StatusCode == HttpStatusCode.OK)
{
// successfully uploaded
}
}

}

public string AuthorizationHeader(string method, string now, HttpWebRequest request, string storageAccount, string storageKey, string containerName, string blobName)
{
string headerResource = $"x-ms-blob-type:BlockBlob\nx-ms-date:{now}\nx-ms-version:2015-12-11";
string urlResource = $"/{storageAccount}/{containerName}/{blobName}";
string stringToSign = $"{method}\n\n\n{request.ContentLength}\n\n{request.ContentType}\n\n\n\n\n\n\n{headerResource}\n{urlResource}";

HMACSHA256 hmac = new HMACSHA256(Convert.FromBase64String(storageKey));
string signature = Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign)));

String AuthorizationHeader = String.Format("{0} {1}:{2}", "SharedKey", storageAccount, signature);
return AuthorizationHeader;
}
}

}

Hope it helps.