Monday, March 14, 2011

Inserting, Updating, or Deleting OptionSet Values in Microsoft Dynamics CRM 2011 in Jscript

I found the other day how useful it can potentially be to be able to work with optionset values from Jscript in the CRM GUI.  I wanted to share quick library I created that inserts, updates, or deletes optionset values in Jscript using the organization service SOAP endpoint from within the application.
 (Note:  The code looks better once you copy and paste it to a different location.)

You will want to remove anything you don't way  from the library, and you will also want to parse in your own values for the edits as the functions currently assume static values that I used for my test scenarios. 

You can then call these functions using the following syntax when hooking up the eventhandlers in CRM:

SDK.OPTIONSETVALUE.InsertOptionValueRequest
SDK.OPTIONSETVALUE.UpdateOptionValueRequest
SDK.OPTIONSETVALUE.DeleteOptionValueRequest

If you are working with optionsets this way you may also want to review my blogpost on how to publish entities from Jscript so you can immediately work with your changes you make with this library at http://mileyja.blogspot.com/2011/03/publish-entity-in-jscript-in-crm-2011.html

I hope this helps, and Enjoy!!

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.OPTIONSETVALUE = {
           _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;
               }, 
           InsertOptionValueRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:InsertOptionValueRequest\" 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>Label</b:key>";
               requestMain += "            <b:value i:type=\"a:Label\">";
               requestMain += "              <a:LocalizedLabels>";
               requestMain += "                <a:LocalizedLabel>";
               requestMain += "                  <a:IsManaged i:nil=\"true\" />";
               requestMain += "                  <a:Label>testoptionCode9</a:Label>";
               requestMain += "                  <a:LanguageCode>1033</a:LanguageCode>";
               requestMain += "                </a:LocalizedLabel>";
               requestMain += "              </a:LocalizedLabels>";
               requestMain += "              <a:UserLocalizedLabel i:nil=\"true\" />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>AttributeLogicalName</b:key>";
               requestMain += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">new_testoptionset</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>EntityLogicalName</b:key>";
               requestMain += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">account</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>InsertOptionValue</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.OPTIONSETVALUE._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.OPTIONSETVALUE.InsertOptionValueResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       InsertOptionValueResponse: 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 successful 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.OPTIONSETVALUE._getError(req.responseXML));
               }
           }
       },
      UpdateOptionValueRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:UpdateOptionValueRequest\" 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>Value</b:key>";
               requestMain += "            <b:value i:type=\"c:int\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">100000001</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>MergeLabels</b:key>";
               requestMain += "            <b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">false</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>EntityLogicalName</b:key>";
               requestMain += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">account</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>AttributeLogicalName</b:key>";
               requestMain += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">new_testoptionset</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>Label</b:key>";
               requestMain += "            <b:value i:type=\"a:Label\">";
               requestMain += "              <a:LocalizedLabels>";
               requestMain += "                <a:LocalizedLabel>";
               requestMain += "                  <a:IsManaged i:nil=\"true\" />";
               requestMain += "                  <a:Label>Updated Option 1</a:Label>";
               requestMain += "                  <a:LanguageCode>1033</a:LanguageCode>";
               requestMain += "                </a:LocalizedLabel>";
               requestMain += "              </a:LocalizedLabels>";
               requestMain += "              <a:UserLocalizedLabel i:nil=\"true\" />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>UpdateOptionValue</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.OPTIONSETVALUE._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.OPTIONSETVALUE.UpdateOptionValueResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       UpdateOptionValueResponse: 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.OPTIONSETVALUE._getError(req.responseXML));
               }
           }
       },
       DeleteOptionValueRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:DeleteOptionValueRequest\" 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>Value</b:key>";
               requestMain += "            <b:value i:type=\"c:int\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">100000001</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>EntityLogicalName</b:key>";
               requestMain += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">account</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>AttributeLogicalName</b:key>";
               requestMain += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">new_testoptionset</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>DeleteOptionValue</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.OPTIONSETVALUE._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.OPTIONSETVALUE.DeleteOptionValueResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       DeleteOptionValueResponse: 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.OPTIONSETVALUE._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
};



