Tuesday, June 14, 2011

Retrieve Entity in Microsoft Dynamics CRM 2011 From SIlverlight Using RetrieveRequest

This tutorial will show you how to retrieve an entity record in Microsoft Dynamics CRM 2011 using C# in Silverlight with RetrieveRequest.

IMPORTANT: First things first.  You have to set up your Silverlight app to make a web services connection to CRM.   The best tutorial I have found for this is located here in the MSDN:
http://msdn.microsoft.com/en-us/library/gg594452.aspx
After you finish that setup you are ready to implement the rest of this post.

Now once that is done you can retrieve a record in CRM using the following syntax.  In the following example I am retrieving a record of type "new_testdata", which is a custom entity I have created.

Here is the call in C#:

private void RetrieveEntity()
{
    try
    {


       EntityReference refEntity = new EntityReference();
       //the guid of the entity you want to retrieve
       refEntity.Id = new Guid("1C49A4FD-0B96-E011-8D5C-1CC1DEE8EA49");
       //the name of the entity type you want to retrieve
       refEntity.LogicalName = "new_testdata";

        //define request type
        OrganizationRequest request = new OrganizationRequest() { RequestName = "Retrieve" };
        request["Target"] = refEntity;
        ColumnSet columns = new ColumnSet();

        //put comma delimited list of attributes you want to retrieve here
        columns.Columns =  new System.Collections.ObjectModel.ObservableCollection<string>(new string[] { "new_name", "new_otherattribute" });
        request["ColumnSet"] = columns;

        //the silverlight utility class is created during the setup process laid out at http://msdn.microsoft.com/en-us/library/gg594452.aspx
        IOrganizationService service = SilverlightUtility.GetSoapService();

        //send the async request and specify it's callback
        service.BeginExecute(request, new AsyncCallback(RetrieveEntityResult), service);
    }
    catch (Exception ex)
    {
        this.ReportError(ex);
    }
}

Now here is the call-back code:

private void RetrieveEntityResult(IAsyncResult result)
{
    try
    {
        OrganizationResponse Response = ((IOrganizationService)result.AsyncState).EndExecute(result);
        Entity e = (Entity)Response["Entity"];
        //strEntityName is a global variable I am using in my program so I can call it in the        //dispatcher method below        
        strEntityName = "entity name = " + e.GetAttributeValue<string>("new_name");

        //call a method that does something in the main UI thread (update the UI with the results of the call) 
        //from method named "method" in this case
        this.Dispatcher.BeginInvoke(method);
   


    }
    catch (Exception ex)
    {
        this.ReportError(ex);
    }
}

You will need to use the this.Dispatcher.BeginInvoke to call a method to act on the UI or perform actions in the main thread.  I did not include the dispatcher invoked method called "method" in this case because it could do anything in the UI.  In my case I will tell you though it is setting a TextBox.Text property to the value of the global variable "strEntityName".

You will notice that the biggest change in thinking and syntax from standard CRM SDK work will be that you have to specify your request and response properties as strings explicitly in code.

I hope this helps!

-

Monday, June 13, 2011

Execute a Workflow Using .NET or Jscript in Microsoft Dynamics CRM 2011 With ExecuteWorkflowRequest

This illustration demonstrates how to execute a workflow using SOAP (JScript) or C# (.NET) with the ExecuteWorkflowRequest message against the Microsoft Dynamics CRM 2011 organization service.

First in C#:

ExecuteWorkflowRequest req = new ExecuteWorkflowRequest();
//specify the guid of the workflow
req.WorkflowId = new Guid("D009C04F-F826-4B3B-90CD-209581CFC2FF");
//specify the guid of the related entity instance
req.EntityId = new Guid("A46FA1C1-E38D-E011-86BA-1CC1DEE8EA49");
ExecuteWorkflowResponse resp = (ExecuteWorkflowResponse)slos.Execute(req);

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;
               }, 
           ExecuteWorkflowRequest: 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:ExecuteWorkflowRequest\" 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>EntityId</c:key>";
               requestMain += "            <c:value i:type=\"d:guid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/\">a46fa1c1-e38d-e011-86ba-1cc1dee8ea49</c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>WorkflowId</c:key>";
               requestMain += "            <c:value i:type=\"d:guid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/\">d009c04f-f826-4b3b-90cd-209581cfc2ff</c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>ExecuteWorkflow</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.ExecuteWorkflowResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       ExecuteWorkflowResponse: 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.ExecuteWorkflowRequest function from your form jscript handler.
Thats all there is to it!

I hope this helps!

Thursday, June 9, 2011

Create Entity in Microsoft Dynamics CRM 2011 from SIlverlight

This tutorial will show you how to create an entity record in Microsoft Dynamics CRM 2011 using C# in Silverlight.

First things first.  You have to set up your Silverlight app to make a web services connection to CRM.   The best tutorial I have found for this is located here in the MSDN:
http://msdn.microsoft.com/en-us/library/gg594452.aspx

Now once that is done you can create a record in CRM using the following syntax.  In the following example I am creating a record of type "new_testdata", which is a custom entity I have created.

Here is the call in C#:

//note that you need to specify the type of request here
OrganizationRequest request = new OrganizationRequest() { RequestName = "Create" };
Entity entity = new Entity();
entity.LogicalName = "new_testdata";

//One of the biggest things you deal with in SilverLight is the way you work with properties and Attributes
CrmSdk.KeyValuePair<string, object> attName = new CrmSdk.KeyValuePair<string, object>();
attName.Key = "new_name";
attName.Value = "Data - " + DateTime.Now.ToString();
entity.Attributes = new AttributeCollection();
entity.Attributes.Add(attName);

//request properties need to be explicitly named as strings
request["Target"] = entity; 

IOrganizationService service = SilverlightUtility.GetSoapService();

//depending on how you do things your calls will most likely be asynchronous
service.BeginExecute(request, new AsyncCallback(CrmCreate_Callback), service);

Since this is an asynchronous call my callback method "CrmCreate_Callback" that returns the entities Guid from the response looks like this:


