RSS

How to append Email Template to Email Entity Form on Load through JavaScript

Introduction

Generally, we add a Signature at the bottom of Email before we send. One of my projects needed the same requirement. We need to insert one Signature Email Template into the description body of Email Form on form load. I have found a solution and now I am going to describe it.

Steps

  1. Create a web resource of Script type and add to the Email Form library
  2. Add the “AddSignatureToEmail” function to the form “onload” event
  3. Create a Email Template containing Signature body and copy the Template Id
  4. Replace that Template Id in the following code for variable “emailTemplateToLoad

Code

Following is the Code snippet.

function AddSignatureToEmail() {
	// Check the form type should be 'create' type
	if (Xrm.Page.ui.getFormType() != 1) { return; }

	// Pre-fill a template signature
	var drawSignature = false;
	var emailTemplateToLoad = "b348fc8b-1e6e-e311-9d64-6c3be5a86df8 "; //created email template Id

	// Check if description is blank or similar
	var theDescription = Xrm.Page.getAttribute("description").getValue();
	if (theDescription == null) {
		drawSignature = true;
	} else if (theDescription == undefined) {
		drawSignature = true;
	} else if (stripHTML(theDescription) == "") {
		drawSignature = true;
	} else if (stripHTML(theDescription).length < 10) {
		drawSignature = true;
	}

	if (drawSignature) {
		// Get Regarding object details
		var regardingobjectid = Xrm.Page.getAttribute("regardingobjectid");
		if (regardingobjectid==undefined) { return; }
		var RegardingItems = Xrm.Page.getAttribute("regardingobjectid").getValue();

		// The signature will not append if regarding field remains blank.
		if (RegardingItems!=null) {
			var regardingObjectId = RegardingItems[0].id;
			var regardingObjectType = RegardingItems[0].type;

			if (regardingObjectId == null || regardingObjectId == "") { return; }
			if (regardingObjectType == null || regardingObjectType == "") { return; }

			// Retrieving email template details

			var command = new RemoteCommand("EmailTemplateService", "GetInstantiatedEmailTemplate");
			command.SetParameter("templateId", emailTemplateToLoad);
			command.SetParameter("objectId", regardingObjectId);
			command.SetParameter("objectTypeCode", regardingObjectType);
			var result = command.Execute();

			if (result.Success) {
				var o = new Object();
				o.EmailBody = "";
				o.EmailSubject = "";
				if (typeof (result.ReturnValue) == "string") {
					// Create a Xml Document of the return value to retrieve actual data
					oXml = CreateXmlDocument(result.ReturnValue);
					o.EmailBody = oXml.lastChild.lastElementChild.textContent;

					Xrm.Page.getAttribute("description").setValue(o.EmailBody);
				}
			}
		}	
	}
}

function stripHTML(signature) {
	var tmp = document.createElement("DIV");
	tmp.innerHTML = signature;
	return tmp.textContent || tmp.innerText;
}

function CreateXmlDocument(signatureXmlStr) {
    // Function to create Xml formate of return email template data
	var parseXml;

	if (window.DOMParser) {
		parseXml = function (xmlStr) {
			return (new window.DOMParser()).parseFromString(xmlStr, "text/xml");
		};
	}
	else if (typeof window.ActiveXObject != "undefined" && new window.ActiveXObject("Microsoft.XMLDOM")) {
		parseXml = function (xmlStr) {	
			var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
			xmlDoc.async = "false";
			xmlDoc.loadXML(xmlStr);
			
			return xmlDoc;
		};
	} 
	else {
		parseXml = function () { return null; }
	}

	var xml = parseXml(signatureXmlStr);
	if (xml) {
		return xml;
	}
}

var a = window.setTimeout(AddSignatureToEmail, 1500);

By Sukanta Mangal
Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 
3 Comments

Posted by on January 13, 2014 in WebResources

 

Tags: , , , , , , , , , , , , , , , , , ,

How to Create Records through Dialog Process and do fields mapping with the Parent Record

Introduction

As we know, in MS CRM, we always try to find solution of any requirement through Out Of The Box. It doesn’t mean that, we can’t do it by writing code. But Out of The Box gives better performance. So, let’s discuss how to create records through Dialog Process and do fields mapping with the Parent Record.

Background

