Query Metadata Using JavaScript

Applies To: Microsoft Dynamics CRM 2011, Microsoft Dynamics CRM Online

Jim Daly
Microsoft Corporation

January, 2013

Summary

This article describes a JavaScript library you can use to query metadata using JavaScript and the messages included in the Microsoft.Xrm.Sdk.Metadata.Query namespace, which is described in the Microsoft Dynamics CRM SDK topic Retrieve and Detect Changes to Metadata.

The SDK.Metadata.Query.js.zip contains the following JavaScript libraries.

SDK.Metadata.Query.vsdoc.js
Use this library at design time to have IntelliSense support in Microsoft Visual Studio.

SDK.Metadata.Query.min.js
Create a web resource using this library. It is smaller (63 KB) and will load faster.

noteNote
These libraries are sample code. They show how the classes and messages used in the Microsoft.Xrm.Sdk.Metadata.Query namespace can be included in a JavaScript library and use the SOAP endpoint for web resources in client-side code. The SOAP endpoint for web resources is a Microsoft Dynamics CRM feature, but these libraries are not. Do not contact Microsoft Dynamics CRM technical support for help with these libraries. If you have any comments or questions, use the Community Additions area at the bottom of this article or click the Send comments about this article to Microsoft link.

The MetadataQueryJavaScript_1_0_0_0_managed.zip is a managed solution that demonstrates the use of this library by replicating the managed code sample included in the Microsoft Dynamics CRM SDK topic: Sample: Query Metadata and Detect Changes.

Applies To

Microsoft Dynamics CRM 2011 and Microsoft Dynamics CRM Online

Microsoft Dynamics CRM 2011 Update Rollup 12 and the Microsoft Dynamics CRM December 2012 Service Update

Retrieve and Detect Changes to Metadata

Introduction

The new classes in the Microsoft.Xrm.Sdk.Metadata.Query namespace and the RetrieveMetadataChangesRequest message in Update Rollup 12 and the December 2012 Service Update provide better options for developers to retrieve just the metadata they need and to detect changes to the metadata over time. These classes and the message are part of the Microsoft.Xrm.Sdk.dll file included in the SDK so developers using managed code can begin using these classes simply because they are included in the assembly.

JavaScript developers need to use the SOAP endpoint for web resources to use the RetrieveMetadataChangesRequest. Microsoft Dynamics CRM doesn’t provide JavaScript libraries for messages using the SOAP endpoint. Therefore, if you can’t locate an open source, third party, or sample library that you can trust, you need to create your own library.

The Microsoft Dynamics CRM SDK includes a walkthrough of the process to create your own library in Walkthrough: Use the SOAP Endpoint for Web Resources with JavaScript. That process uses a console application called SoapLogger to capture the XML requests and responses. You can also use the CrmXpress SmartSoapLogger for Microsoft Dynamics CRM 2011, which provides a user interface. The procedure consists of capturing the XML in the requests and responses generated using managed code. You then create a JavaScript library that you use to send the request and process the results.

The procedure works well for creating a static function to perform specific tasks using simple parameters, but it doesn’t provide the same design time experience or flexibility as the object model contained in the managed assembly classes. The goal of the libraries provided with this article is to give JavaScript developers a similar level of flexibility provided by the managed assembly classes.

This library was created by using the procedure described in the SDK to observe the XML being sent and received, and reverse engineering a set of JavaScript classes and functions that replicate the object model provided by the Microsoft.Xrm.Sdk.Metadata.Query namespace classes.

In This Article

Using Metadata in JavaScript

You may never need to access the metadata for common business logic that is applied using form scripts. You can even create user interface elements like lookup controls that are entirely hard-coded for a specific purpose without accessing the metadata in your code.

However, if you want to create tools for developers, custom user interfaces, or web resources defining controls that can be re-used for different entities and attributes in different organizations, you should access the metadata so that your tools or controls can adapt to differences between organizations and entities. Using metadata in your code can reduce the amount of maintenance required when changes to the metadata affect the logic in your code.

As the name of the message suggests, RetrieveMetadataChangesRequest includes capabilities to track changes to metadata so that a persistent metadata cache can be maintained. With HTML5 Web Storage, it may be possible use JavaScript to cache metadata locally and use the capabilities to track changes so that the cache can be updated efficiently. The SDK.Metadata.Query JavaScript library supports the ability to track changes, but using web storage is not addressed in this article because the most common cases using JavaScript may not require this. Even without implementing a persistent metadata cache, the new objects and the RetrieveMetadataChangesRequest message allow for a much more performant way to retrieve metadata.

Options to Retrieve Metadata Using JavaScript

Before the RetrieveMetadataChangesRequest message was added, the messages to retrieve metadata were limited to the following: RetrieveAllEntitiesRequest, RetrieveEntityRequest, RetrieveAttributeRequest, RetrieveRelationshipRequest and RetrieveOptionSetRequest. These are still valuable messages but they are most useful when you want to view all the metadata for a particular item and you know the names of the items you want. The SDK.Metadata.js library included in the Sample: Retrieve Entity Metadata Using JavaScript includes functions that use RetrieveAllEntitiesRequest, RetrieveEntityRequest, and RetrieveAttributeRequest.

The main problem with using these messages is that they may return more data than you may need. The RetrieveAllEntitiesRequest can be one of the most expensive messages to use in terms of performance. Depending on the number of entities in an organization, the EntityFilters enumeration used in the request, and the latency of the network, this message may take minutes to complete and may possibly time out. The only method to mitigate performance is to set the EntityFilters enumeration so that only the entity properties you need are returned. But then you need to may need to use RetrieveEntityRequest to get details about any specific entity. To get an idea of the performance of these messages, use the Metadata Browser included in the SDK. For more information about the Metadata Browser, see Browse the Metadata for Your Organization.

With RetrieveMetadataChangesRequest you can use classes in the Microsoft.Xrm.Sdk.Metadata.Query namespace to create a query to only return the metadata items you may need in a single request. If you have a requirement for just one specific set of metadata you can still use this request and capture the XML in the request and response using the procedure from Walkthrough: Use the SOAP Endpoint for Web Resources with JavaScript to create a single function to meet your requirement. You may want to re-use parts of the SDK.Metadata.js library _objectifyNode function to generate JavaScript objects for the metadata returned as XML.

However, if you are required to make several different metadata requests or you have a dynamic user interface that may need to interact with an unknown number of entities, attributes or relationships, the library provided with this article may help you meet the requirements.

Using the SDK.Metadata.Query JavaScript library

The SDK.Metadata.Query JavaScript library is designed to provide a developer experience similar to the experience using the strongly typed classes used with managed code. But, because JavaScript is not strongly typed, the objects are defined as functions. For example, compare the definition of a MetadataFilterExpression using C# and JavaScript. In both examples, the excludedEntities variable refers to an array of SchemaName values representing entities that should not be returned.

The following example taken from the SDK Sample: Query Metadata and Detect Changes topic uses C#:

using Microsoft.Xrm.Sdk.Metadata.Query;

 . . .

//A filter expression to limit entities returned to non-intersect, user-owned entities not found in the list of excluded entities.
MetadataFilterExpression EntityFilter = new MetadataFilterExpression(LogicalOperator.And);
EntityFilter.Conditions.Add(new MetadataConditionExpression("IsIntersect", MetadataConditionOperator.Equals, false));
EntityFilter.Conditions.Add(new MetadataConditionExpression("OwnershipType", MetadataConditionOperator.Equals, OwnershipTypes.UserOwned));
EntityFilter.Conditions.Add(new MetadataConditionExpression("SchemaName", MetadataConditionOperator.NotIn, excludedEntities));
MetadataConditionExpression isVisibileInMobileTrue = new MetadataConditionExpression("IsVisibleInMobile", MetadataConditionOperator.Equals, true);
EntityFilter.Conditions.Add(isVisibileInMobileTrue);

The following example defines the same object using JavaScript:


/// <reference path="../VSDoc/Scripts/SDK.Metadata.Query.vsdoc.js" />
var mdq = SDK.Metadata.Query;
var semp = mdq.SearchableEntityMetadataProperties;
var samp = mdq.SearchableAttributeMetadataProperties;
var srmp = mdq.SearchableRelationshipMetadataProperties
var emp = mdq.EntityMetadataProperties;
var amp = mdq.AttributeMetadataProperties;
var rmp = mdq.RelationshipMetadataProperties;
var ve = mdq.ValueEnums;

 . . .

//A filter expression to limit entities returned to non-intersect, user-owned entities not found in the list of excluded entities.
var EntityFilter = new mdq.MetadataFilterExpression(mdq.LogicalOperator.And);
EntityFilter.addCondition(semp.IsIntersect, mdq.MetadataConditionOperator.Equals, false);
EntityFilter.addCondition(semp.OwnershipType, mdq.MetadataConditionOperator.Equals, ve.OwnershipType.UserOwned);
EntityFilter.addCondition(semp.SchemaName, mdq.MetadataConditionOperator.NotIn, excludedEntities);
var isVisibileInMobileTrue = new mdq.MetadataConditionExpression(semp.IsVisibleInMobile, mdq.MetadataConditionOperator.Equals, true);
EntityFilter.addCondition(isVisibileInMobileTrue);

JavaScript doesn’t enjoy all the benefits that managed code does when editing using Microsoft Visual Studio. To get IntelliSense, you must drag a reference to the SDK.Metadata.Query.vsdoc.js file to the top of the JavaScript library you are editing. This reference path enables the IntelliSense and auto completion using this library definition. For Microsoft Visual Studio 2010, installing the Jscript Editor Extensions will help. These extensions are available from within the Microsoft Visual Studio 2010 Tools menu. Select Extension Manager and then search the Online Gallery for Jscript Editor Extensions.

JavaScript namespaces are simulated by creating a hierarchy using nested objects. Rather than adding a reference to the project, you have to refer to the globally defined object provided by the library. Using aliases as shown helps mitigate the typing that would otherwise be required with the long namespace names. The aliases defined previously are recommended but not required. For more information about the enumerations used in this library, see Enumerations in the Reference section.

One major difference between the definitions in the assembly and the JavaScript library is that the SDK.Metadata.Query JavaScript library provides enumerations that allow for IntelliSense when setting parameters that expect names of specific metadata properties. The managed code expects that you will enter string values or create your own enumerations. The JavaScript enumerations are separated into the types of properties that can be requested and those that can be used to construct a query. The searchable properties are a subset of all the available properties. With the managed code you need to read the documentation to understand which properties cannot be used in a query. The new metadata browser included in the SDK should also help because it allows for filtering metadata based on actual data in your organization. For more information about the new metadata browser see Browse the Metadata for Your Organization.

Another difference is that the JavaScript library implements some helper methods, for example, on the SDK.Metadata.Query.MetadataFilterExpression class. The addCondition method accepts the parameters for either a new SDK.Metadata.Query.MetadataConditionExpression or an SDK.Metadata.Query.MetadataConditionExpression instance. It is also possible to add a condition using the following syntax:

EntityFilter.getConditions().add(condition);

Each of the collections implemented by the classes uses a common SDK.Metadata.Query.Collection class that implements type checking and provides the following methods: add, clear, remove, contains, addRange, forEach. This class is similar to the managed code DataCollection Generic class that inherits from the .NET Collection<T> Class.

Continuing the comparison, the following C# and JavaScript code completes an initial request from the managed code sample: Sample: Query Metadata and Detect Changes.

The following C# code defines a MetadataPropertiesExpression to specify that only the Attributes property of the entities should be returned. Then it defines a MetadataFilterExpression for those attributes specifying what types of attributes should be returned.

// EntityProperties is a Properties expression to limit the properties to be included with entities.
MetadataPropertiesExpression EntityProperties = new MetadataPropertiesExpression()
{
 AllProperties = false
};
EntityProperties.PropertyNames.AddRange(new string[] { "Attributes" });

// optionsetAttributeTypes is a condition expression to return optionset attributes.
MetadataConditionExpression[] optionsetAttributeTypes = new MetadataConditionExpression[] { 
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.Picklist),
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.State),
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.Status),
new MetadataConditionExpression("AttributeType", MetadataConditionOperator.Equals, AttributeTypeCode.Boolean)
};

// AttributeFilter is a filter expression to apply the optionsetAttributeTypes condition expression.
MetadataFilterExpression AttributeFilter = new MetadataFilterExpression(LogicalOperator.Or);
AttributeFilter.Conditions.AddRange(optionsetAttributeTypes);

}

The following JavaScript code is the equivalent.

//Define what properties of the entities to retrieve.
var EntityProperties = new mdq.MetadataPropertiesExpression(false, [emp.Attributes]);

//Define an array of SDK.Metadata.Query.MetadataConditionExpression objects to be passed in using the addConditions method.
var optionsetAttributeTypes = [];
optionsetAttributeTypes.push(new mdq.MetadataConditionExpression(samp.AttributeType, mdq.MetadataConditionOperator.Equals, ve.AttributeTypeCode.Picklist));
optionsetAttributeTypes.push(new mdq.MetadataConditionExpression(samp.AttributeType, mdq.MetadataConditionOperator.Equals, ve.AttributeTypeCode.State));
optionsetAttributeTypes.push(new mdq.MetadataConditionExpression(samp.AttributeType, mdq.MetadataConditionOperator.Equals, ve.AttributeTypeCode.Status));
optionsetAttributeTypes.push(new mdq.MetadataConditionExpression(samp.AttributeType, mdq.MetadataConditionOperator.Equals, ve.AttributeTypeCode.Boolean));

var AttributeFilter = new mdq.MetadataFilterExpression(mdq.LogicalOperator.Or);
AttributeFilter.addConditions(optionsetAttributeTypes);

The following C# code defines a MetadataPropertiesExpression class to specify that only the OptionSet and AttributeType properties need to be returned. It also defines a LabelQueryExpression class to indicate that only labels for the user’s preferred language should be returned. The _languageCode variable represents a number value that corresponds to valid language code for the organization. Language codes are four-digit or five-digit locale IDs. Valid locale ID values can be found at Locale ID (LCID) Chart). Typically JavaScript code will use the getUserLcid function to identify the user’s preferred language.

// AttributeProperties is a Properties expression to limit the properties to be included with attributes.
MetadataPropertiesExpression AttributeProperties = new MetadataPropertiesExpression() { AllProperties = false };
AttributeProperties.PropertyNames.Add("OptionSet");
AttributeProperties.PropertyNames.Add("AttributeType");

// labelQuery is a label query expression to limit the labels returned to only those for the user's preferred language
LabelQueryExpression labelQuery = new LabelQueryExpression();
labelQuery.FilterLanguages.Add(_languageCode);


The following JavaScript code is the equivalent.


//Define the attribute properties to return.
var AttributeProperties = mdq.MetadataPropertiesExpression(false);
AttributeProperties.addProperty(amp.OptionSet);
AttributeProperties.addProperty(amp.AttributeType);

//Define that only labels for the user's language preference need to be returned.
var labelQuery = new mdq.LabelQueryExpression([_languageCode]);


The following C# code uses the objects defined to create an EntityQueryExpression class and pass it through to a getMetadataChanges method to return the RetrieveMetadataChangesResponse class.

// entityQueryExpression is an entity query expression to combine the filter expressions and property expressions for the query.
EntityQueryExpression entityQueryExpression = new EntityQueryExpression()
{
 Criteria = EntityFilter,
 Properties = EntityProperties,
 AttributeQuery = new AttributeQueryExpression()
 {
  Criteria = AttributeFilter,
  Properties = AttributeProperties
 },
LabelQuery = labelQuery
};

//Retrieve the metadata for the query without a ClientVersionStamp.
RetrieveMetadataChangesResponse results = getMetadataChanges(entityQueryExpression, null, DeletedMetadataFilters.OptionSet);
// Do something with the results here.

The JavaScript equivalent also uses a getMetadataChanges function except it is asynchronous and requires a successCallback to process the results.

//Initialize the SDK.Metadata.Query.EntityQueryExpression using the variables defined.
_entityQueryExpression = new mdq.EntityQueryExpression(
  EntityFilter,
  EntityProperties,
  new mdq.AttributeQueryExpression(AttributeFilter, AttributeProperties),
  null,
  labelQuery
 );

//Retrieve the metadata and continue through other operations asynchronously 
// using the successCallback parameters containing the next steps.
getMetadataChanges(
 _entityQueryExpression,
 null, //No ClientVersionStamp passed the first time.
 null, //No DeletedMetadataFilters are defined.
function (results){
// Do something with the results here.
},
 function (error) {
     writeMessage(error.message);
 }
);



The following C# code shows the getMetadataChanges method implementation.

protected RetrieveMetadataChangesResponse getMetadataChanges(
 EntityQueryExpression entityQueryExpression,
 String clientVersionStamp,
 DeletedMetadataFilters deletedMetadataFilter)
 {
  RetrieveMetadataChangesRequest retrieveMetadataChangesRequest = new RetrieveMetadataChangesRequest()
  {
   Query = entityQueryExpression,
   ClientVersionStamp = clientVersionStamp,
   DeletedMetadataFilters = deletedMetadataFilter
  };

 return (RetrieveMetadataChangesResponse)_service.Execute(retrieveMetadataChangesRequest);
 }

The following is the JavaScript equivalent.

function getMetadataChanges(entityQueryExpression, clientVersionStamp, deletedMetadataFilter, successCallBack, errorCallback) {
 //Initialize a SDK.Metadata.Query.RetrieveMetadataChangesRequest object.
 var retrieveMetadataChangesRequest = new mdq.RetrieveMetadataChangesRequest(entityQueryExpression, clientVersionStamp, deletedMetadataFilter);
 //Execute the request passing the successCallBack and errorCallback functions through.
 mdq.RetrieveMetadataChanges(retrieveMetadataChangesRequest, successCallBack, errorCallback);
}

Sample getAttributeOptions function

For metadata tasks you perform frequently, you can use the SDK.Metadata.Query library to create reusable functions. The following getAttributeOptions function shows a way to retrieve and cache option values for specific attributes.

  function getAttributeOptions(entityLogicalName, attributeLogicalName, dictionaryObject, onComplete)
  {
   ///<summary>
   /// <para>Retrieves the picklist attribute options and appends them to a dictionary object.</para>
   /// <para>It then executes the function assigned to the onComplete parameter.</para>
   ///</summary>
   ///<param name="entityLogicalName" type="String">
   /// The logical name of the entity
   ///</param>
   ///<param name="attributeLogicalName" type="String">
   /// The logical name of the Picklist attribute
   ///</param>
   ///<param name="dictionaryObject" type="Object">
   /// An empty object that will become a dictionary for the option values.
   ///</param>
   ///<param name="onComplete" type="Function">
   /// A function to perform when the options are assigned to the dictionaryObject;
   ///</param>
   if (!(typeof entityLogicalName == "string")) { throw new Error("getAttributeOptions entityLogicalName parameter is required and must be a string."); }
   if (!(typeof attributeLogicalName == "string")) { throw new Error("getAttributeOptions attributeLogicalName parameter  is required and  must be a string."); }
   if (!(typeof dictionaryObject == "object")) { throw new Error("getAttributeOptions dictionaryObject parameter is required and must be an object."); }
   if (!(typeof onComplete == "function")) { throw new Error("getAttributeOptions onComplete parameter is required and must be a function."); }

   var passThroughObject = {};
   passThroughObject.eln = entityLogicalName;
   passThroughObject.aln = attributeLogicalName;
   passThroughObject.dObj = dictionaryObject;
   passThroughObject.oc = onComplete;

   if ((typeof SDK == "undefined") || (typeof SDK.Metadata == "undefined") || (typeof SDK.Metadata.Query == "undefined"))
   { throw new Error("getAttributeOptions function requires the SDK.Metadata.Query.min.js library and it is not present."); }

   var mdq = SDK.Metadata.Query;
   var semp = mdq.SearchableEntityMetadataProperties;
   var samp = mdq.SearchableAttributeMetadataProperties;
   var srmp = mdq.SearchableRelationshipMetadataProperties
   var emp = mdq.EntityMetadataProperties;
   var amp = mdq.AttributeMetadataProperties;
   var rmp = mdq.RelationshipMetadataProperties;
   var ve = mdq.ValueEnums;

   //EntityFilter
   var ef = new mdq.MetadataFilterExpression(mdq.LogicalOperator.And);
   ef.addCondition(semp.LogicalName, mdq.MetadataConditionOperator.Equals, entityLogicalName);
   //Entity Properties
   var ep = new mdq.MetadataPropertiesExpression(false, [emp.Attributes]);

   //Attribute Filter
   var af = new mdq.MetadataFilterExpression(mdq.LogicalOperator.And);
   af.addCondition(samp.LogicalName, mdq.MetadataConditionOperator.Equals, attributeLogicalName);
      
   //Attribute Properties
   var ap = new mdq.MetadataPropertiesExpression(false, [amp.OptionSet, amp.AttributeType]);
   // AttributeQuery
   var aq = new mdq.AttributeQueryExpression(af, ap);
   // LabelQuery
   var lq = new mdq.LabelQueryExpression([1033]);
   //EntityQueryExpression
   var eqe = new mdq.EntityQueryExpression(ef, ep, aq, null, lq);
   //RetrieveMetadataChangesRequest
   var rmcr = new mdq.RetrieveMetadataChangesRequest(eqe, null, mdq.DeletedMetadataFilters.Default);

   mdq.RetrieveMetadataChanges(
    rmcr,
    function (rmcResponse, pto)
    {
     var attributeType = "unknown";
     if (typeof rmcResponse.EntityMetadata[0] == "undefined" || rmcResponse.EntityMetadata[0] == null)
     { throw new Error("No entity metadata found for " + pto.eln); }
     if (typeof rmcResponse.EntityMetadata[0].Attributes[0] == "undefined" || rmcResponse.EntityMetadata[0].Attributes[0] == null)
     { throw new Error("No attribute metadata found for " + pto.eln + "." + pto.aln); }
     if (typeof rmcResponse.EntityMetadata[0].Attributes[0].OptionSet == "undefined" || rmcResponse.EntityMetadata[0].Attributes[0].OptionSet == null)
     { throw new Error(pto.eln + "." + pto.aln + " does not have an OptionSet property."); }
     attributeType = rmcResponse.EntityMetadata[0].Attributes[0].AttributeType;
     if (attributeType != "Boolean")
     {
      if (typeof rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options == "undefined" || rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options == null)
      { throw new Error(pto.eln + "." + pto.aln + "OptionSet does not have an Options property"); }
      if (typeof rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options[0] == "undefined" || rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options[0] == null)
      { throw new Error(pto.eln + "." + pto.aln + "OptionSet.Options does not have any options"); }
     }


     pto.dObj[pto.eln] = pto.dObj[pto.eln] || {};
     pto.dObj[pto.eln].attributes = pto.dObj[pto.eln].attributes || {};
     pto.dObj[pto.eln].attributes[pto.aln] = pto.dObj[pto.eln].attributes[pto.aln] || {};
     pto.dObj[pto.eln].attributes[pto.aln].options = pto.dObj[pto.eln].attributes[pto.aln].options || {};
     if (attributeType != "Boolean")
     {
      for (var i in rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options)
      {
       var option = rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.Options[i];
       pto.dObj[pto.eln].attributes[pto.aln].options[option.Value] = option.Label.UserLocalizedLabel.Label;
      }
     }
     else
     {
      pto.dObj[pto.eln].attributes[pto.aln].options[0] = rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.FalseOption.Label.UserLocalizedLabel.Label;
      pto.dObj[pto.eln].attributes[pto.aln].options[1] = rmcResponse.EntityMetadata[0].Attributes[0].OptionSet.TrueOption.Label.UserLocalizedLabel.Label;
     }

     pto.oc(pto.eln, pto.aln);
    },
    function (error) { writeMessage(error.message); },
    passThroughObject);

  }

The following code in an HTML web resource shows the use of the getAttributeOptions function.

  // MetaDataDictionary
  var mdd = {};
  function testResults(entityLogicalName, attributeLogicalName) {
   alert("Options for " + entityLogicalName + "." + attributeLogicalName + " cached.");
  }

  document.onreadystatechange = function ()
  {
   if (document.readyState == "complete")
   {
    getAttributeOptions("account", "customertypecode", mdd, testResults);
   }
  }

After the options for the customertypecode attribute have been retrieved and cached they can be accessed using the following code.

for (option in mdd.account.attributes.customertypecode.options)
{
var value = option;
var label = mdd.account.attributes.customertypecode.options[option];
}

Using a consistent structure like this, you can continue to append properties to the metadata dictionary object to display all the metadata items you need to cache.

Reference

The following sections describe the public objects and methods included in the SDK.Metadata.Query JavaScript library.

SDK.Metadata.Query.AttributeQueryExpression

Defines a complex query to retrieve attribute metadata for entities retrieved using an SDK.Metadata.Query.EntityQueryExpression. This class is the equivalent to the AttributeQueryExpression managed code class.

Constructor parameters:

The following table shows the methods available for SDK.Metadata.Query.AttributeQueryExpression.

 

Method Description Returns Parameter Type

getCriteria()

Gets the filter criteria to be applied to attributes in the query.

SDK.Metadata.Query.MetadataFilterExpression

NA

setCriteria(criteria)

Sets the filter criteria to be applied to attributes in the query.

Null

SDK.Metadata.Query.MetadataFilterExpression

getProperties()

Gets the attribute properties to return in the query.

SDK.Metadata.Query.MetadataPropertiesExpression

NA

setProperties(properties)

Gets the attribute properties to return in the query.

Null

SDK.Metadata.Query.MetadataPropertiesExpression

SDK.Metadata.Query.Collection

Defines collections used in the library. Provides a common set of methods to interact with collections. This class is the equivalent to the DataCollection Generic managed code class.

Constructor parameters:
  • type: Required. Specifies the type of object to be stored in the collection

  • List: Optional. An Array of items to initialize the collection.

The following table shows the methods available for SDK.Metadata.Query.Collection.

 

Method Description Returns Parameter Type

add(item)

Adds an item to the collection.

Null

Matches the type set in the constructor

clear()

Removes all items from the collection.

Null

NA

remove(item)

Removes the item matching the parameter.

Null

Matches the type set in the constructor

contains(item)

Returns whether the item in the parameter is in the collection.

Boolean

Matches the type set in the constructor

addRange(array)

Adds items to the collection.

Null

An array of items matching the type set in the constructor

SDK.Metadata.Query.EntityQueryExpression

Defines a complex query to retrieve entity metadata.

Constructor parameters:

The following table shows the methods available for SDK.Metadata.Query.EntityQueryExpression.

 

Method Description Returns Parameter Type

getCriteria()

Gets the filter criteria to be applied to entities in the query.

SDK.Metadata.Query.MetadataFilterExpression

NA

setCriteria(criteria)

Sets the filter criteria to be applied to entities in the query.

Null

SDK.Metadata.Query.MetadataFilterExpression

getProperties()

Gets the entity properties to return in the query.

SDK.Metadata.Query.MetadataPropertiesExpression

NA

setProperties(properties)

Sets the entity properties to return in the query.

Null

SDK.Metadata.Query.MetadataPropertiesExpression

getAttributeQuery()

Gets the attribute query expression used in the query.

SDK.Metadata.Query.AttributeQueryExpression

NA

setAttributeQuery(attributeQuery)

Sets the attribute query expression used in the query.

Null

SDK.Metadata.Query.AttributeQueryExpression

getRelationshipQuery()

Gets the relationship query expression used in the query.

SDK.Metadata.Query.RelationshipQueryExpression

NA

setRelationshipQuery(relationshipQuery)

Sets the relationship query expression used in the query.

Null

SDK.Metadata.Query.RelationshipQueryExpression

getLabelQuery()

Gets the label query expression used in the query.

SDK.Metadata.Query.LabelQueryExpression

NA

setLabelQuery(labelQuery)

Sets the label query expression used in the query.

Null

SDK.Metadata.Query.LabelQueryExpression

SDK.Metadata.Query.GuidValue

Required to use when setting a condition value that is a GUID.

Constructor parameters:
  • stringValue: Required. A String representing a GUID value.

Remarks: Using this constructor creates a unique type that can be checked so that the value can be serialized as a GUID rather than a string value. If you do not use this you will get the following error:
Error: -2147204733 Property MetadataId of type System.Nullable`1[System.Guid] cannot be compared with a condition value of type System.String

The following is an example using this class.

var mdq = SDK.Metadata.Query;
var semp = mdq.SearchableEntityMetadataProperties;
var entityMetadataId = "70816501-edb9-4740-a16c-6a5efbc05d84";
var condition = new mdq.MetadataConditionExpression(semp.MetadataId, mdq.MetadataConditionOperator.Equals, new mdq.GuidValue(entityMetadataId));

SDK.Metadata.Query.LabelQueryExpression

Defines the languages for the labels to be retrieved for metadata items that have labels.

Constructor parameters:
  • languages: Required. An array of LCID Number values

Remarks: Use context.getUserLcid to get the user’s preferred language.

SDK.Metadata.Query.MetadataConditionExpression

Contains a condition expression used to filter the results of the metadata query.

Constructor parameters:
The recommended alias for SDK.Metadata.Query.ValueEnums is ve.

The following table shows the methods available for SDK.Metadata.Query.MetadataConditionExpression.

 

Method Description Returns Parameter Type

getConditionOperator()

Gets the operator used in this expression.

SDK.Metadata.Query.MetadataConditionOperator

NA

setConditionOperator(operator)

Sets the operator used in this expression.

Null

SDK.Metadata.Query.MetadataConditionOperator

getPropertyName()

Gets the name of the metadata property in the condition expression.

String

NA

setPropertyName(name)

Sets the name of the metadata property in the condition expression.

Null

One of the following depending on the type of query.

getValue()

Gets the value to compare.

String

NA

setValue(value)

Sets the value to compare.

Null

See the remarks about setting the value parameter of the SDK.Metadata.Query.MetadataConditionExpression constructor.

SDK.Metadata.Query.MetadataFilterExpression

Specifies complex condition and logical filter expressions used for filtering the results of a metadata query.

Constructor parameters:

The following table shows the methods available for SDK.Metadata.Query.MetadataFilterExpression

 

Method Description Returns Parameter Type

addCondition(propertyName, conditionOperator, value)

Adds a condition using the parameters to construct a SDK.Metadata.Query.MetadataConditionExpression

See Note on Shortcut Methods.

Null

See
SDK.Metadata.Query.MetadataConditionExpression constructor for information about the parameter types.

addCondition(conditionExpression)

Adds a condition using a SDK.Metadata.Query.MetadataConditionExpression

See Note on Shortcut Methods.

Null

SDK.Metadata.Query.MetadataConditionExpression

addConditions(conditionExpressions)

Adds an array of conditions.

See Note on Shortcut Methods.

Null

Array of SDK.Metadata.Query.MetadataConditionExpression

addFilter(filter)

Adds a filter.

See Note on Shortcut Methods.

Null

SDK.Metadata.Query.MetadataFilterExpression

getConditions()

Gets the collection of conditions.

SDK.Metadata.Query.Collection of SDK.Metadata.Query.MetadataConditionExpression instances

NA

setConditions(conditions)

Sets the collection of conditions.

Null

SDK.Metadata.Query.Collection of SDK.Metadata.Query.MetadataConditionExpression instances.

getFilterOperator()

Gets the operator.

SDK.Metadata.Query.LogicalOperator

NA

setFilterOperator(operator)

Sets the operator.

Null

SDK.Metadata.Query.LogicalOperator

getFilters()

Gets the collection of filters.

SDK.Metadata.Query.Collection of SDK.Metadata.Query.MetadataFilterExpression instances

NA

Note on Shortcut Methods

The SDK.Metadata.Query.MetadataFilterExpression addCondition, addConditions, and addFilter methods provide simpler access to internal SDK.Metadata.Query.Collection properties. In the following examples, mfe represents an SDK.Metadata.Query.MetadataFilterExpression instance.

The mfe.addCondition(propertyName, conditionOperator, value) method provides a shortcut for the following code:

mfe.getConditions().add(new SDK.Metadata.Query.MetadataConditionExpression(propertyName,conditionOperator, value))

The mfe.addCondition(conditionExpression) method is a shortcut for the following code:

mfe.getConditions().add(conditionExpression)

The mfe.addConditions(conditionExpressions) method provides a shortcut for the following code:

mfe.getConditions().addRange(conditionExpressions)

The mfe.addFilter(filter) method provides a shortcut for the following code:

mfe.getFilters().add(filter)

SDK.Metadata.Query.MetadataPropertiesExpression

Specifies the properties for which non-null values are returned from a query.

Constructor parameters:

The following table shows the methods available for SDK.Metadata.Query. MetadataPropertiesExpression

 

Method Description Returns Parameter Type

addProperty(propertyName)

Adds the property name to the properties to return.

Null

String

addProperties(propertyNames)

Adds an array of property names.

Null

Array of String

getAllProperties()

Gets the Boolean value indicating if all properties should be returned.

Boolean

NA

setAllProperties(value)

Sets the value indicating if all properties should be returned.

Null

Boolean

getPropertyNames()

Gets the Collection of property names to be returned.

SDK.Metadata.Query.Collection of String

NA

setPropertyNames(value)

Sets the properties to be returned.

Null

SDK.Metadata.Query.Collection of String

SDK.Metadata.Query.MetadataQueryExpression

This is a base class to encapsulate shared functionality exposed by SDK.Metadata.Query.AttributeQueryExpression, SDK.Metadata.Query.EntityQueryExpression, and SDK.Metadata.Query.RelationshipQueryExpression.

Constructor parameters:
For internal use only.

The following table shows the methods available for SDK.Metadata.Query.MetadataQueryExpression

 

Method Description Returns Parameter Type

getCriteria()

For internal use only.

SDK.Metadata.Query.MetadataFilterExpression

NA

setCriteria(criteria)

For internal use only.

Null

SDK.Metadata.Query.MetadataFilterExpression

getProperties()

For internal use only.

SDK.Metadata.Query.MetadataPropertiesExpression

NA

setProperties(properties)

For internal use only.

Null

SDK.Metadata.Query.MetadataPropertiesExpression

SDK.Metadata.Query.RelationshipQueryExpression

Defines a complex query to retrieve entity relationship metadata for entities retrieved using an SDK.Metadata.Query.EntityQueryExpression.

Constructor parameters:

The following table shows the methods available for SDK.Metadata.Query.RelationshipQueryExpression.

 

Method Description Returns Parameter Type

getCriteria()

Gets the filter criteria to be applied to relationships in the query.

SDK.Metadata.Query.MetadataFilterExpression

NA

setCriteria(criteria)

Sets the filter criteria to be applied to relationships in the query.

Null

SDK.Metadata.Query.MetadataFilterExpression

getProperties()

Gets the relationship properties to return in the query.

SDK.Metadata.Query.MetadataPropertiesExpression

NA

setProperties(properties)

Sets the relationship properties to return in the query.

Null

SDK.Metadata.Query.MetadataPropertiesExpression

SDK.Metadata.Query.RetrieveMetadataChangesRequest

Request to retrieve metadata defined in a query or changed metadata that matches the query.

Constructor parameters:

The following table shows the methods available for SDK.Metadata.Query.RetrieveMetadataChangesRequest

 

Method Description Returns Parameter Type

getQuery()

Gets the query.

SDK.Metadata.Query.EntityQueryExpression

NA

setQuery(query)

Sets the query.

Null

SDK.Metadata.Query.EntityQueryExpression

getClientVersionStamp()

Gets the clientVersionStamp.

String

NA

setClientVersionStamp(clientVersionStamp)

Sets the clientVersionStamp.

Null

String

Use a
SDK.Metadata.Query.RetrieveMetadataChangesResponse.
ServerVersionStamp from an earlier request to set this value or set it to Null.

getDeletedMetadataFilters

Gets the DeletedMetadataFilters.

Number

Value corresponds to an SDK.Metadata.Query.DeletedMetadataFilters enumeration value.

NA

setDeletedMetadataFilters(value)

Sets the DeletedMetadataFilters.

Null

Number

Use a SDK.Metadata.Query.DeletedMetadataFilters enumeration value to set this parameter.

SDK.Metadata.Query.RetrieveMetadataChangesResponse

The data returned from SDK.Metadata.Query.RetrieveMetadataChanges.

Properties
  • EntityMetadata: Array of EntityMetadata objects that meet the query filters.

  • ServerVersionStamp: String value identifying the time the query was processed. Pass this value as the SDK.Metadata.Query.RetrieveMetadataChangesRequest.clientVersionStamp parameter value for a subsequent request to return only the changes since the current request.

  • DeletedMetadata: Dictionary of metadata types. Each metadata type corresponds to one of the SDK.Metadata.Query.DeletedMetadataFilters enumerations. Each metadata type contains an array of GUID values representing the MetadataId values of the deleted items.

The following code shows how to remove deleted OptionSet options from a cached array (_optionLabelList) where each cached OptionSet has the MetadataId value set as an optionsetId property value.

if (typeof deletedMetadata.OptionSet != "undefined") {
        optionsetmetadataids = deletedMetadata.OptionSet;
        for (var i = 0; i < optionsetmetadataids.length; i++) {
            //Go backwards through the array so that indexes don't get
            // changed when items are removed.
            for (var n = _optionLabelList.length - 1; n >= 0; n--) {
                if (optionsetmetadataids[i] == _optionLabelList[n].optionsetId) {
                    _optionLabelList.splice(n, 1);
                    optionsRemoved++;
                }
            }
        }
    }

SDK.Metadata.Query.RetrieveMetadataChanges

Sends an asynchronous request with success and error callback functions to process the results.

Parameters
  • RetrieveMetadataChangesRequest: Required. The SDK.Metadata.Query.RetrieveMetadataChangesRequest containing the query to execute.

  • successCallBack: Required. A function that accepts a SDK.Metadata.Query.RetrieveMetadataChangesResponse as the first parameter and optionally an object to be passed through using the passThroughObject parameter.

  • errorCallBack: Required. A function that accepts a JavaScript Error object as the only parameter.

  • passThroughObject: Optional. Any object that you may want to have access to when you process results in the function passed using the successCallBack parameter. Because the request is performed asynchronously, you can use the passThroughObject to ensure that an object is in scope when the results are returned.

Enumerations

This section contains information about enumerations defined within the SDK.Metadata.Query JavaScript library.

SDK.Metadata.Query.AttributeMetadataProperties

The values in this enumeration refer to the names of properties for classes that inherit from the AttributeMetadata class that can be retrieved.

The recommended alias for this enumeration is amp.

  • AttributeOf

  • AttributeType

  • CalculationOf

  • CanBeSecuredForCreate

  • CanBeSecuredForRead

  • CanBeSecuredForUpdate

  • CanModifyAdditionalSettings

  • ColumnNumber

  • DefaultFormValue

  • DefaultValue

  • DeprecatedVersion

  • Description

  • DisplayName

  • EntityLogicalName

  • Format

  • ImeMode

  • IsAuditEnabled

  • IsCustomAttribute

  • IsCustomizable

  • IsManaged

  • IsPrimaryId

  • IsPrimaryName

  • IsRenameable

  • IsSecured

  • IsValidForAdvancedFind

  • IsValidForCreate

  • IsValidForRead

  • IsValidForUpdate

  • LinkedAttributeId

  • LogicalName

  • MaxLength

  • MaxValue

  • MetadataId

  • MinValue

  • OptionSet

  • Precision

  • PrecisionSource

  • RequiredLevel

  • SchemaName

  • Targets

  • YomiOf

SDK.Metadata.Query.DeletedMetadataFilters

The values in this enumeration refer to the DeletedMetadataFilters enumeration.

  • Default: 1

  • Entity: 1

  • Attribute: 2

  • Relationship: 4

  • Label: 8

  • OptionSet: 16

  • All: 31

SDK.Metadata.Query.EntityMetadataProperties

The values in this enumeration refer to names of properties of the EntityMetadata class that can be retrieved.

The recommended alias for this enumeration is emp.

  • ActivityTypeMask

  • Attributes

  • AutoRouteToOwnerQueue

  • CanBeInManyToMany

  • CanBePrimaryEntityInRelationship

  • CanBeRelatedEntityInRelationship

  • CanCreateAttributes

  • CanCreateCharts

  • CanCreateForms

  • CanCreateViews

  • CanModifyAdditionalSettings

  • CanTriggerWorkflow

  • Description

  • DisplayCollectionName

  • DisplayName

  • IconLargeName

  • IconMediumName

  • IconSmallName

  • IsActivity

  • IsActivityParty

  • IsAuditEnabled

  • IsAvailableOffline

  • IsChildEntity

  • IsConnectionsEnabled

  • IsCustomEntity

  • IsCustomizable

  • IsDocumentManagementEnabled

  • IsDuplicateDetectionEnabled

  • IsEnabledForCharts

  • IsImportable

  • IsIntersect

  • IsMailMergeEnabled

  • IsManaged

  • IsMappable

  • IsReadingPaneEnabled

  • IsRenameable

  • IsValidForAdvancedFind

  • IsValidForQueue

  • IsVisibleInMobile

  • LogicalName

  • ManyToManyRelationships

  • ManyToOneRelationships

  • MetadataId

  • ObjectTypeCode

  • OneToManyRelationships

  • OwnershipType

  • PrimaryIdAttribute

  • PrimaryNameAttribute

  • Privileges

  • RecurrenceBaseEntityLogicalName

  • ReportViewName

  • SchemaName

SDK.Metadata.Query.LogicalOperator

The recommended alias for this enumeration is mdq.LogicalOperator.

  • And

  • Or

SDK.Metadata.Query.MetadataConditionOperator

The recommended alias for this enumeration is mdq.MetadataConditionOperator.

  • Equals

  • NotEquals

  • In

  • NotIn

  • GreaterThan

  • LessThan

SDK.Metadata.Query.RelationshipMetadataProperties

The recommended alias for this enumeration is rmp.

  • AssociatedMenuConfiguration

  • CascadeConfiguration

  • Entity1AssociatedMenuConfiguration

  • Entity1IntersectAttribute

  • Entity1LogicalName

  • Entity2AssociatedMenuConfiguration

  • Entity2IntersectAttribute

  • Entity2LogicalName

  • IntersectEntityName

  • IsCustomizable

  • IsCustomRelationship

  • IsManaged

  • IsValidForAdvancedFind

  • MetadataId

  • ReferencedAttribute

  • ReferencedEntity

  • ReferencingAttribute

  • ReferencingEntity

  • RelationshipType

  • SchemaName

  • SecurityTypes

SDK.Metadata.Query.SearchableAttributeMetadataProperties

The recommended alias for this enumeration is samp.

  • AttributeOf

  • AttributeType

  • CalculationOf

  • CanBeSecuredForCreate

  • CanBeSecuredForRead

  • CanBeSecuredForUpdate

  • CanModifyAdditionalSettings

  • ColumnNumber

  • DefaultFormValue

  • DefaultValue

  • DeprecatedVersion

  • EntityLogicalName

  • Format

  • ImeMode

  • IsAuditEnabled

  • IsCustomAttribute

  • IsCustomizable

  • IsManaged

  • IsPrimaryId

  • IsPrimaryName

  • IsRenameable

  • IsSecured

  • IsValidForAdvancedFind

  • IsValidForCreate

  • IsValidForRead

  • IsValidForUpdate

  • LinkedAttributeId

  • LogicalName

  • MaxLength

  • MaxValue

  • MetadataId

  • MinValue

  • Precision

  • PrecisionSource

  • RequiredLevel

  • SchemaName

  • YomiOf

SDK.Metadata.Query.SearchableEntityMetadataProperties

The recommended alias for this enumeration is semp.

  • ActivityTypeMask

  • AutoRouteToOwnerQueue

  • CanBeInManyToMany

  • CanBePrimaryEntityInRelationship

  • CanBeRelatedEntityInRelationship

  • CanCreateAttributes

  • CanCreateCharts

  • CanCreateForms

  • CanCreateViews

  • CanModifyAdditionalSettings

  • CanTriggerWorkflow

  • IconLargeName

  • IconMediumName

  • IconSmallName

  • IsActivity

  • IsActivityParty

  • IsAuditEnabled

  • IsAvailableOffline

  • IsChildEntity

  • IsConnectionsEnabled

  • IsCustomEntity

  • IsCustomizable

  • IsDocumentManagementEnabled

  • IsDuplicateDetectionEnabled

  • IsEnabledForCharts

  • IsImportable

  • IsIntersect

  • IsMailMergeEnabled

  • IsManaged

  • IsMappable

  • IsReadingPaneEnabled

  • IsRenameable

  • IsValidForAdvancedFind

  • IsValidForQueue

  • IsVisibleInMobile

  • LogicalName

  • MetadataId

  • ObjectTypeCode

  • OwnershipType

  • PrimaryIdAttribute

  • PrimaryNameAttribute

  • RecurrenceBaseEntityLogicalName

  • ReportViewName

  • SchemaName

SDK.Metadata.Query.SearchableRelationshipMetadataProperties

The recommended alias for this enumeration is srmp.

  • Entity1IntersectAttribute

  • Entity1LogicalName

  • Entity2IntersectAttribute

  • Entity2LogicalName

  • IntersectEntityName

  • IsCustomizable

  • IsCustomRelationship

  • IsManaged

  • IsValidForAdvancedFind

  • MetadataId

  • ReferencedAttribute

  • ReferencedEntity

  • ReferencingAttribute

  • ReferencingEntity

  • RelationshipType

  • SchemaName

  • SecurityTypes

SDK.Metadata.Query.ValueEnums.AttributeRequiredLevel

The recommended alias for this enumeration is ve.AttributeRequiredLevel.

  • ApplicationRequired

  • None

  • Recommended

  • SystemRequired

SDK.Metadata.Query.ValueEnums.AttributeTypeCode

The recommended alias for this enumeration is ve.AttributeTypeCode.

  • BigInt

  • Boolean

  • CalendarRules

  • Customer

  • DateTime

  • Decimal

  • Double

  • EntityName

  • Integer

  • Lookup

  • ManagedProperty

  • Memo

  • Money

  • Owner

  • PartyList

  • Picklist

  • State

  • Status

  • String

  • Uniqueidentifier

  • Virtual

SDK.Metadata.Query.ValueEnums.RelationshipType

The recommended alias for this enumeration is ve. RelationshipType.

  • Default

  • ManyToManyRelationship

  • OneToManyRelationship

SDK.Metadata.Query.ValueEnums.DateTimeFormat

The recommended alias for this enumeration is ve.DateTimeFormat.

  • DateAndTime

  • DateOnly

SDK.Metadata.Query.ValueEnums.ImeMode

The recommended alias for this enumeration is ve.ImeMode.

  • Active

  • Auto

  • Disabled

  • Inactive

SDK.Metadata.Query.ValueEnums.IntegerFormat

The recommended alias for this enumeration is ve.IntegerFormat.

  • Duration

  • Language

  • Locale

  • None

  • TimeZone

SDK.Metadata.Query.ValueEnums.OwnershipType

The recommended alias for this enumeration is ve.OwnershipType.

  • None

  • OrganizationOwned

  • TeamOwned

  • UserOwned

SDK.Metadata.Query.ValueEnums.SecurityTypes

The recommended alias for this enumeration is ve.SecurityTypes.

  • Append

  • Inheritance

  • None

  • ParentChild

  • Pointer

SDK.Metadata.Query.ValueEnums.StringFormat

The recommended alias for this enumeration is ve.StringFormat.

  • Email

  • PhoneticGuide

  • Text

  • TextArea

  • TickerSymbol

  • Url

  • VersionNumber

Errors

The following errors can occur using this library.

Cannot Deserialize RetrieveMetadataChangesRequest parameter

This error occurs if Update Rollup 12 or the December 2012 Service Release is not installed. The full text of the error is:

The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://schemas.microsoft.com/xrm/2011/Contracts/Services:request. The InnerException message was 'Error in line 1 position 308. Element 'http://schemas.microsoft.com/xrm/2011/Contracts/Services:request' contains data from a type that maps to the name 'http://schemas.microsoft.com/xrm/2011/Contracts:RetrieveMetadataChangesRequest'. The deserializer has no knowledge of any type that maps to this name. Consider changing the implementation of the ResolveName method on your DataContractResolver to return a non-null value for name 'RetrieveMetadataChangesRequest' and namespace 'http://schemas.microsoft.com/xrm/2011/Contracts'.'. Please see InnerException for more details.

ExpiredVersionStamp

This error occurs when the SDK.Metadata.Query.RetrieveMetadataChangesRequest.clientVersionStamp parameter value is earlier than the time specified in the Organization.ExpireSubscriptionsInDays value. This error can also occur if the Organization.ExpireSubscriptionsInDays value is changed so that deleted metadata cannot be accurately tracked. The text of the error is:

ExpiredVersionStamp: The clientVersionStamp value passed with the request is before the time specified in the Organization.ExpireSubscriptionsInDays value. Reinitialize your metadata cache using a null clientVersionStamp parameter.

If you pass a clientVersionStamp parameter with your SDK.Metadata.Query.RetrieveMetadataChangesRequest, you should be prepared to catch this error and send a second request with a null clientVersionStamp parameter so you can re-initialize your metadata cache.

Conclusion

 

This article described a new SDK.Metadata.Query JavaScript library you can use to query metadata using the new classes in the managed code Microsoft.Xrm.Sdk.Metadata.Query namespace and the RetrieveMetadataChangesRequest message in Update Rollup 12 and the December 2012 Service Update. These new classes let developers retrieve just the metadata they need as well as detect changes in metadata over time.

This article also described when developers may need to use metadata in their code and what options exist to retrieve it.

Send comments about this article to Microsoft.

Community Additions

Show: