Tuesday, May 17, 2011

Using Assign Requests to Assign Entities to a User Using Jscript and .NET in Microsoft Dynamics CRM 2011

This illustration shows you how to assign an entity to a User (systemuser) in Microsoft Dynamics CRM 2011 using the assign request.   This example will be given in SOAP (JScript) and in C# (.NET).  In this example we are simply assigning a contact entity to a systemuser entity.

Ok, here is what the calls look like!
First in C#:

// Create the Request Object and Set the Request Object's Properties
         AssignRequest assign = new AssignRequest
         {
             //systemuser you are assigning the entity to
             Assignee = new EntityReference(SystemUser.EntityLogicalName,
                 new Guid("05B84284-0872-E011-8947-1CC1DEE8DAD5")),

             //entity you are assigning to the user
             Target = new EntityReference(Contact.EntityLogicalName,
                 new Guid("0C961D47-FB71-E011-882E-1CC1DEF17774"))
         };


         // Execute the Request
         service.Execute(assign);

If you need help instantiating a service object in .NET within a plugin check out this post:
http://mileyja.blogspot.com/2011/04/instantiating-service-object-within.html

Now here is the Jscript nicely formatted by the CRM 2011 SOAP formatter. Available at: http://crm2011soap.codeplex.com/

Now in Jscript:

if (typeof (SDK) == "undefined")
   { 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.
       SDK.SAMPLES = {
           _getServerUrl: function () {
               ///<summary>
               /// Returns the URL for the SOAP endpoint using the context information available in the form
               /// or HTML Web resource.
               ///</summary>
               var OrgServicePath = "/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 + OrgServicePath;
               }, 
           AssignRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"b:AssignRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
               requestMain += "        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>Target</c:key>";
               requestMain += "            <c:value i:type=\"a:EntityReference\">";
               requestMain += "              <a:Id>C9EE81A3-0572-E011-882E-1CC1DEF17774</a:Id>";
               requestMain += "              <a:LogicalName>contact</a:LogicalName>";
               requestMain += "              <a:Name i:nil=\"true\" />";
               requestMain += "            </c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>Assignee</c:key>";
               requestMain += "            <c:value i:type=\"a:EntityReference\">";
               requestMain += "              <a:Id>05b84284-0872-e011-8947-1cc1dee8dad5</a:Id>";
               requestMain += "              <a:LogicalName>systemuser</a:LogicalName>";
               requestMain += "              <a:Name i:nil=\"true\" />";
               requestMain += "            </c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>Assign</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.SAMPLES._getServerUrl(), 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");
               var successCallback = null;
               var errorCallback = null;
               req.onreadystatechange = function () { SDK.SAMPLES.AssignResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       AssignResponse: function (req, successCallback, errorCallback) {
               ///<summary>
               /// Recieves the assign response
               ///</summary>
               ///<param name="req" Type="XMLHttpRequest">
               /// The XMLHttpRequest response
               ///</param>
               ///<param name="successCallback" Type="Function">
               /// The function to perform when an successfult response is returned.
               /// For this message no data is returned so a success callback is not really necessary.
               ///</param>
               ///<param name="errorCallback" Type="Function">
               /// The function to perform when an error is returned.
               /// This function accepts a JScript error returned by the _getError function
               ///</param>
               if (req.readyState == 4) {
               if (req.status == 200) {
               if (successCallback != null)
               { successCallback(); }
               }
               else {
                   errorCallback(SDK.SAMPLES._getError(req.responseXML));
               }
           }
       },
       _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 = "Unknown Error (Unable to parse the fault)";
           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 new Error(errorMessage);
     },
 __namespace: true
};




To understand how to parse the response please review my post on using the DOM parser.
Now you can call the SDK.SAMPLES.AssignRequest function from your form jscript handler.  
Thats all there is to it!

I hope this helps!

Monday, May 16, 2011

Using LINQ in CRM 2011 Plugins

Andrew Zimmer, a friend and former colleague of mine from Inetium / Avtex posted this today. It very nicely explains how to use LINQ in CRM 2011 Plugins.

http://blogs.inetium.com/blogs/azimmer/archive/2011/05/13/using-linq-in-crm-2011-plugins.aspx

I am hoping someone can tell me if this methodology works with CRM Online sandbox plugins. Last I heard it was not working.

I hope this helps!

Debugging JScript in Microsoft Dynamics CRM 2011

So, in the forums, there are a lot of people asking about jscript / javascript problems or how to debug jscript in Microsoft Dynamics CRM 2011.  I probably tell at least two people a week how to do this and  I always point them to a different post that contains this information but it is somewhat buried.  I thought I should separate this into it's own post for clarity.  It's one of the most helpful tools for working with client-side jscript in CRM 2011 or any other version.

Let's take a look at a sample piece of jscript I want to debug.


function parseResponse(responseXML, attributename) {

    debugger;
    xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
    xmlDoc.async="false";
    xmlDoc.loadXML(responseXML);
    x=xmlDoc.getElementsByTagName("a:KeyValuePairOfstringanyType");
    for (i=0;i<x.length;i++)
   {
      if (x[i].childNodes[0].text == attributename)
      {
         //we decode the base 64 contents and alert the HTML of the Iframe
          alert(x[i].childNodes[1].text);
      }
      
   } 
}


You will notice in the first line of the of the Jscript above I included this miscellaneous line: debugger;

This causes a breakpoint in your code that can be picked up in your code as long as you go in IE to Tools - Internet Options - Advanced and uncheck the two "Disable script debugging" check boxes that are checked by default in IE.

Now, when IE hits the break point it will ask you how you want to debug it. I use Visual Studio 2010 for this debugging, and it stops on my breakpoint and I can use F10 and F11 to step through or step into my code step by step. Then I can add a watch or whatever I want.

Now, if I step into the code in Visual Studio and add my watch I can see all the attributes and, in the context of the jscript snippet above, can clearly see that I can look at the text of the first child node to see my attribute value and I can also drill down into the child nodes and other collections and properties within the structure to determine the syntax I need to unlock the needed values of the other types.


You can see above I am looking at the [0] child node and that the text is "content", you could look at the [1] child node here and see that it contains the value in the text property.

If you have questions feel free to ask questions in the comments.  I am more than willing to help with this kind of thing.

I hope this helps!

Thursday, May 12, 2011

How to: Use Disassociate Requests to Disassociate Related Entities Using Jscript and .NET in Microsoft Dynamics CRM 2011

Dissassociate requests are kind of line the "unfriend" in Facebook, you are breaking off a relationship that is defined within CRM between two entities.

This illustration shows you how to Disassociate two entities in Microsoft Dynamics CRM 2011 using the disassociate request against a known relationship.   This example will be given in SOAP (JScript) and in C# (.NET) with the Associate message against the CRM 2011 organization service.  In this example we are simply disassociating a contact from an account as it's parent customer using the existing "contact_customer_accounts" relationship in CRM.

You can find the relationship schema name to use in the request by going to settings - customization - your entity - relationships.  Here is an example of where to find it.


Ok, here is what the calls look like!
First in C#:

    DisassociateRequest dreq = new DisassociateRequest();

         //Target is the entity that you are disassociating your entities with.
         dreq.Target = new EntityReference("account", new Guid("A6951D47-FB71-E011-882E-1CC1DEF17774"));

         //RelatedEntities are the entities you are disassociating to your target (can be more than 1)
         dreq.RelatedEntities = new EntityReferenceCollection();
         dreq.RelatedEntities.Add(new EntityReference("contact", new Guid("C7EE81A3-0572-E011-882E-1CC1DEF17774")));

         //The relationship schema name in CRM you are using to disassociate the entities. 
         //found in settings - customization - entity - relationships
         dreq.Relationship = new Relationship("contact_customer_accounts");

         //execute the request
         service.Execute(dreq);

If you need help instantiating a service object in .NET check out this post:
http://mileyja.blogspot.com/2011/04/instantiating-service-object-within.html


Now here is the Jscript nicely formatted by the CRM 2011 SOAP formatter. Available at: http://crm2011soap.codeplex.com/

Now in Jscript:

if (typeof (SDK) == "undefined")
   { 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.
       SDK.SAMPLES = {
           _getServerUrl: function () {
               ///<summary>
               /// Returns the URL for the SOAP endpoint using the context information available in the form
               /// or HTML Web resource.
               ///</summary>
               var OrgServicePath = "/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 + OrgServicePath;
               }, 
           DisassociateRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:DisassociateRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
               requestMain += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>Target</b:key>";
               requestMain += "            <b:value i:type=\"a:EntityReference\">";
               requestMain += "              <a:Id>a6951d47-fb71-e011-882e-1cc1def17774</a:Id>";
               requestMain += "              <a:LogicalName>account</a:LogicalName>";
               requestMain += "              <a:Name i:nil=\"true\" />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>Relationship</b:key>";
               requestMain += "            <b:value i:type=\"a:Relationship\">";
               requestMain += "              <a:PrimaryEntityRole i:nil=\"true\" />";
               requestMain += "              <a:SchemaName>contact_customer_accounts</a:SchemaName>";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>RelatedEntities</b:key>";
               requestMain += "            <b:value i:type=\"a:EntityReferenceCollection\">";
               requestMain += "              <a:EntityReference>";
               requestMain += "                <a:Id>C7EE81A3-0572-E011-882E-1CC1DEF17774</a:Id>";
               requestMain += "                <a:LogicalName>contact</a:LogicalName>";
               requestMain += "                <a:Name i:nil=\"true\" />";
               requestMain += "              </a:EntityReference>";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>Disassociate</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.SAMPLES._getServerUrl(), 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");
               var successCallback = null;
               var errorCallback = null;
               req.onreadystatechange = function () { SDK.SAMPLES.DisassociateResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       DisassociateResponse: function (req, successCallback, errorCallback) {
               ///<summary>
               /// Recieves the assign response
               ///</summary>
               ///<param name="req" Type="XMLHttpRequest">
               /// The XMLHttpRequest response
               ///</param>
               ///<param name="successCallback" Type="Function">
               /// The function to perform when an successfult response is returned.
               /// For this message no data is returned so a success callback is not really necessary.
               ///</param>
               ///<param name="errorCallback" Type="Function">
               /// The function to perform when an error is returned.
               /// This function accepts a JScript error returned by the _getError function
               ///</param>
               if (req.readyState == 4) {
               if (req.status == 200) {
               if (successCallback != null)
               { successCallback(); }
               }
               else {
                   errorCallback(SDK.SAMPLES._getError(req.responseXML));
               }
           }
       },
       _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 = "Unknown Error (Unable to parse the fault)";
           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 new Error(errorMessage);
     },
 __namespace: true
};




To understand how to parse the response please review my post on using the DOM parser.
Now you can call the SDK.SAMPLES.DisassociateRequest function from your form jscript handler.  
Thats all there is to it!

I hope this helps!

Wednesday, May 11, 2011

How to: Use Associate Requests to Associate Entities Using Jscript and .NET in Microsoft Dynamics CRM

This illustration shows you how to associate two entities in Microsoft Dynamics CRM 2011 using the associate request against a known relationship.   This example will be given in SOAP (JScript) and in C# (.NET) with the Associate message against the CRM 2011 organization service.  In this example we are simply associating a contact to an account as it's parent customer using the existing "contact_customer_accounts" relationship in CRM.


You can find the relationship schema name to use in the request by going to settings - customization - your entity - relationships.  Here is an example of where to find it.


Ok, here is what the calls look like!
First in C#:

AssociateRequest areq = new AssociateRequest();

         //Target is the entity that you are associating your entities to.
         areq.Target = new EntityReference("account", new Guid("28B942AE-0B70-E011-8DD8-1CC1DEE8EA59"));

         //RelatedEntities are the entities you are associating to your target (can be more than 1)
         areq.RelatedEntities = new EntityReferenceCollection();
         areq.RelatedEntities.Add(new EntityReference("contact", new Guid("5AC04904-D57B-E011-941A-1CC1DEE8EA59")));

         //The relationship schema name in CRM you are using to associate the entities. 
         //found in settings - customization - entity - relationships
         areq.Relationship = new Relationship("contact_customer_accounts");

         //execute the request
         service.Execute(areq);

If you need help instantiating a service object in .NET check out this post:
http://mileyja.blogspot.com/2011/04/instantiating-service-object-within.html


Now here is the Jscript nicely formatted by the CRM 2011 SOAP formatter. Available at: http://crm2011soap.codeplex.com/

Now in Jscript:

if (typeof (SDK) == "undefined")
   { 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.
       SDK.SAMPLES = {
           _getServerUrl: function () {
               ///<summary>
               /// Returns the URL for the SOAP endpoint using the context information available in the form
               /// or HTML Web resource.
               ///</summary>
               var OrgServicePath = "/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 + OrgServicePath;
               }, 
           AssociateRequestRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:AssociateRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
               requestMain += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>Target</b:key>";
               requestMain += "            <b:value i:type=\"a:EntityReference\">";
               requestMain += "              <a:Id>28b942ae-0b70-e011-8dd8-1cc1dee8ea59</a:Id>";
               requestMain += "              <a:LogicalName>account</a:LogicalName>";
               requestMain += "              <a:Name i:nil=\"true\" />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>Relationship</b:key>";
               requestMain += "            <b:value i:type=\"a:Relationship\">";
               requestMain += "              <a:PrimaryEntityRole i:nil=\"true\" />";
               requestMain += "              <a:SchemaName>contact_customer_accounts</a:SchemaName>";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>RelatedEntities</b:key>";
               requestMain += "            <b:value i:type=\"a:EntityReferenceCollection\">";
               requestMain += "              <a:EntityReference>";
               requestMain += "                <a:Id>5ac04904-d57b-e011-941a-1cc1dee8ea59</a:Id>";
               requestMain += "                <a:LogicalName>contact</a:LogicalName>";
               requestMain += "                <a:Name i:nil=\"true\" />";
               requestMain += "              </a:EntityReference>";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>Associate</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.SAMPLES._getServerUrl(), 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");
               var successCallback = null;
               var errorCallback = null;
               req.onreadystatechange = function () { SDK.SAMPLES.AssociateRequestResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       AssociateRequestResponse: function (req, successCallback, errorCallback) {
               ///<summary>
               /// Recieves the assign response
               ///</summary>
               ///<param name="req" Type="XMLHttpRequest">
               /// The XMLHttpRequest response
               ///</param>
               ///<param name="successCallback" Type="Function">
               /// The function to perform when an successfult response is returned.
               /// For this message no data is returned so a success callback is not really necessary.
               ///</param>
               ///<param name="errorCallback" Type="Function">
               /// The function to perform when an error is returned.
               /// This function accepts a JScript error returned by the _getError function
               ///</param>
               if (req.readyState == 4) {
               if (req.status == 200) {
               if (successCallback != null)
               { successCallback(); }
               }
               else {
                   errorCallback(SDK.SAMPLES._getError(req.responseXML));
               }
           }
       },
       _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 = "Unknown Error (Unable to parse the fault)";
           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 new Error(errorMessage);
     },
 __namespace: true
};




To understand how to parse the response please review my post on using the DOM parser.
Now you can call the SDK.SAMPLES.AssociateRequestRequest function from your form jscript handler.  Yes I realize it says request twice, I made a typo in the Soap Formatter tool :)
Thats all there is to it!

I hope this helps!

Tuesday, May 10, 2011

How to: Update an Entity Attribute Using Jscript or .NET Using the Microsoft Dynamics CRM 2011 SDK

This illustration shows you how to update an attribute for an entity using SOAP (JScript) or C# (.NET) with the UpdateAttribute message against the CRM 2011 organization service.  In this example we are just changing the max length to something other than it's default of 100.
First in C#:

StringAttributeMetadata stringAttribute = new StringAttributeMetadata
         {
             // Set base properties
             SchemaName = "new_test1",
             LogicalName= "new_test1",
             DisplayName = new Label("Sample String", 1033),
             RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.None),
             Description = new Label("String Attribute", 1033),
             // Set extended properties
             MaxLength = 50
         };


         // Update an attribute retrieved via UpdateAttributeRequest
         UpdateAttributeRequest updateRequest = new UpdateAttributeRequest
         {
             Attribute = stringAttribute,
             EntityName = Contact.EntityLogicalName,     
             MergeLabels = false
         };

         // Execute the request.
         service.Execute(updateRequest);

If you need help instantiating a service object in .NET check out this post:
http://mileyja.blogspot.com/2011/04/instantiating-service-object-within.html

I also recommend reviewing this article that lays out how to format up the metadata objects for just about any type of attribute out there.  It will help a lot if you want to understand how to update anything besides a string attribute.
http://msdn.microsoft.com/en-us/library/microsoft.xrm.sdk.messages.createattributerequest.aspx

Now here is the Jscript nicely formatted by the CRM 2011 SOAP formatter. Available at: http://crm2011soap.codeplex.com/

Now in Jscript:

if (typeof (SDK) == "undefined")
   { 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.
       SDK.SAMPLES = {
           _getServerUrl: function () {
               ///<summary>
               /// Returns the URL for the SOAP endpoint using the context information available in the form
               /// or HTML Web resource.
               ///</summary>
               var OrgServicePath = "/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 + OrgServicePath;
               }, 
           UpdateAttributeRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:UpdateAttributeRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
               requestMain += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>Attribute</b:key>";
               requestMain += "            <b:value i:type=\"c:StringAttributeMetadata\" xmlns:c=\"http://schemas.microsoft.com/xrm/2011/Metadata\">";
               requestMain += "              <c:MetadataId i:nil=\"true\" />";
               requestMain += "              <c:AttributeOf i:nil=\"true\" />";
               requestMain += "              <c:AttributeType>String</c:AttributeType>";
               requestMain += "              <c:CanBeSecuredForCreate i:nil=\"true\" />";
               requestMain += "              <c:CanBeSecuredForRead i:nil=\"true\" />";
               requestMain += "              <c:CanBeSecuredForUpdate i:nil=\"true\" />";
               requestMain += "              <c:CanModifyAdditionalSettings i:nil=\"true\" />";
               requestMain += "              <c:ColumnNumber i:nil=\"true\" />";
               requestMain += "              <c:DeprecatedVersion i:nil=\"true\" />";
               requestMain += "              <c:Description>";
               requestMain += "                <a:LocalizedLabels>";
               requestMain += "                  <a:LocalizedLabel>";
               requestMain += "                    <a:IsManaged i:nil=\"true\" />";
               requestMain += "                    <a:Label>String Attribute</a:Label>";
               requestMain += "                    <a:LanguageCode>1033</a:LanguageCode>";
               requestMain += "                  </a:LocalizedLabel>";
               requestMain += "                </a:LocalizedLabels>";
               requestMain += "                <a:UserLocalizedLabel i:nil=\"true\" />";
               requestMain += "              </c:Description>";
               requestMain += "              <c:DisplayName>";
               requestMain += "                <a:LocalizedLabels>";
               requestMain += "                  <a:LocalizedLabel>";
               requestMain += "                    <a:IsManaged i:nil=\"true\" />";
               requestMain += "                    <a:Label>Sample String</a:Label>";
               requestMain += "                    <a:LanguageCode>1033</a:LanguageCode>";
               requestMain += "                  </a:LocalizedLabel>";
               requestMain += "                </a:LocalizedLabels>";
               requestMain += "                <a:UserLocalizedLabel i:nil=\"true\" />";
               requestMain += "              </c:DisplayName>";
               requestMain += "              <c:EntityLogicalName i:nil=\"true\" />";
               requestMain += "              <c:IsAuditEnabled i:nil=\"true\" />";
               requestMain += "              <c:IsCustomAttribute i:nil=\"true\" />";
               requestMain += "              <c:IsCustomizable i:nil=\"true\" />";
               requestMain += "              <c:IsManaged i:nil=\"true\" />";
               requestMain += "              <c:IsPrimaryId i:nil=\"true\" />";
               requestMain += "              <c:IsPrimaryName i:nil=\"true\" />";
               requestMain += "              <c:IsRenameable i:nil=\"true\" />";
               requestMain += "              <c:IsSecured i:nil=\"true\" />";
               requestMain += "              <c:IsValidForAdvancedFind i:nil=\"true\" />";
               requestMain += "              <c:IsValidForCreate i:nil=\"true\" />";
               requestMain += "              <c:IsValidForRead i:nil=\"true\" />";
               requestMain += "              <c:IsValidForUpdate i:nil=\"true\" />";
               requestMain += "              <c:LinkedAttributeId i:nil=\"true\" />";
               requestMain += "              <c:LogicalName>new_test1</c:LogicalName>";
               requestMain += "              <c:RequiredLevel>";
               requestMain += "                <a:CanBeChanged>true</a:CanBeChanged>";
               requestMain += "                <a:ManagedPropertyLogicalName i:nil=\"true\" />";
               requestMain += "                <a:Value>None</a:Value>";
               requestMain += "              </c:RequiredLevel>";
               requestMain += "              <c:SchemaName>new_test1</c:SchemaName>";
               requestMain += "              <c:Format i:nil=\"true\" />";
               requestMain += "              <c:ImeMode i:nil=\"true\" />";
               requestMain += "              <c:MaxLength>50</c:MaxLength>";
               requestMain += "              <c:YomiOf i:nil=\"true\" />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>EntityName</b:key>";
               requestMain += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">contact</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>MergeLabels</b:key>";
               requestMain += "            <b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">false</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>UpdateAttribute</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.SAMPLES._getServerUrl(), 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");
               var successCallback = null;
               var errorCallback = null;
               req.onreadystatechange = function () { SDK.SAMPLES.UpdateAttributeResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       UpdateAttributeResponse: function (req, successCallback, errorCallback) {
               ///<summary>
               /// Recieves the assign response
               ///</summary>
               ///<param name="req" Type="XMLHttpRequest">
               /// The XMLHttpRequest response
               ///</param>
               ///<param name="successCallback" Type="Function">
               /// The function to perform when an successfult response is returned.
               /// For this message no data is returned so a success callback is not really necessary.
               ///</param>
               ///<param name="errorCallback" Type="Function">
               /// The function to perform when an error is returned.
               /// This function accepts a JScript error returned by the _getError function
               ///</param>
               if (req.readyState == 4) {
               if (req.status == 200) {
               if (successCallback != null)
               { successCallback(); }
               }
               else {
                   errorCallback(SDK.SAMPLES._getError(req.responseXML));
               }
           }
       },
       _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 = "Unknown Error (Unable to parse the fault)";
           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 new Error(errorMessage);
     },
 __namespace: true
};




To understand how to parse the response please review my post on using the DOM parser.
Now you can call the SDK.SAMPLES.UpdateAttributeRequest function from your form jscript handler.
Thats all there is to it!

I hope this helps!

Monday, May 9, 2011

How to: Retrieve the Metadata for an Entity Using Jscript or .NET Using the Microsoft Dynamics CRM 2011 SDK

This illustration shows you how to retrieve metadata for an entity using SOAP (JScript) or C# (.NET) with the RetrieveEntity message against the CRM 2011 organization service.
First in C#:

     RetrieveEntityRequest retrieveBankAccountEntityRequest = new RetrieveEntityRequest
         {
             EntityFilters = EntityFilters.All,
             LogicalName = "account"
         };
         RetrieveEntityResponse retrieveBankAccountEntityResponse = (RetrieveEntityResponse)service.Execute(retrieveBankAccountEntityRequest);

         string entityname = retrieveBankAccountEntityResponse.EntityMetadata.ManyToManyRelationships[0].IntersectEntityName;


If you need help instantiating a service object in .NET check out this post:
http://mileyja.blogspot.com/2011/04/instantiating-service-object-within.html

The last line there shows how to look into a relationships collection by examining the response object.
It is important to note that you can filter on the type of entity metadata you want returned since the returned XML document will be very large if you choose EntityFilters.All as shown above.  Your choices are All, Attributes, Default, Entity, Privileges, and Relationships.


Now here is the Jscript nicely formatted by the CRM 2011 SOAP formatter. Available at: http://crm2011soap.codeplex.com/

This example is asynchronous, if you want to learn how to make JScript SOAP calls synchronously please visit this posthttp://mileyja.blogspot.com/2011/07/using-jscript-to-access-soap-web.html

Now in Jscript:


if (typeof (SDK) == "undefined")
   { 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.
       SDK.SAMPLES = {
           _getServerUrl: function () {
               ///<summary>
               /// Returns the URL for the SOAP endpoint using the context information available in the form
               /// or HTML Web resource.
               ///</summary>
               var OrgServicePath = "/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 + OrgServicePath;
               }, 
           RetrieveMetadataRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:RetrieveEntityRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
               requestMain += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>EntityFilters</b:key>";
               requestMain += "            <b:value i:type=\"c:EntityFilters\" xmlns:c=\"http://schemas.microsoft.com/xrm/2011/Metadata\">Entity Attributes Privileges Relationships</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>MetadataId</b:key>";
               requestMain += "            <b:value i:type=\"c:guid\" xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/\">00000000-0000-0000-0000-000000000000</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>RetrieveAsIfPublished</b:key>";
               requestMain += "            <b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">false</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>LogicalName</b:key>";
               requestMain += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">account</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>RetrieveEntity</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.SAMPLES._getServerUrl(), 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");
               var successCallback = null;
               var errorCallback = null;
               req.onreadystatechange = function () { SDK.SAMPLES.RetrieveMetadataResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       RetrieveMetadataResponse: function (req, successCallback, errorCallback) {
               ///<summary>
               /// Recieves the assign response
               ///</summary>
               ///<param name="req" Type="XMLHttpRequest">
               /// The XMLHttpRequest response
               ///</param>
               ///<param name="successCallback" Type="Function">
               /// The function to perform when an successfult response is returned.
               /// For this message no data is returned so a success callback is not really necessary.
               ///</param>
               ///<param name="errorCallback" Type="Function">
               /// The function to perform when an error is returned.
               /// This function accepts a JScript error returned by the _getError function
               ///</param>
               if (req.readyState == 4) {
               if (req.status == 200) {
               if (successCallback != null)
               { successCallback(); }
               }
               else {
                   errorCallback(SDK.SAMPLES._getError(req.responseXML));
               }
           }
       },
       _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 = "Unknown Error (Unable to parse the fault)";
           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 new Error(errorMessage);
     },
 __namespace: true
};




To understand how to parse the response please review my post on using the DOM parser.
Now you can call the SDK.SAMPLES.RetrieveMetadataRequest function from your form jscript handler.
Thats all there is to it!

I hope this helps!