Saturday, October 17, 2015

Debug Minified Script in IE 11

Hi,

Today when I was working on some JavaScript issues, I see that there are many minified JS files used and it was taking time to understand and add the debuggers on the fly on the IE 11.

After search I came to know that there is a formatting option available on IE 11 Developer tool kit. i.e. Pretty Print (Ctrl + Shift + P) which highlighted with Yellow Color in the below screen shot.
 

Hope this helps.

--
Happy Coding
Gopinath 

Get the Selected Record Id of Subgrid in CRM 2013/ 2015 - UnSupported

Hi,

At times in CRM, we need to go for unsupported things to fulfill customer requirements. In CRM 2011, we used to get the selected record id of the sub gird in the JavaScript method in a supported way. But in CRM 2013 and 2015 on premise versions we don't have feature available.

Here is the unsupported JavaScript to get the selected record id.

function GetSelectedRecordId() {
    // Grid Control Object
    var objGrid = document.getElementById("opportunityproductsGrid").control;
    // Get Selected Ids.
    var vSelectedIds = objGrid.get_selectedIds();
    if (vSelectedIds.length == 0) {
        alert("No record is selected.");
        return;
    }
    else if (vSelectedIds.length > 1) {
        alert("Please select only one record and click this button.");
        return;
    }
    else {
        // Your logic.
    }
    //All records record id in the sub grid
    // objGrid.get_allRecordIds();
}

Hope this helps.

--
Happy CRM'ing
Gopinath

Tuesday, October 13, 2015

Entity Ownership in CRM

In CRM, when you create a new entity you have to give Display Name, Plural Name, Description etc.. and you will select the ownership of the entity from Ownership field.

The other things are self explanatory but Ownership plays a crucial role in the CRM Security Model.

Entities can be Owned by

Organization
1) Records of “Organization owned entity” can be viewed by the whole organization
2) Records cannot be shared or Assigned.
3) Organization entities have two access levels - None and Organization.

User or a Team
1) Records of “User or a Team owned entity” can be limited to users or teams, so that you restrict data access to authorized users
2) The user-owned or team-owned entities have five access levels: None, User level, Business unit level, Parent: Child Business unit level, Organization

Hope this helps.

--
Happy CRM'ing
Gopinath

Monday, October 12, 2015

Get QueryString Parameters in JavaScript

Hi,

Today I worked on a requirement where we need to read query string parameters on the load of the html page and do some operation based on the values.

Here is the JavaScript to read query string parameters.


function getQuerystringNameValue(name) {
    // page.htm?id=100&code=101&recid=102
    // Ex - passing a name parameter of "id" will return a value of "100", etc.
    var winURL = window.location.href;
    var queryStringArray = winURL.split("?");
    var queryStringParamArray = queryStringArray[1].split("&");
    var nameValue = null;
    for (var i = 0; i < queryStringParamArray.length; i++) {
        queryStringNameValueArray = queryStringParamArray[i].split("=");
        if (name == queryStringNameValueArray[0]) {
              nameValue = queryStringNameValueArray[1];
        }
    }
    return nameValue;
}

Hope this helps.

--
Happy CRM'ing
Gopinath

Error processing request stream. The request should be a valid top-level resource object CRM and oData

Hi,

Today I got the below error when I was trying to update Product Properties using Java Script.

Error processing request stream. The request should be a valid top-level resource object

The code is as follows.

function updateProductProperties() {
   var vUpdateProperty = {};
   vUpdateProperty.ValueString = "testing";
   vUpdateProperty.DynamicPropertyId = "guid";
   vUpdateProperty.RegardingObjectId = "guid"
   var vdynamicProductPropertyId = "<DynamicPropertyInstanceGUID>";
   SDK.REST.updateRecord(vdynamicProductPropertyId, vUpdateProperty, "DynamicPropertyInstance", function () { alert("The dynamic property instance record changes were saved"); }, function (error) { alert(error.message); });
}

After some search I figured out the error was because of type mismatch. When you get this type of error check the fields are mapped to correct data type references. In my case, I need to use Entity Reference Object where I used normal string.

Here is the correct code.

