Wednesday, 18 November 2020

Show Lookup Dialog in Dynamics 365 v9.0

 

Introduction:

In Dynamics 365 v9.0 Microsoft introduces new development feature in Dynamics 365 to show lookup dialog using Xrm.Utility.lookupObjects method.

Xrm.Internal.Opendialog is most commonly used method to open dialog where we need to provide URL. But this method is not supported in UCI or mobile app.

So, open a lookup window using JavaScript can be achieved using Xrm.Utility.lookupObjects method.

Parameters for Xrm.Utility.lookupObjects method is as follows:

  • entityTypes: provide list of the entities to be displayed.
  • defaultEntityType: Specify the default entity to be shown in lookup window.
  • defaultViewId: Specify the Guid of default view need to be displayed in lookup dialog.
  • allowMultiSelect: Specify whether want to allow user to select multiple records.
  • viewIds: Provide the list of views that need to be available for lookup dialog.

Consider, an example where we need to open html webresource, on html page there will be a textbox and button to select the contact. When user click on “Select Contact” button, the lookup dialog of contact will gets open which allows user to select contact.

Steps need to follow:

1. We need to create html page with textbox and “Select Contact” button.

<!DOCTYPE html>

<html xmlns=”http://www.w3.org/1999/xhtml”>

<head>

<title></title>

<meta http-equiv=”X-UA-Compatible” content=”IE=11″ />

<style>

.bottomsection {

position: absolute;

float: right;

margin-top: 5%;

right: 10px;

bottom: 5px;

display: inline-block;

background-color: #F8F8F8;

border-top-color: #FFFFFF;

}

</style>

</head>

<body onload=”load();”>

<div style=”text-align:center”>

<h2>Contact Details</h2>

</div>

<div style=”height:50px”></div>

<div>

Please select Contact : <input type=”text” id=”TxtContact” /> <input type=”button” id=”btnContact” value=”Select Contact” />

</div>

<div>

<input type=”button” class=”bottomsection”  name=”Ok” value=”OK” />

</div>

<script src=”new_Jquery.js” type=”text/javascript”></script>

<script src=”ClientGlobalContext.js.aspx”></script>

<script src=”../../../../_static/_controls/lookup/lookup.js”></script>

<script src=”new_ShowContactLookup.js”></script>

<script type=”text/javascript”>

function load() {

this.OnContactSelectClicked();

}

</script>

</body>

</html>

2.  Next write a script for showing lookup dialog using Xrm.Utility.lookupObjects method.

function openWeb()

{

try {

var height = 360;

var width = 600;

//open the generate Work Order dialog

height = height != “undefined” ? height : null;

width = width != “undefined” ? width : null;

if (typeof Xrm != “undefined” && typeof Xrm.Navigation != “undefined” && Xrm.Navigation.openWebResource != “undefined”) {

var windowsOption = { height: height, width: width, openInNewWindow: true };

Xrm.Navigation.openWebResource(“new_ContactDetails.html”, windowsOption, null);

} else if (typeof Xrm != “undefined” && typeof Xrm.Utility != “undefined” && typeof Xrm.Utility.openWebResource != “undefined”) {

Xrm.Utility.openWebResource(“new_ContactDetails.html”, null, width, height);

} else {

return;

}

} catch (e) {

Xrm.Utility.alertDialog(e.message);

}

}

function OnContactSelectClicked()

{

try {

//bind click event of select contact lookup

$(“#btnContact”).click(function (e)

{

showContactLookupDialog();

});

} catch (e) {

Xrm.Utility.alertDialog(e.message);

}

}

function showContactLookupDialog() {

try {

var fetch = “<filter type=’and’><condition attribute=’lastname’ operator=’like’ value=’%a%’ /></filter>”;

var encodedURL = encodeURIComponent(fetch).replace(/’/g, “%22”);

var lookupParameters = {};

//specify the list of entity types to be displayed in lookup dialog

lookupParameters.entityTypes = [“contact”];

//Sepecify the default entityType need to be displayed

lookupParameters.defaultEntityType = “contact”;

//Default view need to be displayed

lookupParameters.defaultViewId = “{00000000-0000-0000-00AA-000010001004}”;

//allow multiple selection or not

lookupParameters.allowMultiSelect = false;

//list multiple views available on lookup dialog

// lookupParameters.viewIds = [“{0D5D377B-5E7C-47B5-BAB1-A5CB8B4AC105}”, “{A2D479C5-53E3-4C69-ADDD-802327E67A0D}”];

lookupParameters.customFilters = [encodedURL];

lookupParameters.customFilterTypes = [“contact”];

Xrm.Utility.lookupObjects(lookupParameters).then(DisplaySelectedContact, null);

} catch (e) {

Xrm.Utility.alertDialog(e.message);

}

}