//************************

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.OPTIONSETVALUE = {
           _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;
               }, 
           UpdateOptionValueRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:UpdateOptionValueRequest\" 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>Value</b:key>";
               requestMain += "            <b:value i:type=\"c:int\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">100000001</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>MergeLabels</b:key>";
               requestMain += "            <b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">false</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>EntityLogicalName</b:key>";
               requestMain += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">account</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>AttributeLogicalName</b:key>";
               requestMain += "            <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">new_testoptionset</b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>Label</b:key>";
               requestMain += "            <b:value i:type=\"a:Label\">";
               requestMain += "              <a:LocalizedLabels>";
               requestMain += "                <a:LocalizedLabel>";
               requestMain += "                  <a:IsManaged i:nil=\"true\" />";
               requestMain += "                  <a:Label>Updated Option 1</a:Label>";
               requestMain += "                  <a:LanguageCode>1033</a:LanguageCode>";
               requestMain += "                </a:LocalizedLabel>";
               requestMain += "              </a:LocalizedLabels>";
               requestMain += "              <a:UserLocalizedLabel i:nil=\"true\" />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>UpdateOptionValue</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.OPTIONSETVALUE._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.OPTIONSETVALUE.UpdateOptionValueResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       UpdateOptionValueResponse: 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.OPTIONSETVALUE._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
};
 
 //*******************************
 
 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.OPTIONSETVALUE = {
           _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;
               }, 

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


 