private void CrmCreate_Callback(IAsyncResult result)
{
    try
    {
        OrganizationResponse response = ((IOrganizationService)result.AsyncState).EndExecute(result);
        Guid results = (Guid)response["id"];
        
        this.ReportMessage("id: " + results.ToString());
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

You will notice that the biggest change in thinking and syntax will be that you have to specify your request and response properties as strings explicitly in code.

Really though once you understand the differences in working with the two concepts it really isn't a tough nut to crack.

Wednesday, June 8, 2011

We Welcome Elenora Pauline Miley: The Newest Addition to the Family!!!

Elenora was born at 4:51 am and is 6 lb 6 oz.  She is 18.5 inches long.

Kristina woke me up at 3:30 this morning and said her water broke.  She got dressed and drove in while I stayed behind and waited for the babysitter to arrive to watch Adelyn.   By the time I got to the hospital 4:45, I walked in about 2 minutes before the baby was born.  The whole thing happened so fast.


-

Tuesday, June 7, 2011

Merge Entity Records In Microsoft Dynamics CRM 2011 in Jscript or .NET

This illustration shows how to merge entity records of the same type in Microsoft Dynamics CRM 2011 in code in jscript and also C#  using the MergeRequest.   This example will be given in SOAP (JScript) and in C# (.NET).

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

//first get entity you want to merge to pull all of it's attributes so they get merged to the dominate entity
         RetrieveRequest retrievereq = new RetrieveRequest();

         //you must specify each column explicitly for this call because some are invalid.  
         //new ColumnSet(true) will fail here
         string[] updatecolumns = { "address1_city" };

         retrievereq.ColumnSet = new ColumnSet(updatecolumns);
         retrievereq.Target = new EntityReference("account", new Guid("DC2C414E-0D91-E011-8D64-1CC1DE7955DB"));
         RetrieveResponse retrieveresp = (RetrieveResponse)service.Execute(retrievereq);

         MergeRequest req = new MergeRequest();

         //dominate entity for merge
         req.Target = new EntityReference("account", new Guid("A46FA1C1-E38D-E011-86BA-1CC1DEE8EA49"));

         //assign subordinate entity data from retrieve request
         req.UpdateContent = retrieveresp.Entity;

         //subordinate entity for merge
         req.SubordinateId = new Guid("DC2C414E-0D91-E011-8D64-1CC1DE7955DB");

         MergeResponse resp = (MergeResponse)service.Execute(req);

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/


If you need help with the retrieve request portion in jscript please review this post:



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;
               }, 
           MergeRequest: 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:MergeRequest\" 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>a46fa1c1-e38d-e011-86ba-1cc1dee8ea49</a:Id>";
               requestMain += "              <a:LogicalName>account</a:LogicalName>";
               requestMain += "              <a:Name i:nil=\"true\" />";
               requestMain += "            </c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>SubordinateId</c:key>";
               requestMain += "            <c:value i:type=\"d:guid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/\">dc2c414e-0d91-e011-8d64-1cc1de7955db</c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>UpdateContent</c:key>";
               requestMain += "            <c:value i:type=\"a:Entity\">";
               requestMain += "              <a:Attributes>";
               requestMain += "                <a:KeyValuePairOfstringanyType>";
               requestMain += "                  <c:key>address1_city</c:key>";
               requestMain += "                  <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">Richfield 3</c:value>";
               requestMain += "                </a:KeyValuePairOfstringanyType>";
               requestMain += "                <a:KeyValuePairOfstringanyType>";
               requestMain += "                  <c:key>accountid</c:key>";
               requestMain += "                  <c:value i:type=\"d:guid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/\">dc2c414e-0d91-e011-8d64-1cc1de7955db</c:value>";
               requestMain += "                </a:KeyValuePairOfstringanyType>";
               requestMain += "              </a:Attributes>";
               requestMain += "              <a:EntityState i:nil=\"true\" />";
               requestMain += "              <a:FormattedValues />";
               requestMain += "              <a:Id>dc2c414e-0d91-e011-8d64-1cc1de7955db</a:Id>";
               requestMain += "              <a:LogicalName>account</a:LogicalName>";
               requestMain += "              <a:RelatedEntities />";
               requestMain += "            </c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <c:key>PerformParentingChecks</c:key>";
               requestMain += "            <c:value i:type=\"d:boolean\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">false</c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>Merge</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.MergeResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       MergeResponse: 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.MergeRequest function from your form jscript handler.
Thats all there is to it!

I hope this helps!

Check Out What's New in the Microsoft Dynamics CRM 2011 SDK 5.0.4

Microsoft Dynamics CRM 2011 SDK version 5.0.4 has just been released.

You can download it here:
http://www.microsoft.com/downloads/en/confirmation.aspx?FamilyID=420f0f05-c226-4194-b7e1-f23ceaa83b69

The new stuff is below:

General

  •  Updated portal front-side editing scripts to redirect user to parent page on deletion of current page, rather than redirecting to the site root page.
  • Updated portal front-side editing scripts to accept any loaded version of jQuery, rather than performing a version check.
  • Microsoft.Xrm.Client.OrganizationServiceContextExtensions: Added missing relationship methods. Several of the early bound based relationship accessor methods were left unimplemented in the OrganizationServiceContextExtensions class (others were implemented correctly). These are convenience methods that allow relationships to be specified using static code-gen properties rather than using a late bound Relationship object, which requires a relationship schema name to be provided. The new methods are AttachLink, DetachLink, IsDeleted, AddLink, and DeleteLink.
  • Microsoft.Xrm.Portal.Web.UI.WebControls.CrmEntityFormView: Added public method InsertItem, to trigger form insert event from an external control.

ConsoleAppWalkthrough:
  • Updated configuration with required service context configuration section.
  • Updated SDK reference paths to match directory structure of SDK distribution.
  • Removed unnecessary Microsoft.ServiceBus.dll reference.
PluginWalkthrough:
  • Updated SDK reference paths to match directory structure of SDK distribution.
WebApp Walkthrough:
  • Updated SDK reference paths to match directory structure of SDK distribution.
  • Removed unnecessary Microsoft.ServiceBus.dll reference.
  • Updated CrmEntityFormView example to use a system-default view name, rather than a custom one.

Monday, June 6, 2011

Get Exchange Rate From Microsoft Dynamics CRM 2011 Using Jscript or .NET

This illustration shows how to get exchange rates from Microsoft Dynamics CRM 2011 in code in jscript and also C#  using the RetrieveExchangeRateRequest.   This example will be given in SOAP (JScript) and in C# (.NET).

NOTE: If you came here looking for a way to update currency exchange rates programatically from a web service through .NET please refer to this post:
http://mileyja.blogspot.com/2011/05/microsoft-dynamics-crm-2011-currency.html

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

RetrieveExchangeRateRequest req = new RetrieveExchangeRateRequest();

         //set the Guid of the currency to get the exchange rate for.
         req.TransactionCurrencyId = new Guid("A615DE24-D27C-E011-8D68-1CC1DEE89A74");

         RetrieveExchangeRateResponse resp = (RetrieveExchangeRateResponse)service.Execute(req);

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;
               }, 
           RetrieveExchangeRateRequest: 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:RetrieveExchangeRateRequest\" 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>TransactionCurrencyId</c:key>";
               requestMain += "            <c:value i:type=\"d:guid\" xmlns:d=\"http://schemas.microsoft.com/2003/10/Serialization/\">a615de24-d27c-e011-8d68-1cc1dee89a74</c:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>RetrieveExchangeRate</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.RetrieveExchangeRateResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       RetrieveExchangeRateResponse: 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(); }
               alert(req.responseXML.xml);
               }
               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.RetrieveExchangeRateRequest function from your form jscript handler.
Thats all there is to it!

I hope this helps!