function updateProductProperties() {
    var vUpdateProperty = {};
    vUpdateProperty.ValueString = "testing";
    vUpdateProperty.DynamicPropertyId = { Id: "", LogicalName: "dynamicproperty" };
    vUpdateProperty.RegardingObjectId = { Id: "", LogicalName: "opportunityproduct" };
    var vdynamicProductPropertyId = "<DynamicPropertyInstanceGUID>";
    SDK.REST.updateRecord(vdynamicProductPropertyId, vUpdateProperty, "DynamicPropertyInstance", function () { alert("The dynamic property instance record changes were saved"); }, function (error) { alert(error.message); });
}

Hope this helps.

--
Happy CRM'ing
Gopinath

Update Dynamic Property Instance using JavaScript in CRM 2015

Hi,
 
Today we got the requirement to update Dynamic Product Properties of an Opportunity Product using JavaScript.
 
Here is the JavaScript code for doing it.
 
function updateProductProperties() {
   var vUpdateProperty = {};
   vUpdateProperty.ValueString = "testing";
   vUpdateProperty.DynamicPropertyId = { Id: "", LogicalName: "dynamicproperty" };
   vUpdateProperty.RegardingObjectId = { Id: "", LogicalName: "opportunityproduct" };
   var vdynamicProductPropertyId = "<DynamicPropertyInstanceGUID>";
   SDK.REST.updateRecord(vdynamicProductPropertyId, vUpdateProperty, "DynamicPropertyInstance", function () { alert("The dynamic property instance record changes were saved"); }, function (error) { alert(error.message); });
}

Refer this link for Updating Product Properties using C#

Hope this helps.
 
--
Happy CRM'ing
Gopinath

Wednesday, October 7, 2015

Create a folder in SharePoint from CRM Plugin

Hi,
 
Today we got requirement to create a folder automatically in Share Point when a record is created in CRM. Normally SharePoint document location is created when we click on Documents on the left navigation pane for the record.
 
It can be done very easily by using the plugin but we should register the plugin None mode. It's not applicable for Online CRM.
 
Here is the code. 

public void Execute(IServiceProvider serviceProvider)
{
      IPluginExecutionContext iContext = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
      IOrganizationServiceFactory iServFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
      IOrganizationService iService = iServFactory.CreateOrganizationService(iContext.UserId);
      ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
      if (iContext.InputParameters.Contains("Target") && iContext.InputParameters["Target"] is Entity && iContext.MessageName.ToLower() == "create")
      {
           Entity entAccount = (Entity)iContext.InputParameters["Target"];
           string strSharePointURL = CreateFolderInSharePoint(iService, entAccount.Attributes["name"].ToString(), entAccount.Id);
      }
}

public string CreateFolderInSharePoint(IOrganizationService coreCrmService, string strAccountName, Guid guidAccountId)
{
      string strDocLibraryUrl = "http://SharePointURL";
      string strApplicationFolderUrl = strDocLibraryUrl + "/" + "account";
      string strFolderUrl = strApplicationFolderUrl + "/" + strAccountName;
      // Create folder and subfolder inside SharePoint site
      CreateFolderStructure(strApplicationFolderUrl, strFolderUrl);
      // create and associate the url of the folder to SharePointDocumentLocation and the crm record.
      CreateAndAssociateSharePointDocumentLocation(coreCrmService, guidAccountId, "account", strFolderUrl);
      return strFolderUrl;
}

// Check and create folder.
private bool CreateFolderStructure(string strSharePointDocumentUrl, string strFolderUrl)
{
     if (CreateFolder(strSharePointDocumentUrl))
     {
          return CreateFolder(strFolderUrl);
     }
     return false;
}

// Create Folder
private bool CreateFolder(string strFolderUrl)
{
     try
     {
          WebRequest request = WebRequest.Create(strFolderUrl);
          request.UseDefaultCredentials = true;
          request.Method = "MKCOL";
          WebResponse response = request.GetResponse();
          response.Close();
     }
     catch (Exception ex)
     {
           // throw ex;
     }
     return true;
}

// Create a Document Location record in CRM by associating Share Point URL.
public static bool CreateAndAssociateSharePointDocumentLocation(IOrganizationService iService, Guid guidIncidentId, string strAccount, string strSharePointDocumentUrl)
{
      Entity entSharePointDocumentLocation = new Entity("sharepointdocumentlocation");
      entSharePointDocumentLocation.Attributes["name"] = "SharePoint Document Location for " + strAccount;
      entSharePointDocumentLocation.Attributes["description"] = "SharePoint Document Location created for storing documents related to account";
      entSharePointDocumentLocation.Attributes["absoluteurl"] = strSharePointDocumentUrl;
      entSharePointDocumentLocation.Attributes["regardingobjectid"] = new EntityReference("account", guidIncidentId);
      iService.Create(entSharePointDocumentLocation);
      return true;
}
 
Hope this helps.
 
--
Happy CRM'ing
Gopinath

Sunday, October 4, 2015

Trigger a plugin when a case (incident) is resolved in CRM

Hi,

To trigger a plugin when an incident is resolved we need to register the plugin on 'Close' message for the incident entity.

And in the input parameters of the context we need to check for IncidentResolution.

You can get the case id from Incident Resolution entity by using the following code.

IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
if (context.InputParameters.Contains("IncidentResolution"))
{
     Entity incidentResolution = (Entity)context.InputParameters["IncidentResolution"];
     Guid relatedIncidentGuid = ((EntityReference)incidentResolution.Attributes["incidentid"]).Id;
}

IncidentResolution is a special entity that holds the information about the incident record that is being closed.

Hope this helps.

--
Happy CRM'ing
Gopinath

Update records in CRM using Dialogs

Hi,
 
Updating records from Dialogs can be done very easily in CRM.
 
1) Create a new dialog.
2) Click on the row below the 'Steps' node and choose 'Page' from the 'Add Steps' button.
3) Select the row down and click on Add Step. Select 'Prompt and Response' and click on Properties.
4) On the Define Prompt and Response window, you can give your instructions and data type, response type and default value if you want to auto-populate anything.
5) Click on 'Save and Close'.
6) Click on Add Step and select Update Record.
7) Click on View Properties and select the field which you want to update.
8) Get the value from Assistant pane, click the 'Look For' combo box and down near the bottom under the 'Local Values', you should see an item for selection that matches the description you gave the prompt step.
9) Click on 'Save and Close' and activate the dialog.
10) Open the record for which you want to run the dialog and click on 'Start Dialog' button on the ribbon. This will open a dialog requesting the details.
 
Hope this helps.
 
--
Happy CRM'ing
Gopinath

Get OptionSet Values from CRM Database - StringMap in CRM

Hi,
 
At times we get requirement to query and get option set items from CRM and show them in a report or in some custom application. Then we query to SQL MSCRM Organization database to get the pick list values but we get values as 0, 1, 2 and 1000001 etc.. but where we need to show the text values.
 
To retrieve the associated descriptive information, we need ajoin to the StringMapBase table.
 
SELECT
       ATTRIBUTENAME,
       ATTRIBUTEVALUE,
       VALUE
FROM
       STRINGMAPBASE
WHERE
       LANGID = 1033 AND ATTRIBUTENAME = 'statecode' 
 
This works absolutely fine for the unique optionsets but not for StateCode. For statecode, we need to have a condition on objecttypecode. Here is the query to get the objecttypecode of the entity.
 
SELECT
       OBJECTTYPECODE,
       ENTITYID,
       NAME
FROM
       METADATASCHEMA.ENTITY
WHERE
       NAME = 'Opportunity' AND OVERWRITETIME = '1900-01-01' 
The reason for date filter is CRM maintains a history of changes to the entities. If a customization solution has been applied to your CRM instance, more than one record will exist for some entities.

Here is the query after joining.

SELECT
       strMap.ATTRIBUTENAME,
       strMap.ATTRIBUTEVALUE,
       strMap.VALUE
FROM
       STRINGMAPBASE strMap
INNER JOIN
       METADATASCHEMA.ENTITY ent ON strMap.OBJECTTYPECODE = ent.OBJECTTYPECODE
WHERE
       ent.NAME = 'Opportunity'
       AND strMap.ATTRIBUTENAME = 'statecode'
       AND ent.OVERWRITETIME = '1900-01-01'

The LangId filter in all the queries is simply filtering for the English language – this is needed for multi-lingual systems.
 
Hope this helps.
 
--
Happy CRM'ing
Gopinath