14 comments:

  1. One thing about this post. Do the values stay in the optionset after a form is closed and reopen? I ask this because the only thing i managed is to put the data in the option set but if i go to the attribute to see if the data is there,it is not.

    So my steps were:
    ----------------
    1. insert values from jscript onload event of custom entity in a diffrent way than this blog.
    2.Save the form and close.
    3. No value shows up on the Form View Grid with the new inserted values and the values dont exist in the attribute properties.

    So does this fix the problem and leave the new option set values inserted in the list of values ???

    ReplyDelete
  2. I would potentially suggest in your case to try a hybrid of the two techniques. My method WILL fix your persistance problem if you insert them this way and then call an entity publish, which I lay out at this post: http://mileyja.blogspot.com/2011/03/publish-entity-in-jscript-in-crm-2011.html
    The new values are saved in the CRM database using web services.

    Show me your method for insertion, if it uses the SDK for some sort of a supported insert that has an ID and label and such it should work with mine to do exactly what you want, then I would like to actually amend your method to mine in this post to make it even more useful if it works.

    You will notice that the insert call returns the integer ID value in the system for this optionset item. You could try to accomplish what you want this way.

    1. Perform the insert using my method above.
    2. Publish you entity: http://mileyja.blogspot.com/2011/03/publish-entity-in-jscript-in-crm-2011.html
    3. Use the returned integer ID from the insert method as a basis for your temporary insert method you used before to get it into the system. That way you might be able to work with it right away. Otherwise after the publish you will need to redirect back to the page in order to actually see your optionset value.

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Ok i think you overestimated me a little :)

    This is what i was trying to do from the Onload event of a custom entity of a custom optionset i created with JScript. The optionset that i created has 4 values inside(null+3 values starting from 100000000) i have entered when i first created the attribute.

    var picklist=Xrm.Page.data.entity.attributes.get("new_optionsettest");

    var options = picklist.getOptions();
    alert(options.length); <----this gives 4

    var size = 100000000+options.length-1;

    var option = new Option();
    option.text = "testing" ;
    option.value= size;

    tried three staff after
    a)picklist.addOption(option,size);
    b)options.addOption(option,size);
    c)Xrm.Page.data.entity.attributes.get("new_optionsettest").addOption(option,size);

    Nothing works. I get the below error at the line addOption:
    "
    There was an error with this field's customized event.

    Field:window
    event:onload
    error:Object doesn't support this property or method
    "

    what is needed for the addOption as first parameter. In crm4 AddOption had a string.

    That is what i have done and failed.

    I have tried your solution and it worked but the only problem a get now is that i get two values the same because one is created with the Onload and one with the onsave because the form is loaded again there.

    ReplyDelete
  5. Hmm, but only one option is actually persisted to the database the next time you open a form. I see your point.

    Are you preforming your addoption in an onchange event? Maybe that onchange event could fire the save event (which would reload the form) and then you wouldn't do the other addoption, but it would have the one my method put in there?

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. all code that i made is in the onload event of a custom entity.
    Can a button be pushed to execute your code?
    or
    i write the following algorythm:
    1)With the loading of the form(OnLoad) first Clear all the values from the optionset.
    2)Publish then to make the action happen.
    3)After all are cleared populated with the values needed.
    4)Publish again to make the action happen.
    5)Put an OnChange event for the the selected value of the optionset and put the value in a diffrent text field which is read only.

    By doing this i think it fixes all problems but the thing is to do it and if it is worth of doing it without a big bottleneck.

    Also maybe a button can be pushed to execute your code.can that be done?

    Just to note that all the clear, addition and publish steps are going to be used with your code.

    What do u think?

    The OnChange event is field specific and fires when the specified field is changed.

    Thanks i talk to much :)

    ReplyDelete
  9. No this is happenning in an Onload event.If i do it in a onChange event for thespecific field then i will not get the values that i want from the start.

    The Problem is that i dont need data to be entered each time the form is loaded.

    The way i want it is :
    1)When i first open the form the new values are entered in the optionset.
    2)I choose the value that i want
    3)Save the form.Here if you do a save & close, the form will not reload but if i do a save it will be reloaded and hence it will enter the data again.

    There is blind spot in what i want.if all goes well and i load my values the first time. then when i want to come back to my form again the same values will be entered again.

    So the only option in all of this is to perform a clearOption kind of thing to clear first all the values in the picklist and then enter the values but if i do that maybe the records that I have already will get messed up.

    Then i thought of an diffrent approach that implements all that i said with your solution. i write the following algorythm:
    1)With the loading of the form(OnLoad) first Clear all the values from the optionset.
    2)Publish then to make the action happen.
    3)After all are cleared populated with the values needed.
    4)Publish again to make the action happen.
    5)Put an OnChange event for the the selected value of the optionset and put the value in a diffrent text field which is read only.

    By doing this i think it fixes all problems but the tthing is to do it and if it is worth of doing it without a big bottleneck.
    Also maybe a button can be pushed to execute your code.can that be done?


    Just to note that all the clear, addition and publish steps are going to be used with your code.

    What do u think?

    The OnChange event is field specific and fires when the specified field is changed.

    Thanks i talk to much :)

    ReplyDelete
  10. You can give it a stab. The other thing I was thinking of was where are these optionset values being determined? When do you know they need to be added? If it is the creation of another entity or something to that affect why wouldn't you attach the form script to that entity instead?

    ReplyDelete
  11. Also if you wanted to have a button call the code you can edit the ribbon I would think similar to how isv.config worked in 4.0 to put javascript on the backend to fire the code. I haven't done this yet though.

    ReplyDelete
  12. The thing is i want to bring in values i have from my web service(An array of values) and put them in my optionset.

    The thing is i only can think of doing this in the onload event of my custom entity.

    These values are updated all the time so i think thats the only option i have.
    1)Bring an array of values, that are updated all the time, from a service in crm,by pressing a custom button.
    2)Load them in a optionset
    3)use that optionset for the user to pick a value.
    4)the picked value is then put in a text field with the onchange event of the optionset field
    5)and then save the form.

    I have managed to do all this but the last value is not inside my optionset and i cant get the delete thing to work so i can clear all my values first before entering them.

    ReplyDelete
  13. Would you please provide a sample in C# ?
    Thanks

    ReplyDelete
    Replies
    1. Mostafa, there is actually good examples of these calls in C# in MSDN here:
      http://msdn.microsoft.com/en-us/library/gg307406.aspx

      Thanks!

      Jamie

      Delete