Tuesday, April 17, 2012

Changing the reply email address to the queue's email address when replying from a queue in crm 2011

The problem was that we have multiple queues with email addresses in crm 2011. When an email arrives it goes to a particular queue depending on the address that was used. Now what happens when you try to reply to that email? Well nothing much only that the "FROM address" lookup defaults to the currently logged on user instead of defaulting to the queue's email address.
There are various ways you can solve this issue by writing plugin or workflow custom activity etc, but the crux of the matter is that the crm user replying from a queue needs to the see what the from email address is.
This can be best achieved by using Java script.
Please note that the code below is an unsupported customization, but it works.
function CheckEnquiryReplyAddress() {
 // Only complete this validate on Create Form
 var formType = Xrm.Page.ui.getFormType();
 var emailStatus = GetAttributeValue("statecode");
                    var emailDirection = GetAttributeValue("directioncode");



 if (formType == 1 || (formType == 2 && emailStatus == "Open")) {  
                                             
                                       
  if (emailDirection == "1"){
                                                              var previousEmailId=getExtraqsParam("_InReplyToId", window.parent.location.search);

   //getting context from the parent window
   var context = Xrm.Page.context;

   try {
    var serverUrl = context.getServerUrl();
    //The XRM OData end-point
    var ODATA_ENDPOINT = "/XRMServices/2011/OrganizationData.svc";
                                                                                     var query="/EmailSet?$select=ActivityId,ActivityTypeCode,DirectionCode,";
                                                                                     query=query+"ToRecipients,Email_QueueItem/QueueId&$expand=Email_QueueItem&$filter=ActivityId eq guid'" + previousEmailId +"'";
    query =serverUrl+ODATA_ENDPOINT+ query;

    var request= new XMLHttpRequest();
    request.open("GET", query, false);
    request.setRequestHeader("Accept", "application/json");
    request.setRequestHeader("Content-Type", "application/json; charset=utf-8"); 
    request.onreadystatechange=function(){ CompleteEnquiryReplyCheck(request,serverUrl);}
    request.send(null);
   }
   catch(e) {
    alert(e.Description);
   }
  }
 }

          
}
function CompleteEnquiryReplyCheck(request,url)
{
 if (request.readyState==4) {
  if(request.status==200) {
   var queue=JSON.parse(request.responseText).d.results[0];
   
   if (queue != null) {
    var queueId = queue.Email_QueueItem.results[0].QueueId.Id;
    var lookup = new Array();
      var lookupItem = new Object();
  
    lookupItem.id = queueId;
    lookupItem.name = queue.Email_QueueItem.results[0].QueueId.Name;
    lookupItem.typename = "queue";
     
    lookup[0] = lookupItem;
  
    Xrm.Page.getAttribute("from").setValue(lookup);
   }
  }
    }
}
The key here is the _InReplyToId query string parameter from here we are able to query the oData service and get the "To" email address of the original email and then it is simply a matter of putting the "To" address in the "From" lookup. Also note that I am checking that this is an outgoing email. Find the code for getExtraqsParam here. Happy Crming!.

Monday, April 16, 2012

Executing CRM 2011 workflow via Javascript

To execute a workflow we have to use the soap web service. We cannot use oData service. So we have to create a soap envelope and post it to the organization web service. The following function will execute the workflow.
function ExecuteWorkFlow(entityId,workflowId,url)
{

    var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
    url = url + OrgServicePath;
    var request;
    request = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
  "<s:Body>" +
    "<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">"+
      "<request i:type=\"b:ExecuteWorkflowRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">"+
        "<a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">"+
          "<a:KeyValuePairOfstringanyType>"+
            "<c:key>EntityId</c:key>"+
            "<c:value i:type=\"d:guid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/\">"+ entityId+"</c:value>"+
          "</a:KeyValuePairOfstringanyType>"+
          "<a:KeyValuePairOfstringanyType>"+
            "<c:key>WorkflowId</c:key>"+
            "<c:value i:type=\"d:guid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/\">"+ workflowId +"</c:value>"+
          "</a:KeyValuePairOfstringanyType>"+
        "</a:Parameters>"+
        "<a:RequestId i:nil=\"true\" />"+
        "<a:RequestName>ExecuteWorkflow</a:RequestName>"+
      "</request>"+
    "</Execute>"+
  "</s:Body>"+
"</s:Envelope>";

  var req = new XMLHttpRequest();
  req.open("POST", url, 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");
  req.onreadystatechange = function () { assignResponse(req); };
  req.send(request);
  

}

function assignResponse(req) {
if (req.readyState == 4) {
    if (req.status == 200) {
        alert('successfully executed the workflow');
   }
   }
}

Happying Coding!

Accessing HTML web resource funcitons from entity Form in CRM 2011

I found this piece of code really handy. If you have a web resource that you place inside a form and if you want to manipulate the html within that html web resource you can do it.
Xrm.Page.getControl("WebResource_YourWebResource").getObject().contentWindow.window.WebResourceFunction
The function WebResourceFunction sits inside the HTML web resource and can do anything.
An example of how I used it was to call the HTML web resource function on the onchange event of a lookup and display something different for different values in the lookup box. Oh and yes you can pass parameters to the function as well.
To be fair, I found this technique on some other blog, but I can reference it since I lost the address and can't find it any more.
Happy Coding!

Tuesday, April 3, 2012

Parsing query string values in the extraqs parameter

If you want to get values of query string parameters that are inside the extraqs query string field in your crm form then you can call the getExtraqsParam function. It takes two values: they key is the param whose value you want to get to and the query is the actual query string which you can find through window.location.search property. Note that that window.locaiton.search only returns the query string part of the url.
 function getExtraqsParam(key,query)
        {   //Get the any query string parameters and load them
            //into the vals array

            var vals = new Array();
           
                vals = query.substr(1).split("&");
                for (var i in vals)
                {
                    vals[i] = vals[i].replace(/\+/g, " ").split("=");
                }
                //look for the parameter named 'extraqs'
                var found = false;
                var returnVal=null;
                for (var i in vals)
                {

                    if (vals[i][0].toLowerCase() == "extraqs")
                    {
                       
                         
                         returnVal= vals[i][1];

                          break;
                    }
                }

                return parseExtraqs(key,returnVal);                     

        }

function parseExtraqs(key,val)
{

    var returnVal;
    var vals;
    vals=decodeURIComponent(val).split("&");
    for (var i in vals)
     {
         vals[i] = vals[i].replace(/\+/g, " ").split("=");
         if (vals[i][0]==key)
        returnVal=decodeURIComponent(vals[i][1]);
     }
return returnVal;

}
Happy Crming!