According to one of my project requirement, we had to create new record(s) on custom button click, from one existing record and that will be done only through Dialog Process. Before record create, in background, some of data from parent record should automatically get populated to new record’s fields (i.e. Fields mapping). I have found a solution by doing some research.

Steps

Let’s explore step by step.

Here I will open Dialog Process from existing Contact record and create Contact and Opportunity records through dialog sequentially.

Step 1: Create a Process of Dialog Category

Create Dialog Process

Step 2: Add a step of “Page” and under which add “Prompt and Response” step, then click “Set properties” to to create control for record inside dialog

See the following picture.
Add Step Page

Step 3: Mapping Dialog Fields with Contact Fields

After creating all fields required, add a step of “Create record” from Add Steps DropDown. Then choose the record type and click “Set Properties“. Here we will be able to do fields mapping using both Parent data and Dialog Fields data.
The Red colored box on the right side is showing all fields contains in Dialog. Map those fields with corresponding fields in Contact.
Mapping Dialog Fields with Contact Fields

Step 4: Populating Parent Fields data to New Record

The Red Colored box showing fields mapping between Parent record and New record. Same way choose any field and map that with field of Contact
Populating Parent Fields data to new record

Step 5: To set Parent record with one Lookup field of new record

Follow the below Picture.
Set Parent record with Lookup field of new record

Step 6: To add a created record’s link in the end of Dialog

Add a new page and again add a step of “Prompt and Response” under it. Then click Set properties and follow the below image. After that activate the Dialog Process.
Add created record link in the end of Dialog

Step 7: Script to open created Dialog on Button Click

  • Copy the Id of the new Dialog Process from location bar and then do the following
  • Create a Web Resource of Script type using below script
  • Add the Web Resource to the Button Click Event
function LaunchModalDialog()
{
    var dialogId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"; //id of dialog process
    var recordId = Xrm.Page.data.entity.getId();
    var typeName = Xrm.Page.data.entity.getEntityName();
    recordId = recordId.toString();
    recordId = recordId.replace("{", "");
    recordId = recordId.replace("}", "");

    var serverUrl = Xrm.page.getServerUrl();
    
    // Load modal
    var serverUri = serverUrl +'/cs/dialog/rundialog.aspx';

    var mypath = serverUri +'?DialogId=%7b' + dialogId.toUpperCase() +'%7d&EntityName=' + typeName + '&ObjectId=%7b' + recordId +'%7d';

    // First item from selected contacts only
    window.showModalDialog(mypath);

    // Reload form.
    window.location.reload(true);
}

By Sukanta Mangal
Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 
 

Tags: , , , , , , , , , , , , , , , ,

CRM 2013 – Refresh Associated Grid of an Entity

Introduction

Today I got a requirement to add a custom Ribbon Button in the SubGrid of Marketing List Entity and execute some logic and refresh the Grid. Last point was the trickiest one for me and that is why I decided to share the approach how to do it.

Steps

To achieve this, let’s go step by step.

Step-1: Create a JavaScript library that will be executed when Button is Clicked

function OpenLookUp(grid){
    //your logic

    //code that will refresh the grid
    grid.refresh();
}

Step-2: Add Custom Button using Ribbon Workbench and follow the Screen Shots

img1

img4
Select WebResource

Add the Selected Control as parameter.
img3

Step-3: Publish Solutions using Ribbon Workbench

Now the view will refresh after the Button is clicked.

By Puja Jain
Senior Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 
2 Comments

Posted by on December 27, 2013 in WebResources

 

Tags: , , , , , , , , , , , , , , , , , , , , , , , ,

How to Associate Marketing List with Lead, Contact or Account Entity using SOAP Service

Introduction

As we know SDK.REST.js is a JavaScript library having functionality to do many ‘Client-Server‘ operations, so it provides a function to associate two records of different Entities.

Background

I have a requirement in my project to open a Marketing List Lookup on click of a custom button and able to add multiple Marketing List to Lead, Contact or Account records. I have tried this using REST service, but it threw an error message of “Associate not support for Marketing List“. Then I tried using SOAP service and got a fruitful solution.

Let’s do it…

Create a Web Resource for Custom Button and go through the following code.
Here “OpenLookUp function will be fired on button click.

var relationname;
var entityName;
function OpenLookUp(grid) {
    // prepare the CRM URL
    //var serverurl = Xrm.Page.getServerUrl();
    var customServerURL = document.location.protocol + "//" + document.location.host;

    var membertypecode;
    entityName = Xrm.Page.data.entity.getEntityName();
    if (entityName == "lead")
        membertypecode = "4";
    else if (entityName == "account")
        membertypecode = "1";
    else if (entityName == "contact")
        membertypecode = "2";
    
    var url = customServerURL + '/_controls/lookup/lookupinfo.aspx?AllowFilterOff=1&objecttypes=4300&DefaultType=4300&DefaultViewId=%7b7D7737D8-1A05-4ABB-BEBD-843404A83DAD%7d&DisableQuickFind=0&DisableViewPicker=1&LookupStyle=multi&ShowNewButton=1&ShowPropButton=1&browse=0&listType=static&membertypecode=' + membertypecode + '';
    var lookUp = window.showModalDialog(url, "entity", "dialogWidth:600px0px;dialogHeight:600px0px;,resizable=1,menubar=0,status=1,location=0,toolbar=0,scrollbars=1");
    
    if (lookUp != null) {
        if (typeof lookUp != 'object') {
            lookUp = $.parseJSON(lookUp);
            associateMarketingListToEntity(lookUp);
        }
    }
}

///<summary>
/// Associates records asynchronously and displays messages so you can verify the association
///</summary>
function associateMarketingListToEntity(lookup) {
    var id = Xrm.Page.data.entity.getId();
    
    relationname = "Referenced" + entityName + "_parent_list";
    entityName = (entityName.charAt(0)).toUpperCase() + entityName.substr(1, entityName.length - 1);

    var itemLists = lookup.items;
    for (var i = 0; i < itemLists.length; i++) {
        AddMemberListRequest(id.replace(/[{}]/g, ""), (itemLists[i].id).replace(/[{}]/g, ""));
    }
}

function AddMemberListRequest(id, Listid) {
    var requestMain = "";

    requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
    requestMain += "  <s:Body>";
    requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
    requestMain += "      <request i:type=\"b:AddListMembersListRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
    requestMain += "        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
    requestMain += "          <a:KeyValuePairOfstringanyType>";
    requestMain += "            <c:key>ListId</c:key>";
    requestMain += "            <c:value i:type=\"d:guid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + Listid + "</c:value>";
    requestMain += "          </a:KeyValuePairOfstringanyType>";
    requestMain += "          <a:KeyValuePairOfstringanyType>";
    requestMain += "            <c:key>MemberIds</c:key>";
    requestMain += "            <c:value i:type=\"d:ArrayOfguid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">";
    requestMain += "              <d:guid>" + id + "</d:guid>";

    requestMain += "            </c:value>";
    requestMain += "          </a:KeyValuePairOfstringanyType>";
    requestMain += "        </a:Parameters>";
    requestMain += "        <a:RequestId i:nil=\"true\" />";
    requestMain += "        <a:RequestName>AddListMembersList</a:RequestName>";
    requestMain += "      </request>";
    requestMain += "    </Execute>";
    requestMain += "  </s:Body>";
    requestMain += "</s:Envelope>";

    var req = new XMLHttpRequest();
    req.open("POST", _getServerUrl(), true);

    // Responses will return XML. It isn't possible to return JSON.
    req.setRequestHeader("Accept", "application/xml, text/xml, */*");
    req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
    req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
    var successCallback = null;
    var errorCallback = null;
    req.onreadystatechange = AddListMembersListResponse(req, null, null);
    req.send(requestMain);
}

function ReLoadForm() {
    window.location.reload(true);
}

///<summary>
/// Receives the assign response
///</summary>
///<param name="req" Type="XMLHttpRequest">
/// The XMLHttpRequest response
///</param>
///<param name="successCallback" Type="Function">
/// The function to perform when an successful response is returned.
/// For this message no data is returned so a success callback is not really necessary.
///</param>
///<param name="errorCallback" Type="Function">
/// The function to perform when an error is returned.
/// This function accepts a JScript error returned by the _getError function
///</param>
function AddListMembersListResponse(req, successCallback, errorCallback) {
    if (req.readyState == 4) {
        if (req.status == 200) {
            if (successCallback != null)
            { successCallback(); }
        }
        else {
            _getError(req.responseXML);
        }
    }
}

