Wednesday, March 30, 2011

Microsoft Dynamics CRM 2011: Parsing Jscript with DOM Parser

UPDATE:  please review post here: http://mileyja.blogspot.com/2013/06/format-of-soap-responses-to-microsoft.html as format of the returned response has changed!


Hey gang,

I just wanted to talk through some of the logistics of parsing XML responses when using the CRM 2011 SOAP endpoint in Jscript.

Let's start by examining a piece of XML (that's cut off for the sake length that represents a webresource entity as it is returned to us via a RetreiveMultiple call. For more info on making RetrieveMultiple Call please review this post: http://mileyja.blogspot.com/2011/03/crm-2011-retrievemultiple-calls-in.html

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Body>
    <ExecuteResponse xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <ExecuteResult i:type="a:RetrieveMultipleResponse" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts">
        <a:ResponseName>RetrieveMultiple</a:ResponseName>
        <a:Results xmlns:b="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
          <a:KeyValuePairOfstringanyType>
            <b:key>EntityCollection</b:key>
            <b:value i:type="a:EntityCollection">
              <a:Entities>
                <a:Entity>
                  <a:Attributes>
                    <a:KeyValuePairOfstringanyType>
                      <b:key>webresourceidunique</b:key>
                      <b:value i:type="c:guid" xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/">340c69f7-3fc7-40e2-ae20-fbab9470d9d4</b:value>
                    </a:KeyValuePairOfstringanyType>
                    <a:KeyValuePairOfstringanyType>
                      <b:key>organizationid</b:key>
                      <b:value i:type="a:EntityReference">
                        <a:Id>a2fe1552-7977-4d92-a730-05eeb167afb5</a:Id>
                        <a:LogicalName>organization</a:LogicalName>
                        <a:Name>crm</a:Name>
                      </b:value>
                    </a:KeyValuePairOfstringanyType>
                    <a:KeyValuePairOfstringanyType>
                      <b:key>displayname</b:key>
                      <b:value i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">new_webresourceiframe</b:value>
                    </a:KeyValuePairOfstringanyType>
                    <a:KeyValuePairOfstringanyType>
                      <b:key>iscustomizable</b:key>
                      <b:value i:type="a:BooleanManagedProperty">
                        <a:CanBeChanged>true</a:CanBeChanged>
                        <a:ManagedPropertyLogicalName>iscustomizableanddeletable</a:ManagedPropertyLogicalName>
                        <a:Value>true</a:Value>
                      </b:value>
                    </a:KeyValuePairOfstringanyType>
                    <a:KeyValuePairOfstringanyType>
                      <b:key>solutionid</b:key>
                      <b:value i:type="c:guid" xmlns:c="http://schemas.microsoft.com/2003/10/Serialization/">fd140aae-4df4-11dd-bd17-0019b9312238</b:value>
                    </a:KeyValuePairOfstringanyType>
                    <a:KeyValuePairOfstringanyType>
                      <b:key>languagecode</b:key>
                      <b:value i:type="c:int" xmlns:c="http://www.w3.org/2001/XMLSchema">1033</b:value>
                    </a:KeyValuePairOfstringanyType>
                    <a:KeyValuePairOfstringanyType>
                      <b:key>modifiedon</b:key>
                      <b:value i:type="c:dateTime" xmlns:c="http://www.w3.org/2001/XMLSchema">2011-03-20T07:55:52Z</b:value>
                    </a:KeyValuePairOfstringanyType>
                    <a:KeyValuePairOfstringanyType>
                      <b:key>ismanaged</b:key>
                      <b:value i:type="c:boolean" xmlns:c="http://www.w3.org/2001/XMLSchema">false</b:value>
                    </a:KeyValuePairOfstringanyType>
                    <a:KeyValuePairOfstringanyType>
                      <b:key>createdby</b:key>
                      <b:value i:type="a:EntityReference">
                        <a:Id>81ed14d9-4441-e011-963a-080027ad5b6e</a:Id>
                        <a:LogicalName>systemuser</a:LogicalName>
                        <a:Name i:nil="true" />
                      </b:value>
                    </a:KeyValuePairOfstringanyType>
                    <a:KeyValuePairOfstringanyType>
                      <b:key>webresourcetype</b:key>
                      <b:value i:type="a:OptionSetValue">
                        <a:Value>1</a:Value>
                      </b:value>
                    </a:KeyValuePairOfstringanyType>
                    <a:KeyValuePairOfstringanyType>
                      <b:key>canbedeleted</b:key>
                      <b:value i:type="a:BooleanManagedProperty">
                        <a:CanBeChanged>true</a:CanBeChanged>
                        <a:ManagedPropertyLogicalName>canbedeleted</a:ManagedPropertyLogicalName>
                        <a:Value>true</a:Value>
                      </b:value>

Now let's look at how this might be parsed. In CRM 4.0 each attribute had it's own matching tag name so you could just search for the tag and grab the value using the DOM parsar. That is not the case here as each attribute is wrapped in a then the first child node contains the name of the attribute. The following child nodes contain the data associated with the attribute. For an ntext or a number field you will only have two total subkeys, one for the attribute name and one for the value.

This means we can parse out most simple types above using a function like this:


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);
      }
      
   } 
}

Just pass in the xml from the response containing your entity and your attribute you are looking for.

This function iterates through the attributes by grabbing a collection of attributes and walking through them, searches for our "attributename" in the first child node, and if it's found, alerts our second child node that represents the value for the attribute.

You will notice that in the XML that there are exceptions to this rule. When it comes to a lookup field (called an "entityreference") type above you have info representing ID (GUID ID Value), Logical name (Type of entity), and value(usually the name attribute of that entity). You also have attributes of type "BooleanManagedProperty" where you have a "CanBeChanged" child node in between the name of the attribute an the value. I am sure there are more examples but here is how to tackle this.

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. In this case I am going to add a watch on "x[i]" because it represents my attributes from our line, x=xmlDoc.getElementsByTagName("a:KeyValuePairOfstringanyType"); as I step through.

Now, if I step into the code in Visual Studio and add my watch I can see all the attributes and 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!

Retrieve Web Resource Contents in Microsoft CRM 2011 in Jscript or .NET

I already showed everyone how to update web resource contents dynamically in Jscript and in C#, now how about retrieving them.  I saw this question come across the forum and figured I would address it more directly.

Here is what it involves:

1. perform a RetrieveMultiple call to pull back your web resource entity.
2. Decode the "content" property from base-64 to a string.

First in C#:  I am using the SoapLogger solution to do this because it makes figuring out the jscript for this (which I will show you in a minute) much easier.

 SoapLoggerOrganizationService slos = new SoapLoggerOrganizationService(serverConfig.OrganizationUri, service, output);

      //Add the code you want to test here:
      // You must use the SoapLoggerOrganizationService 'slos' proxy rather than the IOrganizationService proxy you would normally use.


      RetrieveMultipleRequest rmr = new RetrieveMultipleRequest();
      RetrieveMultipleResponse resp = new RetrieveMultipleResponse();
         WebResource wb = new WebResource();
         
      QueryExpression query = new QueryExpression()
      {
          EntityName = "webresource",
          ColumnSet = new ColumnSet("content"),
          Criteria = new FilterExpression
          {
              FilterOperator = LogicalOperator.And,
              Conditions = 
                {
                    new ConditionExpression
                    {
                        AttributeName = "webresourceid",
                        Operator = ConditionOperator.Equal,
                        Values = { "ADFA33CB-7050-E011-9CF8-080027AD5B6E" }
                    }
                }
          }
      };

        rmr.Query = query;
        resp  = (RetrieveMultipleResponse)slos.Execute(rmr);
        wb =  (WebResource)resp.EntityCollection.Entities[0];

        byte[] b = Convert.FromBase64String(wb.Content);

        //**************************************
        //The string below will contain your HTML
        //**************************************
        string strHTML = System.Text.Encoding.UTF8.GetString(b);


Now, let's see it in Jscript. I formatted up the jscript for the retrievemultiple call using the CRM 2011 Jscript Soap Formatter Tool. It basically pulls back the response from the soap call and parses out the element we are looking for and alerts it to the screen.

function runme() {
    var guidWebResource = "ADFA33CB-7050-E011-9CF8-080027AD5B6E";
    SDK.SAMPLES.RetrieveWebResourceRequest(guidWebResource);
}

