Introduction

Use this library to write JavaScript code in web resources that can perform actions using the Microsoft Dynamics CRM 2013 Modern App SOAP endpoint (formerly known as the SOAP endpoint for web resources).

You can use this library in form scripts, ribbon commands, or HTML web resources. This library does not provide code to allow authentication for outside of web resources.

IntelliSense support

The Sdk.Soap.js library provides an object model, methods, and messages that you use to write JavaScript code in a manner similar to how you write C# code. Visual Studio has greatly improved how IntelliSense is provided at design time. The Sdk.Soap.js project provides two files described in the following table, but this document refers to them used together as the Sdk.Soap.js library.

File Description and Usage
Sdk.Soap.vsdoc.js
  • Use this file at design time by including a reference at the top of JavaScript files you author. Simply include this file in your project and drag it to the top of the JavaScript library that you’re writing.
  • This library includes comments that provide detailed design-time IntelliSense about the objects and methods included.
  • Size: 400 Kb
Sdk.Soap.min.js
  • Create a JavaScript web resource using this file and include links to it within any HTML pages that use it.
  • If you’re adding this library to a ribbon command or form event handler, it must load before any other code that references it loads.
  • Size: 164 Kb.
  • This file is simply the minimized version of Sdk.Soap.vsdoc.js. If you need to edit the library, edit the vsdoc version and then minimize it.

Note: Full reference documentation for Sdk.Soap.js is not currently available, but you can reference the object and method notes for any method using IntelliSense or by reviewing the comments in Sdk.Soap.vsdoc.js.

Like writing managed code using the Microsoft Dynamics CRM web services, this library provides the options to choose whether you write code using an “early-bound” or “late-bound” style. You can use the Sdk.Soap.js library alone to write code in the late-bound style.

See Sdk.Soap.js Samples for examples.

Early-bound vs. Late-bound

Many developers prefer an early-bound style that requires you to generate class files that provide design-time IntelliSense support for the CRM entities that you’re working with. With managed code, this requires generating a supporting file using the CRMSvcUtil.exe code generation tool.

With Sdk.Soap.js you can generate files to provide object definition and design-time IntelliSense support in Visual Studio using the separate Sdk.Soap Entity Class Generator project. See that project for more information.

However, the code generation tool and the Sdk.Soap entity class generator can only generate classes for entity definitions known in the organization that they’re run against. If your code only uses the entities, attributes, and entity relationships present when these tools are used, the classes will represent the objects your code needs. When you move your code to a different organization, or when new entities, attributes, or entity relationships get added through customizations, you have to generate these classes again.

The alternative is to write your code without the supporting design time classes. Sdk.Soap.js provides an Sdk.Entity class that corresponds to the Microsoft.Xrm.Entity class. However, you won’t be able to take advantage of the design-time auto-completion and IntelliSense in Visual Studio. You'll have to look up information about entities and attributes using resources like the Metadata Browser.

The advantage of using a late-bound style, especially with JavaScript, is that you can reduce the number of files that must be loaded into the page.

The Sdk.Soap.js Samples project contains a number of examples showing both early-bound and late-bound styles. For example:

Early-bound initialization of an Account:

 

JavaScript
Edit|Remove
 var account = new Sdk.Account() 
 account.Name.setValue("Sample Account 001"); 
 account.CreditOnHold.setValue(false); 
 account.Address1_Latitude.setValue(47.638197); 
 account.Address1_Longitude.setValue(-122.131378); 
 account.NumberOfEmployees.setValue(500); 
 account.Description.setValue("This is a description."); 
 account.CreditLimit.setValue(200000.00); 
 account.AccountCategoryCode.setValue(1); 

Late-bound initialization of an Account:

JavaScript
Edit|Remove
 var account = new Sdk.Entity("account"); 
 account.addAttribute(new Sdk.String("name", name)); 
 account.addAttribute(new Sdk.Boolean("creditonhold", false)); 
 account.addAttribute(new Sdk.Double("address1_latitude"47.638197)); 
 account.addAttribute(new Sdk.Double("address1_longitude", -122.131378)); 
 account.addAttribute(new Sdk.Int("numberofemployees"100000)); 
 account.addAttribute(new Sdk.String("description""This is a description.")); 
 account.addAttribute(new Sdk.Money("creditlimit"2000000)); 
 account.addAttribute(new Sdk.OptionSet("accountcategorycode"1)); //Preferred Customer 

Use promises and asynchronous XmlHttpRequests

XmlHttpRequests performed using JavaScript should be asynchronous. Sdk.Soap.js provides the capability to perform synchronous requests, but this isn’t recommended.

Traditionally asynchronous XmlHttpRequests are performed using functions that allow for setting callback functions for success and error conditions. With this style, a chain of operations are added by continuing the next step within the success callback.

The alternative to this approach is to use promises. JQuery uses a Deferred object that provides chainable utility that returns a promise. The CommonJS Promises/A proposal defines a slightly different definition of how promises should work. There are a number of different libraries that implement this standard. One of them is Q.

In order to provide you with options that match your preferences, Sdk.Soap.js separates the core methods used in CRM web services into four separate namespaces. Each of these namespaces provides the methods in the following table that correspond to IOrganizationService methods.

Method IOrganizationService method
associate Associate
create Create
del Delete
Note: ‘delete’ is a JavaScript keyword and can’t be used as a method name.
disassociate Disassociate
execute Execute
retrieve Retrieve
retrieveMultiple RetrieveMultiple
update Update

The following table describes the namespaces that implement these methods.

Namespace Description & Comments
Sdk.Async
  • The method signatures provide successCallBack and errorCallBack parameters.
  • No supporting library required.
Sdk.jQ
  • Depends on the existence of the jQuery library.
  • Returns a jQuery.Deferred object.
  • Requires that the global jQuery variable be explicitly set using the Sdk.jQ.setJQueryVariable function.
    • This supports the best practice defined in the Use of jQuery topic in the Microsoft Dynamics CRM SDK.
    • To avoid conflicts when multiple versions of jQuery might be loaded in a single page, you should explicitly set the jQuery variable.
    • If you’re using jQuery in your own HTML web resource and want to use the default jQuery variable, simply include the following line somewhere in your code:
      Sdk.jQ.setJQueryVariable($);
Sdk.Q
  • Depends on the Q.js library
  • Throws an error if the global variable Q isn’t defined.
Sdk.Sync
  • Methods return synchronously.
  • Strongly not recommended for most situations.

If you don’t want to use these different styles, you can edit the Sdk.Soap.vsdoc.js file and remove the entire namespace group. Then minimize the file and use it instead of Sdk.Soap.min.js.

If you want to implement another style, for example Sdk.WinJs, you can implement the same interface methods in a new namespace and add them to Sdk.Soap.js.

Use messages

In addition to the eight core methods implemented by each namespace, you can perform operations using messages and the execute method. The Sdk.Soap.js project provides 202 messages you can use.

Sdk.AddItemCampaign.js Sdk.AddItemCampaignActivity.js
Sdk.AddListMembersList.js Sdk.AddMemberList.js
Sdk.AddMembersTeam.js Sdk.AddPrivilegesRole.js
Sdk.AddProductToKit.js Sdk.AddRecurrence.js
Sdk.AddSolutionComponent.js Sdk.AddToQueue.js
Sdk.AddUserToRecordTeam.js Sdk.Assign.js
Sdk.Associate.js Sdk.AutoMapEntity.js
Sdk.BackgroundSendEmail.js Sdk.Book.js
Sdk.BulkDelete.js Sdk.BulkDetectDuplicates.js
Sdk.CalculateActualValueOpportunity.js Sdk.CalculateTotalTimeIncident.js
Sdk.CanBeReferenced.js Sdk.CanBeReferencing.js
Sdk.CancelContract.js Sdk.CancelSalesOrder.js
Sdk.CanManyToMany.js Sdk.CheckIncomingEmail.js
Sdk.CheckPromoteEmail.js Sdk.CloneContract.js
Sdk.CloseIncident.js Sdk.CloseQuote.js
Sdk.CompoundUpdateDuplicateDetectionRule.js Sdk.ConvertKitToProduct.js
Sdk.ConvertOwnerTeamToAccessTeam.js Sdk.ConvertProductToKit.js
Sdk.ConvertQuoteToSalesOrder.js Sdk.ConvertSalesOrderToInvoice.js
Sdk.CopyCampaign.js Sdk.CopyCampaignResponse.js
Sdk.CopyDynamicListToStatic.js Sdk.CopyMembersList.js
Sdk.CopySystemForm.js Sdk.Create.js
Sdk.CreateActivitiesList.js Sdk.CreateException.js
Sdk.CreateInstance.js Sdk.CreateWorkflowFromTemplate.js
Sdk.Delete.js Sdk.DeleteAuditData.js
Sdk.DeleteOpenInstances.js Sdk.DeliverIncomingEmail.js
Sdk.DeliverPromoteEmail.js Sdk.DeprovisionLanguage.js
Sdk.Disassociate.js Sdk.DistributeCampaignActivity.js
Sdk.DownloadReportDefinition.js Sdk.ExecuteByIdSavedQuery.js
Sdk.ExecuteByIdUserQuery.js Sdk.ExecuteMultiple.js
Sdk.ExecuteWorkflow.js Sdk.ExpandCalendar.js
Sdk.ExportMappingsImportMap.js Sdk.FetchXmlToQueryExpression.js
Sdk.FindParentResourceGroup.js Sdk.FulfillSalesOrder.js
Sdk.GenerateInvoiceFromOpportunity.js Sdk.GenerateQuoteFromOpportunity.js
Sdk.GenerateSalesOrderFromOpportunity.js Sdk.GetAllTimeZonesWithDisplayName.js
Sdk.GetInvoiceProductsFromOpportunity.js Sdk.GetQuantityDecimal.js
Sdk.GetQuoteProductsFromOpportunity.js Sdk.GetReportHistoryLimit.js
Sdk.GetSalesOrderProductsFromOpportunity.js Sdk.GetTimeZoneCodeByLocalizedName.js
Sdk.GetTrackingTokenEmail.js Sdk.GrantAccess.js
Sdk.ImportMappingsImportMap.js Sdk.ImportRecordsImport.js
Sdk.InitializeFrom.js Sdk.InstallSampleData.js
Sdk.InstantiateFilters.js Sdk.InstantiateTemplate.js
Sdk.IsComponentCustomizable.js Sdk.IsDataEncryptionActive.js
Sdk.IsValidStateTransition.js Sdk.LocalTimeFromUtcTime.js
Sdk.LockInvoicePricing.js Sdk.LockSalesOrderPricing.js
Sdk.LoseOpportunity.js Sdk.Merge.js
Sdk.ModifyAccess.js Sdk.ParseImport.js
Sdk.ProcessInboundEmail.js Sdk.PropagateByExpression.js
Sdk.ProvisionLanguage.js Sdk.PublishAllXml.js
Sdk.PublishDuplicateRule.js Sdk.PublishXml.js
Sdk.QualifyLead.js Sdk.QualifyMemberList.js
Sdk.QueryExpressionToFetchXml.js Sdk.QueryMultipleSchedules.js
Sdk.QuerySchedule.js Sdk.ReassignObjectsOwner.js
Sdk.ReassignObjectsSystemUser.js Sdk.Recalculate.js
Sdk.RemoveItemCampaign.js Sdk.RemoveItemCampaignActivity.js
Sdk.RemoveMemberList.js Sdk.RemoveMembersTeam.js
Sdk.RemoveParent.js Sdk.RemovePrivilegeRole.js
Sdk.RemoveProductFromKit.js Sdk.RemoveSolutionComponent.js
Sdk.RemoveUserFromRecordTeam.js Sdk.RenewContract.js
Sdk.ReplacePrivilegesRole.js Sdk.Reschedule.js
Sdk.ResetUserFilters.js Sdk.Retrieve.js
Sdk.RetrieveAbsoluteAndSiteCollectionUrl.js Sdk.RetrieveAllChildUsersSystemUser.js
Sdk.RetrieveAttributeChangeHistory.js Sdk.RetrieveAuditDetails.js
Sdk.RetrieveAvailableLanguages.js Sdk.RetrieveBusinessHierarchyBusinessUnit.js
Sdk.RetrieveByGroupResource.js Sdk.RetrieveByResourceResourceGroup.js
Sdk.RetrieveByResourcesService.js Sdk.RetrieveByTopIncidentProductKbArticle.js
Sdk.RetrieveByTopIncidentSubjectKbArticle.js Sdk.RetrieveDataEncryptionKey.js
Sdk.RetrieveDependenciesForDelete.js Sdk.RetrieveDependenciesForUninstall.js
Sdk.RetrieveDependentComponents.js Sdk.RetrieveDeploymentLicenseType.js
Sdk.RetrieveDeprovisionedLanguages.js Sdk.RetrieveDuplicates.js
Sdk.RetrieveExchangeRate.js Sdk.RetrieveFilteredForms.js
Sdk.RetrieveFormattedImportJobResults.js Sdk.RetrieveInstalledLanguagePacks.js
Sdk.RetrieveInstalledLanguagePackVersion.js Sdk.RetrieveLicenseInfo.js
Sdk.RetrieveLocLabels.js Sdk.RetrieveMembersBulkOperation.js
Sdk.RetrieveMetadataChanges.js Sdk.RetrieveMissingDependencies.js
Sdk.RetrieveMultiple.js Sdk.RetrieveOrganizationResources.js
Sdk.RetrieveParentGroupsResourceGroup.js Sdk.RetrievePersonalWall.js
Sdk.RetrievePrincipalAccess.js Sdk.RetrievePrincipalAttributePrivileges.js
Sdk.RetrievePrivilegeSet.js Sdk.RetrieveProvisionedLanguagePackVersion.js
Sdk.RetrieveProvisionedLanguages.js Sdk.RetrieveRecordChangeHistory.js
Sdk.RetrieveRecordWall.js Sdk.RetrieveRequiredComponents.js
Sdk.RetrieveRolePrivilegesRole.js Sdk.RetrieveSharedPrincipalsAndAccess.js
Sdk.RetrieveSubGroupsResourceGroup.js Sdk.RetrieveTeamPrivileges.js
Sdk.RetrieveTimestamp.js Sdk.RetrieveUnpublished.js
Sdk.RetrieveUserPrivileges.js Sdk.RetrieveVersion.js
Sdk.ReviseQuote.js Sdk.RevokeAccess.js
Sdk.Rollup.js Sdk.Search.js
Sdk.SearchByBodyKbArticle.js Sdk.SearchByKeywordsKbArticle.js
Sdk.SearchByTitleKbArticle.js Sdk.SendBulkMail.js
Sdk.SendEmail.js Sdk.SendEmailFromTemplate.js
Sdk.SendFax.js Sdk.SendTemplate.js
Sdk.SetBusinessEquipment.js Sdk.SetBusinessSystemUser.js
Sdk.SetDataEncryptionKey.js Sdk.SetParentBusinessUnit.js
Sdk.SetParentSystemUser.js Sdk.SetParentTeam.js
Sdk.SetReportRelated.js Sdk.SetState.js
Sdk.TransformImport.js Sdk.TriggerServiceEndpointCheck.js
Sdk.UninstallSampleData.js Sdk.UnlockInvoicePricing.js
Sdk.UnlockSalesOrderPricing.js Sdk.UnpublishDuplicateRule.js
Sdk.Update.js Sdk.UtcTimeFromLocalTime.js
Sdk.Validate.js Sdk.ValidateRecurrenceRule.js
Sdk.ValidateSavedQuery.js Sdk.WhoAmI.js
Sdk.WinOpportunity.js Sdk.WinQuote.js

These message libraries were generated using code based on the data in entities in Microsoft Dynamics CRM. These don’t represent all the messages available. Certain messages were not included based on the following criteria:

Why is metadata treated differently?

Creating a library to replace application functionality to create or edit entities, attributes, or entity relationships was out of scope.

Messages like RetrieveAllEntities, RetrieveEntity, RetrieveAttributes, and so on perform poorly and are inefficient. RetrieveMetadataChanges provides a more robust means to define queries for metadata and returns only required metadata.

Metadata objects returned via RetrieveMetadataChanges are simple JavaScript objects without get/set methods on the properties. They are read-only.

All message libraries include classes that inherit from a base Sdk.OrganizationRequest class that includes much of the functionality to make these requests work. Each of these libraries includes a Request and Response class for each message.

Note: Not every one of these messages has been tested. Each of them matches a known pattern with known data types. Because each of the data types is known and can be serialized into the XML needed to create the request and to parse the response, they all should work. But full testing of each message was out of scope for this sample. If you find a message that doesn’t work as you expect, please report it.

Some libraries contain additional supporting classes used only for that message. For example, Sdk.RetrieveMetadataChanges.js contains classes found in the Microsoft.Xrm.Sdk.Metadata.Query namespace that support this message. Sdk.Search.js also contains classes used only by that message.

Minimizing messages

The messages provided in the Sdk.Soap.js project contain comments to support design-time IntelliSense. Although most of these files are already rather small (186 of them are 10Kb or below), you can still minimize them to make them smaller. Minimized versions of these libraries aren’t provided in the Sdk.Soap.js project.

Use actions

Actions were introduced in Microsoft Dynamics CRM 2013. An action is essentially a workflow that you can define to generate a custom message. Actions can only be executed in code.

The Sdk.Soap.js Action Message Generator project includes an application you can use to generate JavaScript libraries for any custom actions in your organization. Use these libraries just as you would use the libraries for messages.

Query Data

The Sdk.Soap.js library supports the three main query styles used with retrieve operations:

The objects used to define these queries are found in the Sdk.Query namespace. Each of these classes inherits from an Sdk.QueryBase class so each of them is valid to use as a property for an Sdk.RetrieveMultipleRequest or as a parameter to the retrieveMultiple method.

Use these classes in a manner similar to the way you use them in managed code However, since JavaScript can’t detect types at runtime, you must use the appropriate class in this namespace to explicitly state the type of object when setting the criteria for Sdk.Query.QueryByAttribute or Sdk.Query.QueryExpression.

The classes listed in the following table inherit from Sdk.Query.ValueBase.

Sdk.Query.Booleans Sdk.Query.BooleanManagedProperties Sdk.Query.Dates
Sdk.Query.Decimals Sdk.Query.Doubles Sdk.Query.EntityReferences
Sdk.Query.Guids Sdk.Query.Ints Sdk.Query.Longs
Sdk.Query.Money Sdk.Query.OptionSets Sdk.Query.Strings

Sdk.Query.FetchExpression simply requires a string representing the XML for the query. No object model is provided to compose a FetchXML string programmatically. Use Sdk.Query.QueryExpression if you want to do this.

Use the Sdk.Collection class

The Sdk.Collection class is re-used throughout Sdk.Soap.js. It manages an array of a type set when it is instantiated based on a function set as the type parameter. Any time a new object is added to the collection, it’s checked to ensure all objects in the collection are the same type or inherit from the same type.

Sdk.Collection is used instead of a typed Array used in several CRM object properties.

Sdk.Collection also provides a consistent interface to work with collections. The Sdk.Collection class exposes the following methods:

Design notes

Sdk.Soap.js was written using “plain old JavaScript” rather than some of the other technologies used to build large libraries such as TypeScript and Script#. These technologies have great advantages for maintaining a code base, automated testing, and compile time errors, but the goal of this project was to not require a developer to learn those technologies in order to use the library.

Every operation that uses the Microsoft Dynamics CRM Modern App SOAP endpoint is essentially just serializing objects into a known XML schema and passing that XML as a request and then parsing the XML returned in the response back into JavaScript objects. Because JavaScript is not a strongly typed language, classes needed to be defined as functions to ensure the integrity of each object so that it can be serialized and parsed consistently.

In order to reduce the opportunity for errors to be introduced by developers using the library, every object property or method parameter is carefully type checked. This library also needs to support every browser supported by Microsoft Dynamics CRM, which at this time includes Internet Explorer 8. Internet Explorer 8 standard mode supports the Object.defineProperty Function (JavaScript) only for DOM objects but not user-defined objects. This function is key in creating properties with internal get/set functions that can ensure the type when assigning a value to a property. Without this capability, this library uses explicit getValue/setValue functions for each property, just as the Xrm.Page form scripting object does.

Managing XML namespaces

The patterns used in this library were inferred by using the SOAPLogger sample application in the SDK. One thing that became clear immediately is that the XML namespaces assigned by the application depended on the particular set of objects being serialized. Because XPath expressions were used to parse the values returned and consistent namespace aliases needed to be set when composing the XML to include in the request, it was necessary to define a set of specific alias values to use when composing the XML and to explicitly set namespace alias values when parsing the XML returned in responses.

Within the Sdk.Xml namespace there is an ns property used to set an appropriate alias for each of the schemas.

JavaScript
Edit|Remove
 var ns = { 
  "s""http://schemas.xmlsoap.org/soap/envelope/", 
  "a""http://schemas.microsoft.com/xrm/2011/Contracts", 
  "i""http://www.w3.org/2001/XMLSchema-instance", 
  "b""http://schemas.datacontract.org/2004/07/System.Collections.Generic", 
  "c""http://www.w3.org/2001/XMLSchema", 
  "d""http://schemas.microsoft.com/xrm/2011/Contracts/Services", 
  "e""http://schemas.microsoft.com/2003/10/Serialization/", 
  "f""http://schemas.microsoft.com/2003/10/Serialization/Arrays", 
  "g""http://schemas.microsoft.com/crm/2011/Contracts", 
  "h""http://schemas.microsoft.com/xrm/2011/Metadata", 
  "j""http://schemas.microsoft.com/xrm/2011/Metadata/Query", 
  "k""http://schemas.microsoft.com/xrm/2013/Metadata", 
  "l""http://schemas.microsoft.com/xrm/2012/Contracts" 
 }

These alias values were added as each schema was encountered in the development process and don’t represent any kind of standard alias value for other purposes.

Known issues