///<summary>
/// Returns the URL for the SOAP endpoint using the context information available in the form
/// or HTML Web Resource.
///</summary>
function _getServerUrl() {   
    var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
    var serverUrl = "";
    if (typeof GetGlobalContext == "function") {
        var context = GetGlobalContext();
        serverUrl = context.getServerUrl();
    }
    else {
        if (typeof Xrm.Page.context == "object") {
            serverUrl = Xrm.Page.context.getServerUrl();
        }
        else
        { throw new Error("Unable to access the server URL"); }
    }
    if (serverUrl.match(/\/$/)) {
        serverUrl = serverUrl.substring(0, serverUrl.length - 1);
    }
    return serverUrl + OrgServicePath;
}

///<summary>
/// Parses the WCF fault returned in the event of an error.
///</summary>
///<param name="faultXml" Type="XML">
/// The responseXML property of the XMLHttpRequest response.
///</param>
function _getError(faultXml) {    
    var errorMessage = "Unknown Error (Unable to parse the fault)";

    if (typeof faultXml == "object") {
        try {
            var bodyNode = faultXml.firstChild.firstChild;
            //Retrieve the fault node
            for (var i = 0; i < bodyNode.childNodes.length; i++) {
                var node = bodyNode.childNodes[i];
                //NOTE: This comparison does not handle the case where the XML namespace changes
                if ("s:Fault" == node.nodeName) {
                    for (var j = 0; j < node.childNodes.length; j++) {
                        var faultStringNode = node.childNodes[j];
                        if ("faultstring" == faultStringNode.nodeName) {
                            errorMessage = faultStringNode.text;
                            break;
                        }
                    }
                    break;
                }
            }
        }
        catch (e) { };
    }
    return new Error(errorMessage);
}

By Sukanta Mangal
Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 

Tags: , , , , , , , , , , , , , , , , , ,

How to Bulk Delete Workflow Jobs in Microsoft Dynamics CRM

Introduction

Whenever a Workflow is triggered, a System Job record is created in Microsoft Dynamics CRM and this will be a burden on CRM database. So, eventually Microsoft Dynamics CRM Administrator needs to clean-up the existing Workflow Jobs. Here, we will explore a very quick and easy way to bulk delete all the existing completed System Jobs created by Workflows in Microsoft Dynamics CRM.

 Steps

Image

Login in to Microsoft CRM >> Settings >> Data Management >> Bulk Record Deletion >> click New to start the Bulk Deletion Wizard.

Click Next on the Wizard >> Look for: “System Jobs” >> set the following criteria:

  • Status Equals Completed
  • System Job Type Equals Workflow

Image

Click Next to set the options such as Start Date and Time, set Number of Days to run this recursively & to send a notification when job is finished.

Image

Click Next and Submit it.

By Abhisek Sriramka
Senior Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 
Leave a comment

Posted by on December 24, 2013 in CRM WorkFlow

 

Tags: , , , , , , , , , , , , , , , , , , ,

Retrieve N:N Relationship Records using CrmFetchKit

Introduction

CrmFetchKit is a Cross Browser library that allows the execution of fecthXml queries via JavaScript for Dynamics CRM 2011 and CRM 2013 (using the new WCF Endpoints).

Background

In one of my recent projects, the requirement was to retrieve all Contacts present in a Campaign and to display all those in a Grid onload of Campaign record. As this process would fetch many records, so it should be Asynchronous.

Steps

Here are the steps how to use CrmFetchKit for retrieving records.

Step:1 Get the fetchXml using Advanced Find in Crm.

In my case, I used Advanced Find on Account Entity. Download the fecthXml and save it. It will be like below.

<?xml version="1.0"?>
<fetch distinct="true" mapping="logical" output-format="xml-platform" version="1.0"> 
    <entity name="contact"> 
        <attribute name="contactid"/>
        <attribute name="ownerid"/>
        <attribute name="fullname"/>
        <attribute name="lastname"/>
        <attribute name="telephone2"/>
        <attribute name="firstname"/>
        <attribute name="emailaddress1"/>
        <attribute name="createdon"/>
        <attribute name="new_city"/> 
        <order descending="false" attribute="ownerid"/> 
        <link-entity name="new_campaign_contact" intersect="true" visible="false" to="contactid" from="contactid"> 
        <link-entity name="campaign" to="campaignid" from="campaignid" alias="ab"> 
            <filter type="and">
                <condition attribute="campaignid" value="  campaignId  " uitype="campaign" 
 value="{8BE16D9E-8A7A-E211-B46D-00155D641D0E}"  operator="eq"/> 
            </filter> 
        </link-entity>
        </link-entity>
    </entity> 
</fetch>

Step:2 Add reference of fecthKit in the page where you are going to retrieve records.

<script src="../Scripts/jquery.1.7.1.min.js" type="text/javascript"></script>
<script src="../Scripts/CrmFetchKit.js" type="text/javascript"></script>

NB:The jQuery sholud be jquery.1.7.1.min.js (or higher).

Step:3 Add the code for retrieving Contacts present in a Campaign.

var contactData;
var campaignId;

campaignId = parent.Xrm.Page.data.entity.getId();

if(campaignId != null && campaignId != undefined)
{
    var fecthXMLForContact = '<fetch distinct="true" mapping="logical" output-format="xml-platform" version="1.0">'+
                             '<entity name="contact"> <attribute name="contactid"> <attribute name="ownerid">' +
                             '<attribute name="fullname"> <attribute name="lastname">' +
                             '<attribute name="telephone2"> <attribute name="firstname">' +
                             '<attribute name="emailaddress1"> <attribute name="createdon"> <attribute name="new_city">' +
                             '<order descending="false" attribute="ownerid">' +
                             '<link-entity name="new_campaign_contact" intersect="true" visible="false" to="contactid"   from="contactid">' +
                             '<link-entity name="campaign" to="campaignid" from="campaignid" alias="ab">' +
                             '<filter type="and"> <condition attribute="campaignid" value="' + campaignId + '" uitype="campaign" operator="eq">' +
                             '</condition></filter> </link-entity> </link-entity>' +
                             '</order></attribute></attribute></attribute></attribute></attribute>' +
                             '</attribute></attribute></attribute></attribute></entity> </fetch>';

     CrmFetchKit.Fetch(fecthXMLForContact).fail(function (xhr, status, errorThrown) {
         // get the error-message
         var msg = $(xhr.responseXML).find('Message').text();
         alert('Error occured: ' + msg);
     })
     .done(function (resultsContact) {
         contact = true;
         contactData = resultsContact;                
     });
}

In fetchXml, replace value of CampaignId with the Campaign Id for which you need to retrieve records.
The variable contactData will contain all records present in Campaign.
Here you are done!!!

By Gitanjali
Senior Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 

Tags: , , , , , , , , , , , , , , , , , , ,

CRM 2013 – Passing Custom Parameters to OpenEntityForm Function

Introduction

As we know that Microsoft included Xrm.Utility functions for Microsoft Dynamics CRM 2011, but when trying to pass custom parameters to OpenEntityForm as mentioned by Xrm.Utility Reference, I get following CRM Error.

errormsg

Background

In one of my projects, I need to open a new Email on save of Phone Call Activity and pass the parameters to the new opening Email form. But using the Xrm.Utility Reference link, I got the error as given above. Hence I had found a work around to pass the custom parameters to OpenEntityForm.

Steps

Here are the steps to pass the custom parameters:

Step-1: Add parameters in Email Entity Form.

img

Step-2: Setting custom parameters to pass to the new Email form.

//method call on save of phone call activity
function OpenNewEmail()
{
    //set the parameters to pass to the new form
    var parameters = {};
    parameters["regarding_Id"] =Xrm.Page.getAttribute("regardingobjectid").getValue()[0].id;
    parameters["regarding_name"] = Xrm.Page.getAttribute("regardingobjectid").getValue()[0].name;
    parameters["regarding_type"] = Xrm.Page.getAttribute("regardingobjectid").getValue()[0].entityType;

    //Open the new form
    Xrm.Utility.openEntityForm("email", null, parameters);
}

Step-3: Get the custom parameters in Email Entity Form.

function OnFormLoad()
{
    // Get the Value of the Regarding through the Custom Parameters
    var xrmObject= Xrm.Page.context.getQueryStringParameters();
    var leadName = xrmObject["regarding_name"].toString();
    var leadId = xrmObject["regarding_Id"].toString();
    var entityType = xrmObject["regarding_type"].toString();
}

By Sukanta Mangal
Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 
6 Comments

Posted by on December 4, 2013 in WebResources

 

Tags: , , , , , , , , , , , , , , , , ,

 
%d bloggers like this: