Sdk.Soap.js

IMPORTANT: You should not use this library for new projects! If you have used this library, you should migrate your code to use the Web API. This library uses the deprecated 2011 Organization Service SOAP Endpoint, which will be removed in a future release after v9.x.

C# (475.9 KB)
 
 
 
 
 
4.9 Star
(7)
5,622 times
Add to favorites
10/4/2018
E-mail Twitter del.icio.us Digg Facebook
Sign in to ask a question


  • Unable to set false in mdq.MetadataPropertiesExpression
    3 Posts | Last post June 01, 2015
    • Hello,
      
      I am trying to retrieve only OneToManyRelationship metadata by using Sdk.RetrieveMetadataChangesRequest.
      
      The following code works fine, but I don't want to retrieve all properties.
      var relationshipProperties = new mdq.MetadataPropertiesExpression(true, [
              emp.ManyToManyRelationships
              , emp.ManyToOneRelationships
              , emp.OneToManyRelationships
          ]);
      
      So I changed the code as the following:
          var relationshipProperties = new mdq.MetadataPropertiesExpression(false, [
              emp.OneToManyRelationships
          ]);
      This code does not work fine, and shows the error "Unable to evaluate query".
      
      Could you please check it?
      
      Best regards,
      
    • I tested this with the following code:
      
          var filter = new Sdk.Mdq.MetadataFilterExpression(Sdk.Mdq.LogicalOperator.And);
          filter.addCondition(Sdk.Mdq.SearchableEntityMetadataProperties.LogicalName, Sdk.Mdq.MetadataConditionOperator.Equals, "account");
      
          var emp = Sdk.Mdq.EntityMetadataProperties;
          var properties = new Sdk.Mdq.MetadataPropertiesExpression(false, [emp.OneToManyRelationships])
      
          var req = Sdk.RetrieveMetadataChangesRequest(new Sdk.Mdq.EntityQueryExpression(filter, properties));
      
          Sdk.Async.execute(req, function (resp) {
           console.log(JSON.stringify(resp.getEntityMetadata()[0]["OneToManyRelationships"][0],null,4));
      
          }, function (error) {
           console.log(error.message);
          });
      
      I got the following output to the log: (truncated for brevity)
      
      {
          
          "MetadataId": "28be1745-2c06-11df-80a6-00137299e1c2",
      
          "HasChanged": null,
      
          "IsCustomRelationship": false,
      
          "IsCustomizable": {
      
              "CanBeChanged": false,
      
              "ManagedPropertyLogicalName": "iscustomizable",
      
              "Value": false
          },
      
          "IsManaged": true,
          
          "IsValidForAdvancedFind": false,
      
          "SchemaName": "account_principalobjectattributeaccess",
      
          "SecurityTypes": "Append",
      
          "IntroducedVersion": "5.0.0.0",
      
          "RelationshipType": "OneToManyRelationship",
      
         .....
      
      I can't repro this behavior.
      
      You may want to make sure that you have set 'emp' to be the alias for Sdk.Mdq.EntityMetadataProperties. This isn't in the library, you have to create this alias using this:
      
      var emp = Sdk.Mdq.EntityMetadataProperties;
    • Thank you very much. I could retrieve.
      Thank you.
  • RetrieveMultiple using FetchXml with aggregation
    2 Posts | Last post May 23, 2015
    • I am having an issue when executing RetrieveMultiple using a FetchExpression where the FetchXml uses aggregation (a sum in this case).  In some scenarios, the values are coming back as null, which is throwing errors in 2 places.
      
      1) The switch statement that processes the AliasedValue type fails when it tries to split the "i:type" attribute text to derive the nested type.  In the case of a null value, that attribute isn't present in the XML.
      2) The code that processes the FormattedValues nodes also isn't expecting a null value, so the call to create a new Sdk.FormattedValue throws a "Sdk.FormattedValue Value property must be a string" error.
      
      I have worked around it for the time being by editing the source and converting nulls to empty strings, but I would appreciate it if you could take a look.  Please let me know if you would like to see the XML being returned from the query.
      
      Thanks!
      
      
    • I'd be happy to take a look. We can do this inline via this discussion, or if you want to send me some code, pls send to mscrmsdksamples@microsoft.com and I'll circle back to post any changes or guidance here.
      
      Thanks for reporting this.
  • Errors using Sdk.RetrieveMetadataChanges.js library
    1 Posts | Last post December 13, 2014
    • Thanks to Jason Lattimer for reporting issues he found.
      Errors reported:
       - Uncaught ReferenceError: _addValidLanguage is not defined
       - TypeError: Cannot assign to read only property '_type'
      
      These errors where not occurring on all browsers and could have been resolved by removing 'use strict' from the file, but we located the source of these errors and updated the Sdk.RetrieveMetadataChanges.js file with the fixes.
  • Early Binding - Clearing values (using null)
    3 Posts | Last post November 23, 2014
    • The following code shows that the .setValue() function accepts null for string attributes, but not for the complex types like lookups.  
      
      What is the syntax for clearing data in a column like option sets or lookups?
      
      function RetrieveSucceeded(entity, updateFields) {
          //Cast entity
          var account = new Sdk.Account(entity);
          //Update attributes from the passthrough value
          account.Name.setValue(updateFields.Name);
          if (updateFields.Number == "")
              updateFields.Number = null;
          account.AccountNumber.setValue(updateFields.Number);
          account.ParentAccountId.setValue(null); //Uncaught Error: Sdk.Lookup value property must be a Sdk.EntityReference.
          debugger;
      
          //Update the record...
          Sdk.Async.update(account,
              function () {
                  //success
              },
              function (result) {
                  //failure
              },
              null);
      }
      
      
      Thanks!
    • Good catch.
      I just searched the Sdk.Soap.vsdoc.js for the error message and found it within the Sdk.Lookup.setValue method:
      
       this.Lookup = function (name, value) {
        ///<summary>
        /// A Lookup Attribute
        ///</summary>
        ///<param name="name" type="String" optional="false" mayBeNull="false">
        /// The logical name of the attribute
        ///</param>
        ///<param name="value" type="Sdk.EntityReference" optional="true" mayBeNull="false">
        /// The value of the attribute
        ///</param>
        if (!(this instanceof Sdk.Lookup)) {
         return new Sdk.Lookup(name, value);
        }
        Sdk.AttributeBase.call(this);
        this.setValue = function (value) {
         ///<summary>
         /// Sets the value of a Lookup attribute
         ///</summary>
         ///<param name="value" type="Sdk.EntityReference" optional='false' mayBeNull='true'>
         /// The value to set
         ///</param>
         if (value instanceof Sdk.EntityReference) {
          this.setValidValue(value);
         }
         else {
          throw new Error("Sdk.Lookup value property must be a Sdk.EntityReference.");
         }
        }
      
      If you compare this to the other attribute setValue methods, it seems like this one is not allowing a null value. I suspect this is just a mistake. Please try changing this line:
         if (value instanceof Sdk.EntityReference) {
      To this:
         if (value == null || value instanceof Sdk.EntityReference) {
      
      This should bypass the current error and if the data is updated correctly after you save then I expect it will be fine. I will give this a proper test later, but wanted to respond right away.
      
      This library is a sample so you should feel free to take a copy and change it as necessary. As serious issues (like this one) are found we will maintain it and update it periodically.
      
      Really appreciate you reporting this and other issues. Once I have a chance to verify that this change will fix the problem without any other downstream consequences, I'll update the sample.
    • I checked this out and it looks like this change should not have any downstream impact.
      I have fixed this and updated both the Sdk.Soap.min.js and Sdk.Soap.vsdoc.js
  • Bug in calls to Sdk.BooleanManagedPropertyValue
    2 Posts | Last post November 23, 2014
    • I believe there is a bug in Sdk.Soap.vsdoc.js.
      
      The function signature for this method is:
      
      this.BooleanManagedPropertyValue = function (canBeChanged, value, managedPropertyLogicalName)
      
      However, it is called with the parameters in the wrong order on line 4737:
      
      return new Sdk.BooleanManagedProperty(logicalName, new Sdk.BooleanManagedPropertyValue(_canBeChanged, _managedPropertyLogicalName, _bmpValue));
      
      It is also called wrong on line 4790:
      
      return new Sdk.BooleanManagedProperty(logicalName, new Sdk.BooleanManagedPropertyValue(_aCanBeChanged, _aManagedPropertyLogicalName, _aBmpValue));
      
      This is also true in the "Sdk.Soap.js Samples" package avaible on here. Just figured I bring it up since it took me a long time to realize it was a bug in the SDK.
      
      Thanks.
      
    • Sorry for the delay in responding.
      Thanks for reporting this.
      I have fixed this and updated both the Sdk.Soap.min.js and Sdk.Soap.vsdoc.js
  • Typo Line 1378
    2 Posts | Last post November 23, 2014
    • I noticed
      
      this.setTargetRecords = function (targetRecords) {
         ///<summary>
         /// Sets the collection of relationship records that were added or removed. 
         ///</summary>
         /// <param name="targetRecords" type="Sdk.Collection">
         /// The collection of relationship records that were added or removed. 
         ///</param>
         _setValidX(targetRecords);
      }
      
      _setValidX(targetRecords); needs to be _setValidTargetRecords(targetRecords);
    • Thanks for reporting this.
      I have fixed this and updated both the Sdk.Soap.min.js and Sdk.Soap.vsdoc.js
  • Where are aliased values in QueryExpression's LinkEntities?
    4 Posts | Last post August 07, 2014
    • I'm unable to find the aliased attributes when using early binding for Sdk.Account.js and Sdk.Async.retrieveMultiple().  
      
      Where do the aliased values live on the entity collection's result collection?  
      
      
          var q = new Sdk.Query.QueryExpression("account");
          q.setColumnSet("accountid", "name", "accountnumber");
          q.addOrder("name", Sdk.Query.OrderType.Ascending);
          
          var fAnd = new Sdk.Query.FilterExpression(Sdk.Query.LogicalOperator.And);
          fAnd.addCondition(new Sdk.Query.ConditionExpression("account", "name", Sdk.Query.ConditionOperator.Equal, Sdk.Query.Strings(["Soap Test"])));
          q.setCriteria(fAnd);
      
          var leTask = new Sdk.Query.LinkEntity("account", "task", "accountid", "regardingobjectid", Sdk.Query.JoinOperator.LeftOuter, "aliasTask");
          leTask.setColumns("activityid", "subject");
          q.addLink(leTask);
      
          Sdk.Async.retrieveMultiple(q,
              function (entityCollection) {
                  //success
                  
                  var account = new Sdk.Account(entityCollection.getEntity(0));
                  
                  //This seems like a hack.  What is the best way to get this attribute?  There must be a better way.
                  var subject = account.view().attributes["aliasTask.subject"].fValue
      
                  debugger;
                  //alert("Accounts Found:  " + entityCollection.getCount());
              },
              function (result) {
                  //failed
                  debugger;
              },
              null);
      
      Thanks!
    • This took a little while to track down. It is a bug but you can work around it by changing the alias name value to all lowercase. After you change "aliasTask" to "aliastask" it should work.
      
      You don't really need to convert the entity into an Account, both of these work:
      
      var test1Value = entityCollection.getEntity(0).getValue("aliastask.subject");
      var test2Value = new Sdk.Account(entityCollection.getEntity(0)).getValue("aliastask.subject");
      
      The problem can be found in line 9995 of the Sdk.Soap.vsdoc.js. The Sdk.AttributeCollection.prototype.getAttributeByName function includes the following:
      
      this.getAttributes().forEach(function (att, i) {
        if (att.getName() == name.toLowerCase()) {
         returnValue = att;
         return;
        }
       });
      
      If the name was not converted to lowercase in the comparison it would have worked. The reason to do this was to try and avoid errors if people used a schema name inadvertently.
      Possible fixes:
      1. Remove the '.toLowerCase()' from the getAttributeByName function
      2. Add a requirement that the LinkEntity.entityAlias property always be lower case.
      
      BTW The view function doesn't exist in the managed code SDK, it was added in this library mostly to enable debugging to work around the getValue functions added to support IE8.
      
      
    • Nice find.  :)  I have reservations about manipulating the core files considering future product releases.  In the meantime we have enforced the lower case alias names requirement.  I would think this would be an acceptable modification to the Sdk.Soap file if any one is curios.  
      
      this.getAttributes().forEach(function (att, i) { 
           if (name.indexOf('.' === -1)) { 
               name = name.toLowerCase(); 
           } 
           else { 
               var res = name.split('.'); 
               name = res[0] + "." + res[1].toLowerCase(); 
           } 
      
           if (att.getName() == name) { 
               returnValue = att; 
               return; 
           } 
       }); 
      
    • I like the suggestion to check for the existence of the period. Much more flexible. I will try to implement this when I update the sample.
  • Problem when using Sdk.Soap.min.js - Response object doesn't support property or method
    2 Posts | Last post August 03, 2014
    • Found this issue today and will update the files shortly to address it.
      Calling a message using Sdk.Async.execute with a minimized version of Sdk.Soap.vsdoc.js. The Response object returned doesn't have a method it should, instead it is just a function object.
      The problem is in how the code is minimized.
      
      Sdk.Soap.vsdoc.js contains several places where this pattern is found when executing messages:
      
         successCallBack(new request.getResponseType()(doc), passThruObj);
      
      When this is minimized by ajaxmin, it becomes:
      
         a(new (c.getResponseType)(d), e)
      
      When it should be:
      
         a(new c.getResponseType()(d), e)
      
      The immediate fix you can apply if you are experiencing this issue is to manually edit the minimized Sdk.Soap.min.js library and find replace the following:
      
      't((new n.getResponseType)(u)'  =>  't(new n.getResponseType()(u)'
      'r.resolve((new i.getResponseType)(n))'  =>  'r.resolve(new i.getResponseType()(n))'
      'i.resolve((new t.getResponseType)(n))'  =>  'i.resolve(new t.getResponseType()(n))'
      '(new n.getResponseType)(i)'  =>  'new n.getResponseType()(i)'
      
      
      
      
      
    • I have updated the Sdk.Soap.min.js in the download package, but if you make changes to the Sdk.Soap.vsdoc.js and minimize it again, the same errors will be introduced and you will need to make the 4 find/replace steps mentioned above.
  • Sdk.Util.isGuid doesn't accept curly braces { }
    4 Posts | Last post June 18, 2014
    • Sdk.Util.isGuid() doesn't accept curly braces { }, while Xrm.Page.data.entity.getId() returns a Guid-string surrounded with curly braces. This is an annoyance when simply trying to construct a new Sdk.EntityReference(Xrm.Page.data.entity.getEntityName(), Xrm.Page.data.entity.getId()).
      Please extend the regular expression with /^\{? at the start and \}?$/ at the end to allow the Guid to be surrounded with curly braces.
    • Thanks for your feedback and pointing this out.
      
      It is important that Sdk.Util.isGuid not be changed to allow curly braces. The rest of the library expects that all GUID values are strings without the curly braces. This shared function guarantees that.
      
      I have gotten this feedback before but didn't have time to make a change and test. I think I would just change the Sdk.EntityReference constructor to detect that the value has those curly braces and then remove them before the validation function is called. You can edit the Sdk.Soap.vsdoc.js and apply the change, then minimize it.
      The code is an internal function (at about line 3077):
      
        function _setValidId(value)
        {
      //put your change to trim any curly braces from the value parameter here
      
         if (value != null && Sdk.Util.isGuidOrNull(value))
         {
          _id = value;
         }
         else
         {
          throw new Error("Sdk.EntityReference constructor id value property is required and must be a String representation of a GUID value.");
         }
      
        }
      
      Alternatively, write a helper to trim it in the form script before passing it to the Sdk.EntityReference constructor.
      
      It is good for folks to be aware of this. When we have time to update this sample, I'll try to include this. For now, please use the workaround steps described here.
      
    • Thanks for your answer.
      I've yet to find a case where using a Guid surrounded with braces does not work in Sdk.Soap. However, there's more than one place where Sdk.Util.isGuidOrNull is called (also in messages like Sdk.CancelContractRequest). So I don't understand what the added value is for "sanitizing" the Guid each time I need to use it in Sdk.Soap. A Guid with braces is a valid Guid string-representation during (de)serialization... So when there is no actual dependency " (and when there is, please point it out specifically) I still think allowing braces is the way to go.
      
      We're actively using/implementing Sdk.Soap in an existing 2011 project (step-by-step), so please regard my comments as constructive criticism from the trenches.
    • Thanks for your feedback. I think you have a point. I never tried to include the curly braces along with the XML because when I observed the XML passed using the SOAP logger sample it always removed them. I assumed that was a requirement.
      
      I'm glad this is working for you with CRM 2011. I never actually tested it in a 2011 environment, but I suspected it should work. The endpoint didn't change between those two releases.
  • Why throw error when attribute does not exist?
    2 Posts | Last post June 18, 2014
    • Can you please explain why you would throw an error when for instance getting an attribute by name and it doesn't exist in the retrieved entity? This means every call to get a specific attribute must be wrapped in a try/catch. The Retrieve call already verifies (server side) whether the attribute exists (when explicitly set in the ColumnSet). From my point of view returning null would be sufficient.
      It also differs from the implementation in the C# SDK for Entity.getAttributeValue<T>(), which simply returns null for reference types (including nullable value types) when the attribute doesn't exist.
    • I assume you are using the late-bound style. It was to ensure that the developer only accesses attributes that they expect to be there in the entity. I take it that you are saying that you are comfortable with the fact that a missing attribute in the entity when you included it in your query column set equals a null value. I guess I wasn't comfortable making that assumption. What if the attribute wasn't actually in the columnSet? Then the code would be assuming that the value is null when in fact the developer just forgot to include it in the columnSet or later removed it from the columnSet without realizing that other parts of their code might be referencing it.
      I was thinking that it would be better to throw an error if the attribute wasn't present rather than just pass back a null value.
      
      I was expecting that people would explicitly initialize the entity to attach any attributes that they intend to use. They would do this either by using the entity class generator to include supporting entity definitions in an early-bound style, or they would add them individually using the late-bound style. 
      
      In the Sdk.Soap.js Samples project the SampleHelperMethods.js library includes an initializeEntity function that you can use in conjunction with a dictionary of columns to re-initialize the entity instance when using the late-bound style. You can also use the getColumnSet helper function described there to use that same dictionary to control what attributes you retrieve. I believe if you adopt that pattern you shouldn't have a problem with errors thrown when the attribute doesn't exist because it will be there. Also, you can have a central place to define the attributes you are interested in either retrieving or working with for that entity.
      I hope that helps.
11 - 20 of 20 Items