function DisplaySelectedContact(selectedContact) {

try {

if (selectedContact != undefined &&  selectedContact != null && selectedContact != “”)

$(“#TxtContact”).val(selectedContact[0].name);

} catch (e) {

Xrm.Utility.alertDialog(e.message);

}

}

3. Add ribbon button “Contact Details” on Account form. Add “openWeb” function onclick of the ribbon button.

Show Lookup Dialog

4. Now when we click on the contact lookup button it will open the “Contact Details” html page.

Show Lookup Dialog

5. This html page consist of a textbox and “Select Contact” button. When user click on the button, lookup dialog with default entity and default view provided in parameters of lookupObjects method gets open.

Show Lookup Dialog

6. In UCI or Mobile app it opens the lookup dialog as shown in below screenshot.

Show Lookup Dialog


Working on Lookup Field of Dynamics 365 in PowerApps

 

Introduction:

PowerApps is a quick service that helps you to easily build business apps that runs on browsers and in phone or tablet without any coding experience needed. It allows anyone in an organization unlock new business agility.

Recently we had a business requirement, where we need to work on lookup field of Dynamics 365 using PowerApps, but currently, we cannot directly fetch the lookup values in PowerApps. So after some research and play around we found a solution on this.

This blog explains about steps to read and set Lookup fields of Dynamics 365 in Power Apps.

1. Create a new power Apps by selecting the Phone Layout as shown in the below screenshot.

Working on Lookup Field of Dynamics 365 in PowerApps

2. Select the database i.e. Entity and then click on Connect as shown in the below screenshot.

Working on Lookup Field of Dynamics 365 in PowerApps

3. We get the following three screen on the left side

  • Browse Screen
  • Detail Screen
  • Edit Screen

4. Click on Browse Screen and user can see the List of Opportunities in the CRM.

5. Now as seen in the below screenshot user can see GUID of parent account.

Working on Lookup Field of Dynamics 365 in PowerApps

To display the name of the parent account follow the steps as given below:

  • Add a data source of Account i.e. Account Entity by selecting on View, Data source and then select “Add Data Source” as shown in the below screenshot.

Working on Lookup Field of Dynamics 365 in PowerApps

To display the name of the parent account set the text property of the Body1 which contains parentaccountid as below:

LookUp(Accounts,accountid=ThisItem._parentaccountid_value,name)

The Lookup Property search the accountid in Accounts which equals to GUID shown in textbox and returns the name of the Account.

Working on Lookup Field of Dynamics 365 in PowerApps

Now you can see the name of the parent Account which is selected on Opportunity as shown below.

Working on Lookup Field of Dynamics 365 in PowerApps

Following are the steps to assign Lookup value in PowerApps:

1. Click on Edit Screen and insert the “Search” Icon inside a Data Card as shown in the below screenshot.

Working on Lookup Field of Dynamics 365 in PowerApps

2. Insert another List screen and add data source as Accounts. This screen will show list of Accounts present in CRM.

Working on Lookup Field of Dynamics 365 in PowerApps

 

3. On “OnSelect” property of Search Icon set the formula as:

Navigate(AccountScreen,ScreenTransition.Fade,{searchAccountName : DataCardValue12 .Text});Clear(accountToBeAdded)

Working on Lookup Field of Dynamics 365 in PowerApps

The above formula will navigate the Account Screen which shows list of Accounts and update the value of searchAccountName by value in DataCardValue12

4. Now on Account Screen, on “OnSelect” property of  icon write the formula as

ClearCollect(accountTobeAdded , {account :BrowseGallery2.Selected});Back()

Working on Lookup Field of Dynamics 365 in PowerApps

This formula create a collection name as “accountToBeAdded” and add the selected account in Collection and navigate back to the Edit Screen.

5. Now go back to the edit form, on text box of the Account  set the Default property  as following:

If(IsBlank(First(accountToBeAdded).account.accountid),Blank(),First(accountToBeAdded).account.name)

Working on Lookup Field of Dynamics 365 in PowerApps

This formula check whether the “accountToBeAdded” collection contain accountid. If true set the name else set it as “Blank”.

6. On Update property of Data Card set the formula as:

First(accountToBeAdded).account.accountid

Working on Lookup Field of Dynamics 365 in PowerApps

The above formula will update the Data card value to the selected account.

Dynamics 365 v9.0: Xrm.WebApi – CRUD Operations

 

Introduction:

Microsoft Dynamics 365 July Update, formally known as V9.0 has come up with lots of new and exciting features. No doubt these features have been applauded by end users and developers.

One of the important enhancement that will be boon for developer is Xrm.WebApi. Earlier to v9.0, to perform CRUD operation in Dynamics CRM we need to create our own library or used other third party libraries or used XmlHttpRequest and ajax request. So Xrm.WebApi is a cool enhancement added in Dynamics 365 v9.0 which will help to make developers life simple.

In this blog, we will discuss about how we can perform CRUD operations and work with all data types using newly added WebApi in Xrm namespace.

Using Xrm.WebApi:

Below is the example where we can used Xrm.WebApi.

1. Create:

To create the record, first we need to create the object of entity and then set the required fields and its value and then call Xrm.WebApi.createRecord function to create record in CRM. The parameters of this function are shown below;

1. Entity logical name

2. Entity object

/// This function is used to create a contact record
function createContact() {
    var contactObj = null;
    try {
       
        // create the contact object
        contactObj = new Object();
        contactObj.firstname = "Mike";
        contactObj.lastname = "Morgan";
        contactObj.creditonhold = false;

        //set optionsetvalue
        contactObj.accountrolecode = 2;
        //set the lookup value
        contactObj["parentcustomerid_account@odata.bind"] = "/accounts(A8A19CDD-88DF-E311-B8E5-6C3BE5A8B200)"

        Xrm.WebApi.createRecord("contact", contactObj).then(function (result) {
            //get the guid of created record
            var recordId = result.id;

            //below code is used to open the created record
            var windowOptions = {
                openInNewWindow: true
            };
            //check if XRM.Utility is not null
            if (Xrm.Utility != null) {

                //open the entity record
                Xrm.Utility.openEntityForm("contact", recordId, null, windowOptions);
            }
        },
      function (error) {
          Xrm.Utility.alertDialog(error.message);
      });

    } catch (e) {
        Xrm.Utility.alertDialog(e.message);
    }
}

 2. Update:

To update the record, first we need to create the object of the entity and then set the fields and its value that we need to update and then call Xrm.WebApi.updateRecord function to create the record in CRM. The parameters of this function are as shown below;

1. Entity logical name

2. Entity guid

3. Entity object

//this function is used to update contact
function updateContact() {
    var ownerId = null;
    var contactObj = null;
    try {

        // create the contact object
        contactObj = new Object();

        //set the properties
        contactObj.creditonhold = true;
        //set optionsetvalue
        contactObj.accountrolecode = 3;
        //set the lookup value        
        ownerId = "1809D364-F311-4B0A-98D2-198B721B2061";
        contactObj["ownerid@odata.bind"] = "/systemusers(" + ownerId + ")"

        // pass entity logical name , entity guid, entity object
        Xrm.WebApi.updateRecord("contact", "49A0E5B9-88DF-E311-B8E5-6C3BE5A8B200", contactObj).then(function (result) {
            Xrm.Utility.alertDialog("Record updated successfully.");
        },
function (error) {
            Xrm.Utility.alertDialog(error.message);
        });

    } catch (e) {
        Xrm.Utility.alertDialog(e.message);
    }
}

3. Delete:

To delete record from CRM use Xrm.WebApi.deleteRecord.

 The parameters of this function are shown below;

1. Entity logical name

2. Entity guid

/// This function is used to retrieve the Delete record
function deleteRecord() {
    try {
        Xrm.WebApi.deleteRecord("contact", "8DA6E5B9-88DF-E311-B8E5-6C3BE5A8B200")
      .then(function (result) {
          Xrm.Utility.alertDialog("Record deleted successfully.");
      },
       function (error) {
        Xrm.Utility.alertDialog(e.message);

      });
    } catch (e) {
        Xrm.Utility.alertDialog(e.message);
    }
}

4. Retrieve Record:

In order to retrieve record we can use Xrm.WebApi.retrieveRecord. The parameters of this function are as shown below;

1. Entity logical name

2. Entity guid

3. In last parameter pass following [select cause, filter cause etc.]

 

Note: If you want to get the value of lookup field you have use _ as prefix and _value as suffix. For example for parentcustomerid use _parentcustomerid_value

/// This function is used to retrieve the contact record
function retrieveContact() {
    try {

        Xrm.WebApi.retrieveRecord("contact", "465B158C-541C-E511-80D3-3863BB347BA8", "$select=fullname,telephone1,preferredcontactmethodcode,createdon,_parentcustomerid_value,creditlimit")
            .then(function (data) {
                retrieveContactSuccess(data);
            },
             function (error) {
                Xrm.Utility.alertDialog(error.message);
            });
    } catch (e) {
        Xrm.Utility.alertDialog (e.message);
    }
}

///retrieve success
function retrieveContactSuccess(data) {
   
    try {
        //get the values 

        //string
        var fullname = data["fullname"];

        //optionset
        var typeCode = data["customertypecode"];

        //lookup
        var customerGuid = data["_parentcustomerid_value"];
        var customerName = data["_parentcustomerid_value@OData.Community.Display.V1.FormattedValue"];
        var customerEntityLogicalName = data["_parentcustomerid_value@Microsoft.Dynamics.CRM.lookuplogicalname"];      

        //money
        var creditLimit = data["creditlimit@OData.Community.Display.V1.FormattedValue"];

        //date
        var createdonFormattedValue = data["createdon@OData.Community.Display.V1.FormattedValue"]; // gives date in following format 2017-09-30T21:10:19Z
        
        var createdon = data["createdon"]; // gives date in following format 10/1/2017 2:40 AM

        //optionset
        var preferredConMethod = data["preferredcontactmethodcode@OData.Community.Display.V1.FormattedValue"];        

    } catch (e) {
        Xrm.Utility.alertDialog(e.message);
    }
}


1. Retrieve Multiple: 

Retrieve multiple is used to retrieve more than one record from MS CRM. Suppose we want to retrieve all active contact from CRM then we will use the Retrieve multiple.

If we want to retrieve multiple records then use Xrm.WebApi.retrieveMultipleRecords

The parameters of this function are shown below.

  1. Entity logical name
  2. Odata Query (i.e. select and filter)
//this function is used to retrieve Account
function retrieveMultipleAccounts() {
    var queryOption = "";
    try {

        //create the query
        queryOption = "?$select=fullname,telephone1,preferredcontactmethodcode,createdon,_parentcustomerid_value,creditlimit&$filter=(statecode eq 0)";

        //execute the query and get the results
        Xrm.WebApi.retrieveMultipleRecords("contact", queryOption)
           .then(function (data) {
               retrieveContactSuccess(data.entities);
           },
               function (error) {
                   Xrm.Utility.alertDialog(error.message);
               };

    } catch (e) {
        Xrm.Utility.alertDialog(e.message);
    }
}

In retrieveContactSucess function loop through the records and get the values as shown below.

///retrieve success
function retrieveContactSuccess(results) {

    try {
        //get the values 
        $.each(results, function (index, data) {

            //string
            var fullname = data["fullname"];

            //lookup
            var customerGuid = data["_parentcustomerid_value"];
            var customerName = data["_parentcustomerid_value@OData.Community.Display.V1.FormattedValue"];
            var customerEntityLogicalName = data["_parentcustomerid_value@Microsoft.Dynamics.CRM.lookuplogicalname"];

            //money
            var creditLimit = data["creditlimit@OData.Community.Display.V1.FormattedValue"];

            //date
            var createdonFormattedValue = data["createdon@OData.Community.Display.V1.FormattedValue"]; // gives date in following format 2017-09-30T21:10:19Z

            var createdon = data["createdon"]; // gives date in following format 10/1/2017 2:40 AM

            //optionset
            var preferredConMethod = data["preferredcontactmethodcode@OData.Community.Display.V1.FormattedValue"];
        });
    } catch (e) {
        Xrm.Utility.alertDialog(e.message);
    }
}

If you have more than 5000 records than used data.nextLink. And if the response has value data.nextLink then used it to retrieve next set of records.

2. Execute Action: 

There are predefined Actions defined in Dynamics CRM 2016 that can be executed using Web API. On the following link will find the list of Web API actions. https://msdn.microsoft.com/en-in/library/mt607829.aspx

There are three types of Action as listed below.

Unbound actions: It is not bound to any specific entity. i.e the first parameter to such actions does not include the entity. E.g. WinOpportunity, CancelContract etc

Bound actions: It is bound to a specific entity. i.e the first parameter to such actions does not include the entity. e.g. – AddToQueue Action

Custom action: It is custom actions developed by developers using Processes.

Now we will discuss about Qualify request. Suppose you want to qualify request programmatically then we will use Qualify request. Web API provides QualifyLead Action.

In our blog, we have explained QualifyLead using WebApi. Now we will see how we can do the same using inbuilt Xrm.WebApi.

To execute action use Xrm.WebApi.execute.

//This function is used to qualify lead
function qualifyLead() {
    var saleOrderID = null;
    var columnsSet = null;
    var salesOrderToInvoiceReq = null;
    var leadId = "E5975EA3-531C-E511-80D8-3863BB3CE2C8";
    var qualifyLeadReq = "";
    try {

        qualifyLeadReq = {
            entity: {
                id: leadId,
                entityType: "lead"
            },
            CreateAccount: true,
            CreateContact: true,
            CreateOpportunity: true,
            Status: 3,
            getMetadata: function () {
                var metadata = {
                    boundParameter: "entity",
                    parameterTypes: {
                        "entity": {
                            "typeName": "Microsoft.Dynamics.CRM.lead",
                            "structuralProperty": 5
                        },
                        "CreateAccount": {
                            "typeName": "Edm.Int32",
                            "structuralProperty": 1
                        },
                        "CreateContact": {
                            "typeName": "Edm.Int32",
                            "structuralProperty": 1
                        },
                        "CreateOpportunity": {
                            "typeName": "Edm.Int32",
                            "structuralProperty": 1
                        },
                        "Status": {
                            "typeName": "Edm.Int32",
                            "structuralProperty": 1
                        }
                    },
                    operationName: "QualifyLead",
                    operationType: 0
                };

                return metadata;
            }
        };

        Xrm.WebApi.execute(qualifyLeadReq)
            .then(function (result) {
                Xrm.Utility.alertDialog("Success");
            },
            function (error) {
                var message = error.message;
                //Add handling of error that occurred
            });
  } catch (e) {
Xrm.Utility.alertDialog(e.message);
    }

}

 

Thursday, 6 August 2020

How to use Xrm and formContext in HTML WebResource in Dynamics 365 CRM

Introduction

In this blog we will explore how to pass ‘Xrm’ and ‘formContext’ in HTML pages using the
‘getContentWindow’ client API in Unified Interface of Dynamics 365 CRM so that we can get or set the form attributes inside the HTML web resource.  As we all know, parent.Xrm is going to deprecate in near future so below is the supported way to use the ‘Xrm’ and ‘formContext’ in HTML page.

Suppose there is a HTML web resource on Account entity form which shows notes record related to a Parent Account. And from the HTML page we need to read or set some fields on Account record using formContext and also want to do CRUD operations inside the HTML Page using Xrm.webapi. So, the Xrm and formContext won’t be accessed directly in HTML page. To access, you can follow the below steps:

1. Add the below code in the ‘onLoad’ event handler of Account entity. The below code is written in Typescript so you need to compile it in JavaScript and add it on ‘onLoad’ event of the account form.

onLoad(executionContext: any): void {

let functionName: string = “onLoad”;

try {

//validate execution context

if (!CRMWork_Account_Library.isValid(executionContext)) { return }

//get form context

let formContext = executionContext.getFormContext();

//validate form context

if (!CRMWork_Account_Library.isValid(formContext)) { return }

//Get AccountNotes control

let accountNotesControl = formContext.getControl(“WebResource_AccountNotes”)

//Validate control

if (CRMWork_Account_Library.isValid(accountNotesControl)) {

//get getContentWindow

accountNotesControl.getContentWindow().then(

function (contentWindow) {

//Pass xrm and formcontext

contentWindow.setClientApiContext(Xrm,formContext);

}

)

}

}

catch (ex) {

CRMWork_Account_Library.throwError(functionName, ex);

}

}

In the above code, we are accessing the HTML page using getControl method. Using the getContentWindow() which returns a content window instance representing an IFRAME or web resource we are going to pass the parameter ‘Xrm’ and ‘formContext’ in HTML page.

‘WebResource_AccountNotes’ is the name of the HTML web resource control added on the Account form.

HTML WebResource in Dynamics 365 CRM

2. Bind the above code on ‘Onload’ of the Account form as shown in below screenshot:

HTML WebResource in Dynamics 365 CRM

3. Now, add the following code in your HTML web resource:

<script>

function setClientApiContext(xrm, formContext) {

//To set the attribute on Account form

formContext.getAttribute(“preferredcontactmethodcode”).setValue(1);

//To do CRUD operation

var data =

{

“subject”: “Sample”,

}

// create Note record

xrm.WebApi.createRecord(“annotation”, data).then(

function success(result) {

console.log(“Notes created with ID: ” + result.id);

},

function (error) {

console.log(error.message);

// handle error conditions

}

);

}

</script>

You can see in above function we have set the value of the ‘preferredcontactmethodcode’ attribute on Account record and we created a new note record using Xrm.webapi functions.

Note: The function name defined in the HTML page i.e. ‘setClientApiContext’ should use the same function name while calling in Onload function of Form event handler.

Conclusion

As illustrated above, you can now pass ‘Xrm’ and ‘formContext’ in HTML pages using the
‘getContentWindow’ client API in Unified Interface of Dynamics 365 CRM.