Sunday, May 6, 2012

Dynamics CRM 2011 : AddToQueueRequest via Workflow, JScript, C# Code & Using in Plugin

In Dynamics CRM 2011 we can manually assign the entity records to Queue from the Entity Form or List View (Grid) ribbon Add to Queue button but to assign the items automatically to queue either we can create a Queue Item record (discussed in this post) or may use AddToQueue request.

The following examples below can be use to add an entity record to the Queue via a process Workflow, Jscript, C# code and also explains how to use plugin code for AddToQueue plugin message.
[Workflow Process Example]

The following steps below describe the solution for adding a High Priority cases to the High Priority Cases Queue using AddToRequest by using workflow custom activity.

1.    Import WodCrmWorkflowLibrary_1_0_managed.Zip solution in CRM, you can download solution from this link: https://skydrive.live.com/redir.aspx?cid=06f61fc8aa6032c9&resid=6F61FC8AA6032C9!152&parid=6F61FC8AA6032C9!117

2.    Create new workflow process, go to Settings Process Center Processes, click on new button and enter process details:

·         Enter Processname i.e.  Assign Cases to Queue,
·         In Entity field choose Case
·         In Category field choose Workflow and click ok button

3.    In workflow Options for Automatic Process choose the following:

·         In Scope choose Organization
(If require to run this workflow for all Case records regardless of Business Units or User specific records)
·         In Starts When check Record is Created option

4.    Add Check Condition step, click on the condition and In Specify Condition Web Dialog, choose Case  (entity) in first list box, choose Priority (case entity field) from second list box, choose Equals (condition operator) in list box  and choose High (case priority field value) in the final list box. The condition will look like:

Case                Priority                       Equals             High

5.    Add wod.Crm.Workflow.Library.v1 QueuesLibrary.wod_AddToQueueRequest step and click on Set properties button and set the following properties:

·         In Source Queue field, choose queue from which the record is required to be move (optional paramter)
·         In Destination Queue field, choose queue record i.e. High Priority Queue
·         If you will mention the entity name in Entity Name field (optional paramter) then you have to also pass the Entity GUID into the Entity GUID field, if these fields will leave blank then workflow actvity will automatically take up current entity and its GUID

6.    Click on Activate button to Activate the process

[C# Code Example]

   private void Main(IOrganizationService wod_CrmService)
    {

            // Assigning CRM Queue GUID value, the entity record will be added to this queue
            // SourceQueueId parameter is optional and may skip
            Guid wod_SourceQueueId = new Guid("D8FACAB8-6B8F-E111-A6A1-B8AC6F3EDD32");

            // Assigning CRM Queue GUID value, the entity record will be added to this queue
            Guid wod_DestinationQueueId = new Guid("10AD0882-9F96-E111-A6A1-B8AC6F3EDD32");

            // Assigning entity name & id, this entity record will be added to the queue
            EntityReference wod_CaseLookup = new EntityReference()
            {
                LogicalName = "incident",
                Id = new Guid("EE0CB48D-A28F-E111-A6A1-B8AC6F3EDD32")
            };

            // Creating AddToQueueRequest and assigning require parameter values to it
            // AddToQueueRequest object will be passed to the CRM service execute method

            AddToQueueRequest wod_AddtoQueueRequest = new AddToQueueRequest
            {
             // Only pass Source Queue Id parameter (optional) value in case of moving item from
             // older queue to new queue
                SourceQueueId = wod_SourceQueueId,

                DestinationQueueId = wod_DestinationQueueId,
                Target = wod_CaseLookup
            };

            // Passing AddToQueueRequest object to CRM Service Execute method
            // for request processing
            AddToQueueResponse wod_AddToQueueResponse =
                              (AddToQueueResponse)wod_CrmService.Execute(wod_AddtoQueueRequest);



[JScript Code Example]


if (typeof (wod_SDK) == "undefined")
{ wod_SDK = { __namespace: true }; }
//This will establish a more unique namespace for functions in this library. This will reduce the
// potential for functions to be overwritten due to a duplicate name when the library is loaded.
wod_SDK.QueuesLib = {
    _getServerUrl: function () {
        ///<summary>
        /// Returns the URL for the SOAP endpoint using the context information available in the form
        /// or HTML Web resource.
        ///</summary>
        var ServicePath = "/XRMServices/2011/Organization.svc/web";
        var serverUrl = "";
        if (typeof GetGlobalContext == "function") {
            var context = GetGlobalContext();
            serverUrl = context.getServerUrl();
        }
        else {
            if (typeof Xrm.Page.context == "object") {
                serverUrl = Xrm.Page.context.getServerUrl();
            }
            else
            { throw new Error("Unable to access the server URL"); }
        }
        if (serverUrl.match(/\/$/)) {
            serverUrl = serverUrl.substring(0, serverUrl.length - 1);
        }

        return serverUrl + ServicePath;
    },
    AddToQueueRequest: function (prmSourceQueueId, prmDestinationQueueId, prmEntityName, prmEntityId) {
        var wod_Request = ""
        wod_Request += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
        wod_Request += "  <s:Body>";
        wod_Request += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
        wod_Request += "      <request i:type=\"b:AddToQueueRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
        wod_Request += "        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
        wod_Request += "          <a:KeyValuePairOfstringanyType>";
        wod_Request += "            <c:key>Target</c:key>";
        wod_Request += "            <c:value i:type=\"a:EntityReference\">";
        wod_Request += "              <a:Id>" + prmEntityId + "</a:Id>";
        wod_Request += "              <a:LogicalName>" + prmEntityName + "</a:LogicalName>";
        wod_Request += "              <a:Name i:nil=\"true\" />";
        wod_Request += "            </c:value>";
        wod_Request += "          </a:KeyValuePairOfstringanyType>";
        wod_Request += "          <a:KeyValuePairOfstringanyType>";
        wod_Request += "            <c:key>DestinationQueueId</c:key>";
        wod_Request += "            <c:value i:type=\"d:guid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + prmDestinationQueueId + "</c:value>";
        wod_Request += "          </a:KeyValuePairOfstringanyType>";

        if (prmSourceQueueId != null && prmSourceQueueId != "") {
            wod_Request += "          <a:KeyValuePairOfstringanyType>";
            wod_Request += "            <c:key>SourceQueueId</c:key>";
            wod_Request += "            <c:value i:type=\"d:guid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + prmSourceQueueId + "</c:value>";
            wod_Request += "          </a:KeyValuePairOfstringanyType>";
        }

        wod_Request += "        </a:Parameters>";
        wod_Request += "        <a:RequestId i:nil=\"true\" />";
        wod_Request += "        <a:RequestName>AddToQueue</a:RequestName>";
        wod_Request += "      </request>";
        wod_Request += "    </Execute>";
        wod_Request += "  </s:Body>";
        wod_Request += "</s:Envelope>";

        var req = new XMLHttpRequest();
        req.open("POST", wod_SDK.QueuesLib._getServerUrl(), 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(wod_Request);

        //Checking if error occurs
        var errorMessage = wod_SDK.QueuesLib._getError(req.responseXML);

        if (errorMessage != "") {
            alert(errorMessage);
        }
    },
    _getError: function (faultXml) {
        ///<summary>
        /// Parses the WCF fault returned in the event of an error.
        ///</summary>
        ///<param name="faultXml" Type="XML">
        /// The responseXML property of the XMLHttpRequest response.
        ///</param>
        var errorMessage = "";
        if (typeof faultXml == "object") {
            try {
                var bodyNode = faultXml.firstChild.firstChild;
                //Retrieve the fault node
                for (var i = 0; i < bodyNode.childNodes.length; i++) {
                    var node = bodyNode.childNodes[i];

                    //NOTE: This comparison does not handle the case where the XML namespace changes
                    if ("s:Fault" == node.nodeName) {
                        for (var j = 0; j < node.childNodes.length; j++) {
                            var faultStringNode = node.childNodes[j];
                            if ("faultstring" == faultStringNode.nodeName) {
                                errorMessage = faultStringNode.text;
                                break;
                            }
                        }
                        break;
                    }
                }
            }
            catch (e) { };
        }
        return errorMessage;
    },

    __namespace: true
};



[JScript Code Function Call Example]


// Function Call : Source Queue Id (optional may pass null), Destination Queue Id (required),
// Entity Logical Name (required), Entity GUID (required)

wod_SDK.QueuesLib.AddToQueueRequest(null, DestinationQueueId "incident", IncidentGUID);


[Plugin Usage Example]


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using Microsoft.Crm.Sdk;

namespace wod.Crm.AddToQueuePlugin
{
    public class wodPlugin : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            // Obtain the execution context from the service provider.
            IPluginExecutionContext context = (IPluginExecutionContext)
                serviceProvider.GetService(typeof(IPluginExecutionContext));

            try
            {
                switch (context.MessageName)
                {
                    case "AddToQueue":

                      Guid wod_SourceQueueId = Guid.Empty, wod_DestinationQueueId = Guid.Empty;

                      EntityReference wod_EntityReference = null;

                      // SourceQuueId paramter (optional) will only pass if record will be moved
                      // from one queue to another
                      if (context.InputParameters.Contains("SourceQueueId"))
                      {
                            wod_SourceQueueId = (Guid)context.InputParameters["SourceQueueId"];
                      }

                   // Destination Queue Id, record will be added to this queue
                   wod_DestinationQueueId = (Guid)context.InputParameters["DestinationQueueId"];

                   // Entity record Reference which will be added to the destination queue
                   wod_EntityReference = (EntityReference)context.InputParameters["Target"];

                   break;
                }
            }

            catch (System.Web.Services.Protocols.SoapException ex)
            {
                throw new InvalidPluginExecutionException(ex.Detail.InnerText);
            }

            catch (Exception ex)
            {
                throw new InvalidPluginExecutionException(ex.Message);
            }
        }
    }
}
                       

6 comments:

  1. The blog is absolutely fantastic. Lots of great information and inspiration, both of which we all need. Thanks.

    ReplyDelete
  2. Thank you for your compliments :) and i hope to publish soon new articles and free CRM utilities.

    ReplyDelete
  3. Thats very good . i think this information really help me . Thanks.

    ReplyDelete
  4. Hello Javeed,
    I am looking at a requirement where we can change the WorkOn to different users instead of queue routing. Is that a possibility using C#?

    ReplyDelete
  5. If you need your ex-girlfriend or ex-boyfriend to come crawling back to you on their knees (even if they're dating somebody else now) you must watch this video
    right away...

    (VIDEO) Why your ex will NEVER come back...

    ReplyDelete