Friday, July 4, 2014

Filter Sub Grid control based on value selected in lookup field in CRM 2013


If you are planning to filter Sub Grid based on the value selected in look up field or change of look up field value, then this bog will help to achieve this customization in CRM 2013.
To demonstrate, I have created one look up field of type Account and Sub Grid that shows Contact records based on Account set in look up field.
 
Requirement is to filter the sub grid so as to show only contact records based on the value selected in Account look up field.
This need to be achieved by client side scripting, below JS function will filter the sub grid based on look up field value (Display contact records that are associated to account selected in look up field).

function FilterSubgrid() {
    var filterId = null;
    var accountLookupObject = Xrm.Page.getAttribute('new_account').getValue();  // get look up field value 

    if (accountLookupObject != null) {
        accountLookupObject[0].name; // text of lookup
        filterId = accountLookupObject[0].id; // Guid of lookup
    }

    var subgridnameObject = document.getElementById("Contacts");   // Contacts is the name of the sub grid on the form 

    if (subgridnameObject == null || subgridnameObject.readyState != "complete") {
        setTimeout(function () { FilterSubgrid(); }, 100);
        return;
    } 

    if (filterId == null) return; 

    // Fetch xml for retrieving filtered contacts based on primary customer

    var fetchXml = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>";

    fetchXml += "<entity name='contact'>";

    fetchXml += "<attribute name='fullname'/>";

    fetchXml += "<attribute name='telephone1'/>";

    fetchXml += "<attribute name='contactid'/>";   

    fetchXml += "<order attribute='fullname' descending='false' />";

    fetchXml += "<filter type='and'>";

    fetchXml += "<condition attribute='parentcustomerid' operator='eq' uitype='account' value='"+filterId+"' />";

    fetchXml += "</filter>";

    fetchXml += "</entity>";

    fetchXml += "</fetch>"; 

    subgridnameObject.control.SetParameter("fetchXml", fetchXml);

    subgridnameObject.control.refresh();


}

This function need to be used on form load as well as on change of look up field value.

Wednesday, July 2, 2014

How to maintain managed solution in CRM

Solutions are how customizers and developers author, package, and maintain units of software that extend Microsoft Dynamics CRM
 
There are two types of Microsoft Dynamics CRM solutions: managed and unmanaged. A managed solution is a completed solution that is intended to be distributed and installed. An unmanaged solution is one that is still under development or isn’t intended to be distributed. When the unmanaged solution is complete and you want to distribute it, export it and package it as a managed solution.
 
Before we release managed solution to another environment, we need to consider how to maintain it. If already managed solution is installed, if there is any update in the solution components then uninstalling and reinstalling a managed solution is not a good option when solution contains entities or attributes. This is because data will be lost when entities are deleted.
 
The preferred way to address above problem, is to release a new version of your managed solution.In original unmanaged source solution, make necessary changes and increase the version number of the solution before packaging it as a managed solution.
 

When the organizations that use your solution install the new version, their capabilities will be upgraded to include your changes. If you want to go back to the behavior in a previous version, simply re-install the previous version. This overwrites any solution components with the definitions from the previous version but does not remove solution components added in the newer version.
 
During the installation of previous version of a solution CRM will confirm that the person installing prevoius version wants to proceed.

Note: It is good practice to take back up of each version of managed solution, so we can revert any version of the solution at any point of time.
 

Microsoft Dynamic CRM 2011 useful XRM scripts


Get the value from a CRM field
var value = Xrm.Page.getAttribute(“CRMFieldSchemaName”).getValue();


Set the value of a CRM field
Xrm.Page.getAttribute(“CRMFieldSchemaName “).setValue(“New Value”);


Get the value from a CRM OptionSet field
var value = Xrm.Page.getAttribute(“CRMOptionSetSchemaName”).getValue();


Get the text from a CRM OptionSet field
var text = Xrm.Page.getAttribute(“CRMOptionSetSchemaName”).getText();


Set the value of a CRM OptionSet field
Xrm.Page.getAttribute(“CRMOptionSetSchemaName”).setValue(“1″); // OptionSet Value


Get the selected text of a CRM OptionSet field
Xrm.Page.getAttribute(“CRMOptionSetSchemaName”).getSelectedOption().text;


Get the selected value of a CRM OptionSet field
Xrm.Page.getAttribute(“CRMOptionSetSchemaName”).getSelectedOption().value;


Get the text and value of a CRM Lookup field
var lookupObject = Xrm.Page.getAttribute(“CRMLookupSchemaName”).getValue();
lookupObject[0].name; // text of lookup
lookupObject[0].id; // Guid of lookup


Set the value of a CRM Lookup field
var lookupData = new Array();
var lookupItem = new Object();
lookupItem.id = “4A2A54CB-349C-E111-8D26-1CC1DEE8DA78″; // Guid of record
lookupItem.name = “New Contact”; // Entity record name
lookupItem.entityType = “EntitySchemaName”;
lookupData[0] = lookupItem;
Xrm.Page.getAttribute(“CRMLookupSchemaName”).setValue(lookupData);


Disable CRM field
Xrm.Page.ui.controls.get(“CRMFieldSchemaName”).setDisabled(true);


Hide CRM field
Xrm.Page.ui.controls.get(“CRMFieldSchemaName”).setVisible(false);


Hide a Tab in CRM
Xrm.Page.ui.tabs.get(“tabName”).setVisible(false);


Hide a Section in CRM
var tab = Xrm.Page.ui.tabs.get(“tabName”);
tab.sections.get(“sectionName”).setVisible(false);


Set the Requirement level in CRM
Xrm.Page.getAttribute(“CRMFieldSchemaName”).setRequiredLevel(“required”);
Xrm.Page.getAttribute(“CRMFieldSchemaName”).setRequiredLevel(“none”);
Xrm.Page.getAttribute(“CRMFieldSchemaName”).setRequiredLevel(“recommended”);


Set Focus on a field in CRM
Xrm.Page.ui.controls.get(“CRMFieldSchemaName”).setFocus(true);


Cancelling Onsave Event in CRM
event.returnValue = false;
return false;


Note: Make sure to check the checkbox for Pass execution context as first parameter in event handlers of the form.

Check IsDirty in CRM field
var isDirty = Xrm.Page.getAttribute(“CRMFieldSchemaName”).getIsDirty();
alert(isDirty); // returns true if the field is dirty


Check IsDirty for all the fields in CRM
var isDirty = Xrm.Page.data.entity.getIsDirty();
alert(isDirty); // returns true if any of the field is dirty in the entire form.


Force Submit a read only field in CRM
Xrm.Page.getAttribute(“CRMFieldSchemaName”).setSubmitMode(“always”);


Preventing an attribute to be saved in CRM form
Xrm.Page.getAttribute(“CRMFieldSchemaName”).setSubmitMode(“never”);


Get Unique Organization Name in CRM
Xrm.Page.context.getOrgUniqueName();


Get Server url in CRM
Xrm.Page.context.getServerUrl();


Get the record Id in CRM
Xrm.Page.data.entity.getId();


Get the User Id in CRM
Xrm.Page.context.getUserId();


Get the Entity Schema Name in CRM
Xrm.Page.data.entity.getEntityName();


Get the UserRole Id’s in CRM
var userRoles = Xrm.Page.context.getUserRoles();
for (var i = 0; i < userRoles.length; i++)
{
var userRole = userRoles[i]; // returns the Role Id
}


Get the Form Type in CRM
Xrm.Page.ui.getFormType();


Form Types in CRM
Is the user creating a new record?
Xrm.Page.ui.getFormType() == “1″


Is the user updating an existing record?
Xrm.Page.ui.getFormType() == “2″


Is the user unable to update this record?
Xrm.Page.ui.getFormType() == “3″


Is this record deactivated?
Xrm.Page.ui.getFormType() == “4″


Is the user using the Quick Create form?
Xrm.Page.ui.getFormType() == “5″


Is the user using the Bulk Edit form?
Xrm.Page.ui.getFormType() == “6″


Save a record in CRM
Xrm.Page.data.entity.save(); // for saving a record
Xrm.Page.data.entity.save(“saveandclose”); // for save and close
Xrm.Page.data.entity.save(“saveandnew”); // for save and new


Close the form in CRM
Xrm.Page.ui.close();



Useful functions

// Function to disable tabfunction tabdisable(tabname, disablestatus) {

var allSections = Xrm.Page.ui.tabs.get(tabname).sections.get(); //returns all the sections for the tab "tabname"

for (var i in allSections) {

var allCntrls = allSections[i].controls.get(); //get all the controls for this section.

for (var j in allCntrls) {

if (allCntrls[j].getName() != null && allCntrls[j].getName() != "asu_mdn") {

if (allCntrls[j].getControlType() == 'lookup' || allCntrls[j].getControlType() == 'standard' || allCntrls[j].getControlType() == 'optionset') {
allCntrls[j].setDisabled(disablestatus);
         }
      }
    }
  }
}
// Function to hide ribbon button
function HideRibbonButton(buttonID, action) {
var intervalId = self.setInterval(function () {

var button = window.top.document.getElementById(buttonID);

if (button != null) {

self.clearInterval(intervalId);

button.style.display = action;

}

}, 10);

}

// Function Disable Notes Contolfunction DisableNotesControl(val) {
var controlId = "notescontrol" // this is the default id of the notes control
   
 var iframe = document.getElementById(controlId);
if (iframe.readyState == "complete") {

DisableNotesControlContents(iframe, val); // this will be used once notes control is loaded and with complete state

}
// onreadystatechange works with IE but not other browsers

iframe.onreadystatechange =function () {
if (iframe.readyState == "complete") {
DisableNotesControlContents(iframe, val);

     }

   }

}

function DisableNotesControlContents(iframe, val) {
var controls = iframeDoc.getElementsByTagName("textarea");

 
if (controls != null) {

for (var i = 0; i < controls.length; i++) {

controls[i].disabled = val;

     }

   }

}


 
 

Resolving incident programmatically in Microsoft Dynamic CRM 2011


This blog explains how to resolve the case programmatically. It can be used in Plugin or Custom workflow or from any web application that interacts with CRM.

We need to use CloseIncidentRequest to close an incident (case) with a case resolution.

Incident cannot be closed if there are any activities with "Open" status. So we need to programmatically complete all the activities associated to incident and then close the incident.

First we will see how to complete all the activities associated to case. Below function accepts IOrganizationService and incident GUID as an parameter to make the status of all the activities as “Complete” for the incident id passed.

Note: We need to complete only activities that are Open.

private void CompleteAssociatedActivities(IOrganizationService service, Guid incidentId)
        {
            using (OrganizationServiceContext context = new OrganizationServiceContext(service))
            {
                try
                {
                    var query = (from a in context.CreateQuery("activitypointer")
                                 where (a.GetAttributeValue<Guid>("regardingobjectid") == incidentId) && a.GetAttributeValue<int>("statecode") != 1
                                 select new { Activity = a }).ToList();
                    foreach (var v in query)
                    {
                        if (v.Activity.Contains("activitytypecode") && !Guid.Empty.Equals(v.Activity.Id))
                        {
                            SetStateRequest setStateRequest = new SetStateRequest();

                            // Completing Interaction activty

                            setStateRequest.EntityMoniker = new EntityReference(v.Activity["activitytypecode"].ToString(), v.Activity.Id); 

                            // Set the State and Status OptionSet Values to completed.

                            setStateRequest.State = new OptionSetValue(1);
                            setStateRequest.Status = new OptionSetValue(2); 

                            // Execute the Response
                            SetStateResponse setStateResponse = (SetStateResponse)service.Execute(setStateRequest);
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw; // or log the error
                }
            }
        }

Next step is to close the incident as we completed all the activities associated to the incident. Below function uses CloseIncidentRequest to close Incident with resolution.

private void ResolveIncident(IOrganizationService service, Guid recordGUID, string entityName)
        {
            CloseIncidentRequest closeIncidentRequest = new CloseIncidentRequest();
            try
            {
                closeIncidentRequest.IncidentResolution = new Entity("incidentresolution");
                closeIncidentRequest.IncidentResolution["subject"] = "Resolved incident";
                closeIncidentRequest.IncidentResolution["incidentid"] = new EntityReference(entityName, recordGUID);
                closeIncidentRequest.Status = new OptionSetValue(5);

                CompleteAssociatedActivities(service, recordGUID); // Makes all the activities associated to case to complete before resolving a case

                service.Execute(closeIncidentRequest);
            }
            catch (Exception ex)
            {
                throw;
            }
        }


Hope this blogs helps to understand resolving incident by completing all activities.