CRM 2015 Building Action Links (or how a URL can change records in CRM)

I was looking for an easy way to allow a user to perform an action in CRM by opening a hyper link. The idea being the URL can be embedded in an email, SMS, or anything else, and simply opening the URL allows the user to perform an action in CRM (without having to actually use the full CRM interface).

I cobbled together this proof of concept which chains together a couple of components to create an “Action Link”.

aciton url process

So there are three main components:

  1. A standard hyper link, the id is a task record id, which is eventually passed to the action as input, e.g. https://crm//WebResources/new_Acknowledge?Data=id%3DCC87E9A5-C556-E511-80F2-3863BB350D58
  2. A HTML web resource (code below), reads the id from query string Data parameters. It then makes a SOAP call in JavaScript to fire the action with the id as input. I built mine from sticking together these resources:
    1. For reading parameters from the query string in a web resource – Sample: Pass multiple values to a web resource through the data parameter.
    2. For making a SOAP call to execute an action in JavaScript – Deepak Kumar’s Actions in CRM 2013.
  3. An action process in CRM, this one runs on a task and updates the description.

action

Once this was all put together then every time I hit my URL I am presented with my web resource. The id is consumed and passed to the action.

Capture

The action then makes an update to my task record (whose record Id was originally placed on the URL).

task

A simple proof of concept, this pattern could be easily extended with additional input parameters, an improved UI, and flexible action logic to allow a user to interact in a process by simply opening a URL.

Web resource code, this is a bit rough and ready.

</span>
<span><html>
<head>
 <title>Show Data Parameters Page</title>
 <script src="ClientGlobalContext.js.aspx" type="text/javascript"></script>
 <style type="text/css">
 body {
 font-family: Segoe UI, Tahoma, Arial;
 background-color: #d6e8ff;
 }
 
 tbody {
 background-color: white;
 }
 
 th {
 background-color: black;
 color: White;
 }
 </style>
 <script type="text/javascript">
 document.onreadystatechange = function() {
 if (document.readyState == "complete") {
 getDataParam();
 }
 }

 function getDataParam() {
 //Get the any query string parameters and load them
 //into the vals array

 var vals = new Array();
 if (location.search != "") {
 vals = location.search.substr(1).split("&");
 for (var i in vals) {
 vals[i] = vals[i].replace(/\+/g, " ").split("=");
 }
 //look for the parameter named 'data'
 var found = false;
 for (var i in vals) {
 if (vals[i][0].toLowerCase() == "data") {
 parseDataValue(vals[i][1]);
 found = true;
 break;
 }
 }
 if (!found) {
 noParams();
 }
 } else {
 noParams();
 }
 }

 function parseDataValue(datavalue) {
 if (datavalue != "") {
 var vals = new Array();

 var message = document.createElement("p");
 setText(message, "These are the data parameters values that were passed to this page:");
 document.body.appendChild(message);

 vals = decodeURIComponent(datavalue).split("&");
 for (var i in vals) {
 vals[i] = vals[i].replace(/\+/g, " ").split("=");
 }

 //Create a table and header using the DOM
 var oTable = document.createElement("table");
 var oTHead = document.createElement("thead");
 var oTHeadTR = document.createElement("tr");
 var oTHeadTRTH1 = document.createElement("th");
 setText(oTHeadTRTH1, "Parameter");
 var oTHeadTRTH2 = document.createElement("th");
 setText(oTHeadTRTH2, "Value");
 oTHeadTR.appendChild(oTHeadTRTH1);
 oTHeadTR.appendChild(oTHeadTRTH2);
 oTHead.appendChild(oTHeadTR);
 oTable.appendChild(oTHead);
 var oTBody = document.createElement("tbody");
 //Loop through vals and create rows for the table
 for (var i in vals) {
 var oTRow = document.createElement("tr");
 var oTRowTD1 = document.createElement("td");
 setText(oTRowTD1, vals[i][0]);
 var oTRowTD2 = document.createElement("td");
 setText(oTRowTD2, vals[i][1]);

 oTRow.appendChild(oTRowTD1);
 oTRow.appendChild(oTRowTD2);
 oTBody.appendChild(oTRow);
 }

 oTable.appendChild(oTBody);
 document.body.appendChild(oTable);

 var entityId = vals[0][1];
 var entityName = "task";
 var requestName = "new_AcknowledgeAction";
 ExecuteAction(entityId, entityName, requestName);

 var message = document.createElement("p");
 setText(message, "Acknowledged");
 document.body.appendChild(message);

 } else {
 noParams();
 }
 }

 function noParams() {
 var message = document.createElement("p");
 setText(message, "No data parameter was passed to this page");


 document.body.appendChild(message);
 }
 //Added for cross browser support.
 function setText(element, text) {
 if (typeof element.innerText != "undefined") {
 element.innerText = text;
 } else {
 element.textContent = text;
 }

 }

 function ExecuteAction(entityId, entityName, requestName) {
 // Creating the request XML for calling the Action
 var requestXML = ""
 requestXML += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
 requestXML += " <s:Body>";
 requestXML += " <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
 requestXML += " <request xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
 requestXML += " <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
 requestXML += " <a:KeyValuePairOfstringanyType>";
 requestXML += " <b:key>Target</b:key>";
 requestXML += " <b:value i:type=\"a:EntityReference\">";
 requestXML += " <a:Id>" + entityId + "</a:Id>";
 requestXML += " <a:LogicalName>" + entityName + "</a:LogicalName>";
 requestXML += " <a:Name i:nil=\"true\" />";
 requestXML += " </b:value>";
 requestXML += " </a:KeyValuePairOfstringanyType>";
 requestXML += " </a:Parameters>";
 requestXML += " <a:RequestId i:nil=\"true\" />";
 requestXML += " <a:RequestName>" + requestName + "</a:RequestName>";
 requestXML += " </request>";
 requestXML += " </Execute>";
 requestXML += " </s:Body>";
 requestXML += "</s:Envelope>";
 var req = new XMLHttpRequest();
 req.open("POST", GetGlobalContext().getClientUrl() + "/XRMServices/2011/Organization.svc/web", false)
 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");
 req.send(requestXML);
 }
 </script>
 <meta charset="utf-8">
</head>
<body>
<br>
</body>
</html></span>
<span>
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s