//is called by the soap response and parses the response, finds our "content" property and then alerts our content value
function parseResponse(responseXML) {

    
    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 =="content")
      {
         //we decode the base 64 contents and alert the HTML of the Iframe
          alert(decode64(x[i].childNodes[1].text));
      }
      
   } 
}
 
 function decode64(input) {
    var keyStr = "ABCDEFGHIJKLMNOP" +
               "QRSTUVWXYZabcdef" +
               "ghijklmnopqrstuv" +
               "wxyz0123456789+/" +
               "=";

    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;

    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
    var base64test = /[^A-Za-z0-9\+\/\=]/g;
    if (base64test.exec(input)) {
        alert("There were invalid base64 characters in the input text.\n" +
              "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
              "Expect errors in decoding.");
    }
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    do {
        enc1 = keyStr.indexOf(input.charAt(i++));
        enc2 = keyStr.indexOf(input.charAt(i++));
        enc3 = keyStr.indexOf(input.charAt(i++));
        enc4 = keyStr.indexOf(input.charAt(i++));

        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;

        output = output + String.fromCharCode(chr1);

        if (enc3 != 64) {
            output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
            output = output + String.fromCharCode(chr3);
        }

        chr1 = chr2 = chr3 = "";
        enc1 = enc2 = enc3 = enc4 = "";

    } while (i < input.length);

    return unescape(output);
}


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;
               }, 
           RetrieveWebResourceRequest: function (webResourceGuid) {
               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:RetrieveMultipleRequest\" 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>Query</b:key>";
               requestMain += "            <b:value i:type=\"a:QueryExpression\">";
               requestMain += "              <a:ColumnSet>";
               requestMain += "                <a:AllColumns>false</a:AllColumns>";
               requestMain += "                <a:Columns xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">";
               requestMain += "                  <c:string>content</c:string>";
               requestMain += "                </a:Columns>";
               requestMain += "              </a:ColumnSet>";
               requestMain += "              <a:Criteria>";
               requestMain += "                <a:Conditions>";
               requestMain += "                  <a:ConditionExpression>";
               requestMain += "                    <a:AttributeName>webresourceid</a:AttributeName>";
               requestMain += "                    <a:Operator>Equal</a:Operator>";
               requestMain += "                    <a:Values xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">";
               requestMain += "                      <c:anyType i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + webResourceGuid + "</c:anyType>";
               requestMain += "                    </a:Values>";
               requestMain += "                  </a:ConditionExpression>";
               requestMain += "                </a:Conditions>";
               requestMain += "                <a:FilterOperator>And</a:FilterOperator>";
               requestMain += "                <a:Filters />";
               requestMain += "              </a:Criteria>";
               requestMain += "              <a:Distinct>false</a:Distinct>";
               requestMain += "              <a:EntityName>webresource</a:EntityName>";
               requestMain += "              <a:LinkEntities />";
               requestMain += "              <a:Orders />";
               requestMain += "              <a:PageInfo>";
               requestMain += "                <a:Count>0</a:Count>";
               requestMain += "                <a:PageNumber>0</a:PageNumber>";
               requestMain += "                <a:PagingCookie i:nil=\"true\" />";
               requestMain += "                <a:ReturnTotalRecordCount>false</a:ReturnTotalRecordCount>";
               requestMain += "              </a:PageInfo>";
               requestMain += "              <a:NoLock>false</a:NoLock>";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>RetrieveMultiple</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.RetrieveWebResourceResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       RetrieveWebResourceResponse: 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) {
               
                  parseResponse(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
};


I hope this helps!

Friday, March 25, 2011

CRM 2011 and IE9 Support - Release Version Works Great!!

There has been a lot of activity in the CRM forums lately about whether or not Internet Explorer 9 is compatible with Microsoft Dynamics CRM 2011.   Here is the current answer as of 3/25/2011.

My answer that can be backed up by other sources that I shall post below: YES - For Release Version, but absolutely not for anything pre-release.


The official MSFT answer:  Not in Beta or pre-release, but can't find anything on release version yet.

Sources other than personal use:

http://social.microsoft.com/Forums/en/crm2011beta/thread/1b9dd45e-7f28-4e65-9f4b-ed887a4037b2

http://social.microsoft.com/Forums/en/crmdevelopment/thread/0025e3ee-f87b-47fc-b681-b20a0a2861e7

http://www.xrmservices.com/2011/03/crm-2011-online-and-internet-explorer-9.html

I have been using the release version now for a few days and I can say I haven't run into any problems yet with CRM 2011.   I have been performing customizations to forms and have even enabled script debugging and stopped on script breakpoints.  It just works great.

I hope this helps!

Wednesday, March 23, 2011

Set HTML Rendered Within IFrame in CRM 2011 in Jscript OnLoad Event

So yesterday's post covered how to update the contents of a web resource in C# and in Jscript using the SDK.  Now on to part 2.

Today I am going to build a little on the Jscript version of that concept to show you how to use this to determine the HTML rendered in an Iframe in the form OnLoad event. 

There isn't much more to it, here goes!

1.  Upload a blank or next to blank HTML page to act as a web resource placeholder that we will change in code and make note of the URL, we will use it in our Jscript.




Next, we need to modify yesterday's Jscript so that we are setting the Iframe source URL to the edited web resource in the appropriate place in the response after it is published.

I will re-paste the entire code here, make note of the publish response function of the entity and you will see where we are setting the Iframe source.  All you have to do is publish an event handler in the GUI that calls the runme function of this library after you swap our your specific web resource GUID.



function runme() {
    
    var guidWebResource = "ADFA33CB-7050-E011-9CF8-080027AD5B6E";

    var strContentHTML = "<html><body><h1>HELLO WORLD!!<h1></body</html>";
    var enc = encode64(strContentHTML);
    SDK.SAMPLES.UpdateWebResourceRequest(guidWebResource, enc);
    SDK.SAMPLES.PublishWebResourceRequest(guidWebResource);

 


}

function encode64(input) {
    var keyStr = "ABCDEFGHIJKLMNOP" +
               "QRSTUVWXYZabcdef" +
               "ghijklmnopqrstuv" +
               "wxyz0123456789+/" +
               "=";

    //input = escape(input);
    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;

    do {
        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);

        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }

        output = output +
           keyStr.charAt(enc1) +
           keyStr.charAt(enc2) +
           keyStr.charAt(enc3) +
           keyStr.charAt(enc4);
        chr1 = chr2 = chr3 = "";
        enc1 = enc2 = enc3 = enc4 = "";
    } while (i < input.length);

    return output;
}

function decode64(input) {
    var keyStr = "ABCDEFGHIJKLMNOP" +
               "QRSTUVWXYZabcdef" +
               "ghijklmnopqrstuv" +
               "wxyz0123456789+/" +
               "=";

    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;

    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
    var base64test = /[^A-Za-z0-9\+\/\=]/g;
    if (base64test.exec(input)) {
        alert("There were invalid base64 characters in the input text.\n" +
              "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
              "Expect errors in decoding.");
    }
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    do {
        enc1 = keyStr.indexOf(input.charAt(i++));
        enc2 = keyStr.indexOf(input.charAt(i++));
        enc3 = keyStr.indexOf(input.charAt(i++));
        enc4 = keyStr.indexOf(input.charAt(i++));

        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;

        output = output + String.fromCharCode(chr1);

        if (enc3 != 64) {
            output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
            output = output + String.fromCharCode(chr3);
        }

        chr1 = chr2 = chr3 = "";
        enc1 = enc2 = enc3 = enc4 = "";

    } while (i < input.length);

    return unescape(output);
}


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;
    },
    UpdateWebResourceRequest: function (guidWebResourceID, strEncodedContent) {
        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:UpdateRequest\" 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:Entity\">";
        requestMain += "              <a:Attributes>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>webresourceidunique</b:key>";
        requestMain += "                  <b:value i:type=\"c:guid\" xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/\">434e47dd-8cb5-427f-8e5f-72b7ed93dcf6</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>organizationid</b:key>";
        requestMain += "                  <b:value i:type=\"a:EntityReference\">";
        requestMain += "                    <a:Id>a2fe1552-7977-4d92-a730-05eeb167afb5</a:Id>";
        requestMain += "                    <a:LogicalName>organization</a:LogicalName>";
        requestMain += "                    <a:Name>crm</a:Name>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>displayname</b:key>";
        requestMain += "                  <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">new_webresourceiframe</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>iscustomizable</b:key>";
        requestMain += "                  <b:value i:type=\"a:BooleanManagedProperty\">";
        requestMain += "                    <a:CanBeChanged>true</a:CanBeChanged>";
        requestMain += "                    <a:ManagedPropertyLogicalName>iscustomizableanddeletable</a:ManagedPropertyLogicalName>";
        requestMain += "                    <a:Value>true</a:Value>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>solutionid</b:key>";
        requestMain += "                  <b:value i:type=\"c:guid\" xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/\">fd140aae-4df4-11dd-bd17-0019b9312238</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>languagecode</b:key>";
        requestMain += "                  <b:value i:type=\"c:int\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">1033</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>modifiedon</b:key>";
        requestMain += "                  <b:value i:type=\"c:dateTime\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">2011-03-19T23:12:38Z</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>ismanaged</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>createdby</b:key>";
        requestMain += "                  <b:value i:type=\"a:EntityReference\">";
        requestMain += "                    <a:Id>81ed14d9-4441-e011-963a-080027ad5b6e</a:Id>";
        requestMain += "                    <a:LogicalName>systemuser</a:LogicalName>";
        requestMain += "                    <a:Name i:nil=\"true\" />";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>webresourcetype</b:key>";
        requestMain += "                  <b:value i:type=\"a:OptionSetValue\">";
        requestMain += "                    <a:Value>1</a:Value>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>canbedeleted</b:key>";
        requestMain += "                  <b:value i:type=\"a:BooleanManagedProperty\">";
        requestMain += "                    <a:CanBeChanged>true</a:CanBeChanged>";
        requestMain += "                    <a:ManagedPropertyLogicalName>canbedeleted</a:ManagedPropertyLogicalName>";
        requestMain += "                    <a:Value>true</a:Value>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>componentstate</b:key>";
        requestMain += "                  <b:value i:type=\"a:OptionSetValue\">";
        requestMain += "                    <a:Value>0</a:Value>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>modifiedby</b:key>";
        requestMain += "                  <b:value i:type=\"a:EntityReference\">";
        requestMain += "                    <a:Id>81ed14d9-4441-e011-963a-080027ad5b6e</a:Id>";
        requestMain += "                    <a:LogicalName>systemuser</a:LogicalName>";
        requestMain += "                    <a:Name i:nil=\"true\" />";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>ishidden</b:key>";
        requestMain += "                  <b:value i:type=\"a:BooleanManagedProperty\">";
        requestMain += "                    <a:CanBeChanged>true</a:CanBeChanged>";
        requestMain += "                    <a:ManagedPropertyLogicalName>ishidden</a:ManagedPropertyLogicalName>";
        requestMain += "                    <a:Value>false</a:Value>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>webresourceid</b:key>";
        requestMain += "                  <b:value i:type=\"c:guid\" xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + guidWebResourceID + "</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>createdon</b:key>";
        requestMain += "                  <b:value i:type=\"c:dateTime\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">2011-03-17T08:30:20Z</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>name</b:key>";
        requestMain += "                  <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">new_webresourceiframe</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>content</b:key>";
        requestMain += "                  <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + strEncodedContent + "</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "              </a:Attributes>";
        requestMain += "              <a:EntityState i:nil=\"true\" />";
        requestMain += "              <a:FormattedValues>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>iscustomizable</b:key>";
        requestMain += "                  <b:value>True</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>languagecode</b:key>";
        requestMain += "                  <b:value>1,033</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>modifiedon</b:key>";
        requestMain += "                  <b:value>3/19/2011 4:12 PM</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>ismanaged</b:key>";
        requestMain += "                  <b:value>Unmanaged</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>webresourcetype</b:key>";
        requestMain += "                  <b:value>Web Page (HTML)</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>canbedeleted</b:key>";
        requestMain += "                  <b:value>True</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>componentstate</b:key>";
        requestMain += "                  <b:value>Published</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>ishidden</b:key>";
        requestMain += "                  <b:value>False</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>createdon</b:key>";
        requestMain += "                  <b:value>3/17/2011 1:30 AM</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "              </a:FormattedValues>";
        requestMain += "              <a:Id>adfa33cb-7050-e011-9cf8-080027ad5b6e</a:Id>";
        requestMain += "              <a:LogicalName>webresource</a:LogicalName>";
        requestMain += "              <a:RelatedEntities />";
        requestMain += "            </b:value>";
        requestMain += "          </a:KeyValuePairOfstringanyType>";
        requestMain += "        </a:Parameters>";
        requestMain += "        <a:RequestId i:nil=\"true\" />";
        requestMain += "        <a:RequestName>Update</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.UpdateWebResourceResponse(req, successCallback, errorCallback); };
        req.send(requestMain);
    },
    UpdateWebResourceResponse: 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));
            }
        }
    },
    PublishWebResourceRequest: function (guidID) {
        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:PublishXmlRequest\" 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>ParameterXml</c:key>";
        requestMain += "            <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">&lt;importexportxml&gt;&lt;webresources&gt;&lt;webresource&gt;" + guidID + "&lt;/webresource&gt;&lt;/webresources&gt;&lt;/importexportxml&gt;</c:value>";
        requestMain += "          </a:KeyValuePairOfstringanyType>";
        requestMain += "        </a:Parameters>";
        requestMain += "        <a:RequestId i:nil=\"true\" />";
        requestMain += "        <a:RequestName>PublishXml</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.PublishWebResourceResponse(req, successCallback, errorCallback); };
        req.send(requestMain);
    },
    PublishWebResourceResponse: 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) {
                
                //****************************************
                //BELOW IS WHERE WE ARE SETTING THE IFRAME SOURCE
                //******************************************
                var iframeObject = Xrm.Page.getControl("IFRAME_testiframe");
                iframeObject.setSrc("http://win-fo6aph8hsbq/crm/WebResources/new_webresourceiframe");

                //                if (successCallback != null)
                //                { successCallback(); }
            }
            else {
                errorCallback(SDK.SAMPLES._getError(req.responseXML));
            }
        }
    },
    RetrieveWebResourceRequest: function (guidID) {
        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:RetrieveMultipleRequest\" 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>Query</b:key>";
        requestMain += "            <b:value i:type=\"a:QueryExpression\">";
        requestMain += "              <a:ColumnSet>";
        requestMain += "                <a:AllColumns>false</a:AllColumns>";
        requestMain += "                <a:Columns xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">";
        requestMain += "                  <c:string>content</c:string>";
        requestMain += "                </a:Columns>";
        requestMain += "              </a:ColumnSet>";
        requestMain += "              <a:Criteria>";
        requestMain += "                <a:Conditions>";
        requestMain += "                  <a:ConditionExpression>";
        requestMain += "                    <a:AttributeName>webresourceid</a:AttributeName>";
        requestMain += "                    <a:Operator>Equal</a:Operator>";
        requestMain += "                    <a:Values xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">";
        requestMain += "                      <c:anyType i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + guidID + "</c:anyType>";
        requestMain += "                    </a:Values>";
        requestMain += "                  </a:ConditionExpression>";
        requestMain += "                </a:Conditions>";
        requestMain += "                <a:FilterOperator>And</a:FilterOperator>";
        requestMain += "                <a:Filters />";
        requestMain += "              </a:Criteria>";
        requestMain += "              <a:Distinct>false</a:Distinct>";
        requestMain += "              <a:EntityName>webresource</a:EntityName>";
        requestMain += "              <a:LinkEntities />";
        requestMain += "              <a:Orders />";
        requestMain += "              <a:PageInfo>";
        requestMain += "                <a:Count>0</a:Count>";
        requestMain += "                <a:PageNumber>0</a:PageNumber>";
        requestMain += "                <a:PagingCookie i:nil=\"true\" />";
        requestMain += "                <a:ReturnTotalRecordCount>false</a:ReturnTotalRecordCount>";
        requestMain += "              </a:PageInfo>";
        requestMain += "              <a:NoLock>false</a:NoLock>";
        requestMain += "            </b:value>";
        requestMain += "          </a:KeyValuePairOfstringanyType>";
        requestMain += "        </a:Parameters>";
        requestMain += "        <a:RequestId i:nil=\"true\" />";
        requestMain += "        <a:RequestName>RetrieveMultiple</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.RetrieveWebResourceResponse(req, successCallback, errorCallback); };
        req.send(requestMain);
    },
    RetrieveWebResourceResponse: 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) {
                return req.responseXML.xml.toString();
                //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
};

Thats all there is to it!
Now let's look at our result when we open the preview form, it takes about 1.5 seconds to show our updated Jscript on my low powered dev box.



I hope this helps!

Tuesday, March 22, 2011

Editing Embedded Web Resource Contents Using the SDK (C# or Jscript) in Microsoft Dynamics CRM 2011 (A Two Part Series)

I don't know if any of you have run into a situation where it would be useful to be able to update a web resource's contents to do something like parse in your own HTML that could be rendered dynamically.   I have seen this a few times before, in particular it is used in the non profit (NGO) solution sold by Microsoft for CRM 4.0. 

Here is how it works: 

It's a simple update call to the web service to update the webresource entity instance based on it's ID, however, there is one catch.  If you look at the content attribute of the web resource in the database or in a retrieve call, it is encoded.  This is simple Base-64 encoding and you can use one of many available encoding/decoding functions available on the internet for .NET or for Jscript.  Keep in mind that you will have to perform a publish on the webresource using the publish SDK message if you want your changes to be immediately available to the app.

Also, I will reveal tomorrow what my point in all of this was and the end-game should prove to be useful to a lot of people also, so tune in tomorrow for that.

First here is the update code code in C#:
You will notice that the code is using the SoapLogger solution contained in the SDK.  There is a reason for this.  It basically is how we figure out the Jscript, but don't worry, I will show you the Jscript also. :)

  public void Run(ServerConnection.Configuration serverConfig)
  {
   try
   {
    
    // Connect to the Organization service. 
    // The using statement assures that the service proxy will be properly disposed.
    using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri,
                                                        serverConfig.HomeRealmUri,
                                                        serverConfig.Credentials,
                                                        serverConfig.DeviceCredentials))
    {
     // This statement is required to enable early-bound type support.
     _serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());

     IOrganizationService service = (IOrganizationService)_serviceProxy;

     using (StreamWriter output = new StreamWriter("output.txt"))
     {

      SoapLoggerOrganizationService slos = new SoapLoggerOrganizationService(serverConfig.OrganizationUri, service, output);

      //Add the code you want to test here:
      // You must use the SoapLoggerOrganizationService 'slos' proxy rather than the IOrganizationService proxy you would normally use.

      RetrieveMultipleRequest rmr = new RetrieveMultipleRequest();
      RetrieveMultipleResponse resp = new RetrieveMultipleResponse();
         WebResource wb = new WebResource();
         
      QueryExpression query = new QueryExpression()
      {
          EntityName = "webresource",
          ColumnSet = new ColumnSet("content"),
          Criteria = new FilterExpression
          {
              FilterOperator = LogicalOperator.And,
              Conditions = 
                {
                    new ConditionExpression
                    {
                        AttributeName = "webresourceid",
                        Operator = ConditionOperator.Equal,
                        Values = { "ADFA33CB-7050-E011-9CF8-080027AD5B6E" }
                    }
                }
          }
      };

      rmr.Query = query;
         resp  = (RetrieveMultipleResponse)slos.Execute(rmr);
         wb = (WebResource)resp.EntityCollection.Entities[0];

         byte[] b = Convert.FromBase64String(wb.Content);
         string strHTML = System.Text.Encoding.UTF8.GetString(b);
         strHTML = "<html><body><h1>HELLO WORLD!</h1></body></html>";

         byte[] byt = System.Text.Encoding.UTF8.GetBytes(strHTML);

         // convert the byte array to a Base64 string

         wb.Content = Convert.ToBase64String(byt);

         UpdateRequest ur = new UpdateRequest();
         ur.Target = wb;
         slos.Execute(ur);



         //Publish the OptionSet
         PublishXmlRequest pxReq1 = new PublishXmlRequest { ParameterXml = String.Format("<importexportxml><webresources><webresource>ADFA33CB-7050-E011-9CF8-080027AD5B6E</webresource></webresources></importexportxml>") };
         slos.Execute(pxReq1);

     }


    }

   }

   // Catch any service fault exceptions that Microsoft Dynamics CRM throws.
   catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>)
   {
    // You can handle an exception here or pass it back to the calling method.
    throw;
   }
  }



Now, here it is in Jscript, in the event handler in the gui you can just call the runme function after replacing the GUID with that of your webresource entity along with changing the HTML to what you want.:

function runme() {
    
    var guidWebResource = "ADFA33CB-7050-E011-9CF8-080027AD5B6E";

    var strContentHTML = "<html><body><h1>HELLO WORLD!)<h1></body</html>";
    var enc = encode64(strContentHTML);
    SDK.SAMPLES.UpdateWebResourceRequest(guidWebResource, enc);
    SDK.SAMPLES.PublishWebResourceRequest(guidWebResource);

}

function encode64(input) {
    var keyStr = "ABCDEFGHIJKLMNOP" +
               "QRSTUVWXYZabcdef" +
               "ghijklmnopqrstuv" +
               "wxyz0123456789+/" +
               "=";

    //input = escape(input);
    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;

    do {
        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);

        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }

        output = output +
           keyStr.charAt(enc1) +
           keyStr.charAt(enc2) +
           keyStr.charAt(enc3) +
           keyStr.charAt(enc4);
        chr1 = chr2 = chr3 = "";
        enc1 = enc2 = enc3 = enc4 = "";
    } while (i < input.length);

    return output;
}

function decode64(input) {
    var keyStr = "ABCDEFGHIJKLMNOP" +
               "QRSTUVWXYZabcdef" +
               "ghijklmnopqrstuv" +
               "wxyz0123456789+/" +
               "=";

    var output = "";
    var chr1, chr2, chr3 = "";
    var enc1, enc2, enc3, enc4 = "";
    var i = 0;

    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
    var base64test = /[^A-Za-z0-9\+\/\=]/g;
    if (base64test.exec(input)) {
        alert("There were invalid base64 characters in the input text.\n" +
              "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
              "Expect errors in decoding.");
    }
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    do {
        enc1 = keyStr.indexOf(input.charAt(i++));
        enc2 = keyStr.indexOf(input.charAt(i++));
        enc3 = keyStr.indexOf(input.charAt(i++));
        enc4 = keyStr.indexOf(input.charAt(i++));

        chr1 = (enc1 << 2) | (enc2 >> 4);
        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
        chr3 = ((enc3 & 3) << 6) | enc4;

        output = output + String.fromCharCode(chr1);

        if (enc3 != 64) {
            output = output + String.fromCharCode(chr2);
        }
        if (enc4 != 64) {
            output = output + String.fromCharCode(chr3);
        }

        chr1 = chr2 = chr3 = "";
        enc1 = enc2 = enc3 = enc4 = "";

    } while (i < input.length);

    return unescape(output);
}


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;
    },
    UpdateWebResourceRequest: function (guidWebResourceID, strEncodedContent) {
        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:UpdateRequest\" 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:Entity\">";
        requestMain += "              <a:Attributes>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>webresourceidunique</b:key>";
        requestMain += "                  <b:value i:type=\"c:guid\" xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/\">434e47dd-8cb5-427f-8e5f-72b7ed93dcf6</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>organizationid</b:key>";
        requestMain += "                  <b:value i:type=\"a:EntityReference\">";
        requestMain += "                    <a:Id>a2fe1552-7977-4d92-a730-05eeb167afb5</a:Id>";
        requestMain += "                    <a:LogicalName>organization</a:LogicalName>";
        requestMain += "                    <a:Name>crm</a:Name>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>displayname</b:key>";
        requestMain += "                  <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">new_webresourceiframe</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>iscustomizable</b:key>";
        requestMain += "                  <b:value i:type=\"a:BooleanManagedProperty\">";
        requestMain += "                    <a:CanBeChanged>true</a:CanBeChanged>";
        requestMain += "                    <a:ManagedPropertyLogicalName>iscustomizableanddeletable</a:ManagedPropertyLogicalName>";
        requestMain += "                    <a:Value>true</a:Value>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>solutionid</b:key>";
        requestMain += "                  <b:value i:type=\"c:guid\" xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/\">fd140aae-4df4-11dd-bd17-0019b9312238</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>languagecode</b:key>";
        requestMain += "                  <b:value i:type=\"c:int\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">1033</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>modifiedon</b:key>";
        requestMain += "                  <b:value i:type=\"c:dateTime\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">2011-03-19T23:12:38Z</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>ismanaged</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>createdby</b:key>";
        requestMain += "                  <b:value i:type=\"a:EntityReference\">";
        requestMain += "                    <a:Id>81ed14d9-4441-e011-963a-080027ad5b6e</a:Id>";
        requestMain += "                    <a:LogicalName>systemuser</a:LogicalName>";
        requestMain += "                    <a:Name i:nil=\"true\" />";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>webresourcetype</b:key>";
        requestMain += "                  <b:value i:type=\"a:OptionSetValue\">";
        requestMain += "                    <a:Value>1</a:Value>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>canbedeleted</b:key>";
        requestMain += "                  <b:value i:type=\"a:BooleanManagedProperty\">";
        requestMain += "                    <a:CanBeChanged>true</a:CanBeChanged>";
        requestMain += "                    <a:ManagedPropertyLogicalName>canbedeleted</a:ManagedPropertyLogicalName>";
        requestMain += "                    <a:Value>true</a:Value>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>componentstate</b:key>";
        requestMain += "                  <b:value i:type=\"a:OptionSetValue\">";
        requestMain += "                    <a:Value>0</a:Value>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>modifiedby</b:key>";
        requestMain += "                  <b:value i:type=\"a:EntityReference\">";
        requestMain += "                    <a:Id>81ed14d9-4441-e011-963a-080027ad5b6e</a:Id>";
        requestMain += "                    <a:LogicalName>systemuser</a:LogicalName>";
        requestMain += "                    <a:Name i:nil=\"true\" />";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>ishidden</b:key>";
        requestMain += "                  <b:value i:type=\"a:BooleanManagedProperty\">";
        requestMain += "                    <a:CanBeChanged>true</a:CanBeChanged>";
        requestMain += "                    <a:ManagedPropertyLogicalName>ishidden</a:ManagedPropertyLogicalName>";
        requestMain += "                    <a:Value>false</a:Value>";
        requestMain += "                  </b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>webresourceid</b:key>";
        requestMain += "                  <b:value i:type=\"c:guid\" xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/\">" + guidWebResourceID + "</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>createdon</b:key>";
        requestMain += "                  <b:value i:type=\"c:dateTime\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">2011-03-17T08:30:20Z</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>name</b:key>";
        requestMain += "                  <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">new_webresourceiframe</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "                <a:KeyValuePairOfstringanyType>";
        requestMain += "                  <b:key>content</b:key>";
        requestMain += "                  <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + strEncodedContent + "</b:value>";
        requestMain += "                </a:KeyValuePairOfstringanyType>";
        requestMain += "              </a:Attributes>";
        requestMain += "              <a:EntityState i:nil=\"true\" />";
        requestMain += "              <a:FormattedValues>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>iscustomizable</b:key>";
        requestMain += "                  <b:value>True</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>languagecode</b:key>";
        requestMain += "                  <b:value>1,033</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>modifiedon</b:key>";
        requestMain += "                  <b:value>3/19/2011 4:12 PM</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>ismanaged</b:key>";
        requestMain += "                  <b:value>Unmanaged</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>webresourcetype</b:key>";
        requestMain += "                  <b:value>Web Page (HTML)</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>canbedeleted</b:key>";
        requestMain += "                  <b:value>True</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>componentstate</b:key>";
        requestMain += "                  <b:value>Published</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>ishidden</b:key>";
        requestMain += "                  <b:value>False</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "                <a:KeyValuePairOfstringstring>";
        requestMain += "                  <b:key>createdon</b:key>";
        requestMain += "                  <b:value>3/17/2011 1:30 AM</b:value>";
        requestMain += "                </a:KeyValuePairOfstringstring>";
        requestMain += "              </a:FormattedValues>";
        requestMain += "              <a:Id>adfa33cb-7050-e011-9cf8-080027ad5b6e</a:Id>";
        requestMain += "              <a:LogicalName>webresource</a:LogicalName>";
        requestMain += "              <a:RelatedEntities />";
        requestMain += "            </b:value>";
        requestMain += "          </a:KeyValuePairOfstringanyType>";
        requestMain += "        </a:Parameters>";
        requestMain += "        <a:RequestId i:nil=\"true\" />";
        requestMain += "        <a:RequestName>Update</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.UpdateWebResourceResponse(req, successCallback, errorCallback); };
        req.send(requestMain);
    },
    UpdateWebResourceResponse: 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));
            }
        }
    },
    PublishWebResourceRequest: function (guidID) {
        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:PublishXmlRequest\" 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>ParameterXml</c:key>";
        requestMain += "            <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">&lt;importexportxml&gt;&lt;webresources&gt;&lt;webresource&gt;" + guidID + "&lt;/webresource&gt;&lt;/webresources&gt;&lt;/importexportxml&gt;</c:value>";
        requestMain += "          </a:KeyValuePairOfstringanyType>";
        requestMain += "        </a:Parameters>";
        requestMain += "        <a:RequestId i:nil=\"true\" />";
        requestMain += "        <a:RequestName>PublishXml</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.PublishWebResourceResponse(req, successCallback, errorCallback); };
        req.send(requestMain);
    },
    PublishWebResourceResponse: 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));
            }
        }
    },
    RetrieveWebResourceRequest: function (guidID) {
        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:RetrieveMultipleRequest\" 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>Query</b:key>";
        requestMain += "            <b:value i:type=\"a:QueryExpression\">";
        requestMain += "              <a:ColumnSet>";
        requestMain += "                <a:AllColumns>false</a:AllColumns>";
        requestMain += "                <a:Columns xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">";
        requestMain += "                  <c:string>content</c:string>";
        requestMain += "                </a:Columns>";
        requestMain += "              </a:ColumnSet>";
        requestMain += "              <a:Criteria>";
        requestMain += "                <a:Conditions>";
        requestMain += "                  <a:ConditionExpression>";
        requestMain += "                    <a:AttributeName>webresourceid</a:AttributeName>";
        requestMain += "                    <a:Operator>Equal</a:Operator>";
        requestMain += "                    <a:Values xmlns:c=\"http://schemas.microsoft.com/2003/10/Serialization/Arrays\">";
        requestMain += "                      <c:anyType i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">" + guidID + "</c:anyType>";
        requestMain += "                    </a:Values>";
        requestMain += "                  </a:ConditionExpression>";
        requestMain += "                </a:Conditions>";
        requestMain += "                <a:FilterOperator>And</a:FilterOperator>";
        requestMain += "                <a:Filters />";
        requestMain += "              </a:Criteria>";
        requestMain += "              <a:Distinct>false</a:Distinct>";
        requestMain += "              <a:EntityName>webresource</a:EntityName>";
        requestMain += "              <a:LinkEntities />";
        requestMain += "              <a:Orders />";
        requestMain += "              <a:PageInfo>";
        requestMain += "                <a:Count>0</a:Count>";
        requestMain += "                <a:PageNumber>0</a:PageNumber>";
        requestMain += "                <a:PagingCookie i:nil=\"true\" />";
        requestMain += "                <a:ReturnTotalRecordCount>false</a:ReturnTotalRecordCount>";
        requestMain += "              </a:PageInfo>";
        requestMain += "              <a:NoLock>false</a:NoLock>";
        requestMain += "            </b:value>";
        requestMain += "          </a:KeyValuePairOfstringanyType>";
        requestMain += "        </a:Parameters>";
        requestMain += "        <a:RequestId i:nil=\"true\" />";
        requestMain += "        <a:RequestName>RetrieveMultiple</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.RetrieveWebResourceResponse(req, successCallback, errorCallback); };
        req.send(requestMain);
    },
    RetrieveWebResourceResponse: 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) {
                return req.responseXML.xml.toString();
                //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
};


I hope this helps!

Again, come back tomorrow to see what my end-game is with all of this. :)

Monday, March 21, 2011

Fixed: Microsoft CRM 2011 WCF Timing Issue When Making Web Service Calls

I have periodically ran into the following exception on my CRM 2011 virtual dev machine:

System.ServiceModel.Security.MessageSecurityException: An unsecured or incorrectly secured fault was received from the other party. See the inner FaultException for the fault code and detail. ---> System.ServiceModel.FaultException: An error occurred when verifying security for the message.

I have found ways to work around this now every time I have ran into it.
I have noticed another Exception with the same cause before when working with the CrmSvcUtil.exe tool. 

Cause: Timezone or time being wrong on the client or server. 

Resolution: Correct date and time settings on affected machine, also restart client application making call

Example Post Illustrating: http://social.msdn.microsoft.com/Forums/is/wcf/thread/d7a13c9b-2144-4b0d-9585-5a487126ab1f

I had to restart Visual Studio on the client machine after I fixed the time on the server for my calls to function properly.

I hope this helps!