RSS

Monthly Archives: December 2013

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

Advertisements
 
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: , , , , , , , , , , , , , , , , ,

CRM 2013 – How to get Server URL in SOAP or REST ?

Introduction

This blog is simply explains the trick for getting the Server URL for SOAP Endpoint or REST Endpoint from the Context.

In CRM 2011

We were using following two lines of code to get Server URL.

var context = GetGlobalContext();
serverUrl = context.getServerUrl();

Now in CRM 2013

getClientUrl() will be supported instead of getServerUrl().

var context = GetGlobalContext();
clientUrl = context.getClientUrl();

By Anish Thakur
Senior Software Engineer @Team DynamicsCRM.
Mindfire Solutions

 
 

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

CRM2013 – Form Level Notifications

Introduction

In this blog, I will explain how to display Form level Notifications in CRM 2013.

Background

The requirement was, on entering an Account form the Account Number must be greater than 4 digits and Main Phone is a mandatory field or else we will show a notification “Account number should be more than 4 digits” and “Main phone field is mandatory” on the Form level.

Code

We will use the following two methods for our task.

  • setFormNotification(message, level, uniqueId) : To set the notification on Form level.
    1. message : Text of the notification.
    2. level : Message icon – can be “ERROR”, “WARNING” or “INFO”.
    3. uniqueid : Id to be used to clear notification.
  • clearFormNotification() : To remove the Notification from the Form.

Code can be used onChange or onSave event.

//Function To Show Error Notification On Form Level
function FormNotificationError()
{
    //Check If Digit Count of Account Number Is Less Than 4 or not
    if (CountDigit(Xrm.Page.getAttribute("accountnumber").getValue()) <= 4)
    {
        //Set The Form Notification With Error Icon
        Xrm.Page.ui.setFormNotification("Account number should be more than 4 digits", "ERROR", "accountnumber");
    }
    else
    {
        //Clear Notification
        Xrm.Page.ui.clearFormNotification("accountnumber");
    }
}

//Function To Show Warning Notification On Form Level
function FormNotificationWarning()
{
    //Check If The Main Phone Is Not Blank
    if (Xrm.Page.getAttribute("telephone1").getValue() == null)
    {
        //Set The Form Notification With Warning Icon
        Xrm.Page.ui.setFormNotification("Main phone field is mandatory", "WARNING", "telephone1");
    }
    else
    {
        //Clear Notification
        Xrm.Page.ui.clearFormNotification("telephone1");
    }
}

//Function To Get Count Of Digits
function CountDigit(number)
{
    return number.toString().length;
}

Output

Image
The screen shot displays the notification on the Form level for Account Number and Main Phone.

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

 
 

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

 
%d bloggers like this: