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. :)

7 comments:

  1. Hi, I have created HTML page through which I am reading XML(data) , Now I want to Update this XML(data) File using javascript in this HTML page

    ReplyDelete
  2. Hi I am getting error at

    else
    {
    errorCallback(SDK.SAMPLES._getError(req.responseXML));
    }

    errorCallback is null here, can you please check this

    ReplyDelete
    Replies
    1. I am trying to update XML(data) web resource. so are tehre any changes to be made to this code for that.

      Delete
  3. I would recommend debugging your jscript using step-by-step.

    ReplyDelete
  4. ok, I have to make changes to request, thank you

    ReplyDelete
  5. sorry can you please show me how to upadate xml data

    ReplyDelete
    Replies
    1. It's text, pick your favorite editor, I usually use Visual Studio or Notepad++. You need to change the guids to match that of your records. This example uses guids and attributes from my implementation on CRM. You need to do a little bit of work to make this example work for your environment.

      Delete