Compartilhar via


Sample: Retrieve entity metadata using JavaScript

 

Applies To: Dynamics CRM 2013

This sample code is for Microsoft Dynamics CRM 2013 and Microsoft Dynamics CRM Online. Download the Microsoft Dynamics CRM SDK package. It can be found in the following location in the download package:

SDK\SampleCode\JS\SOAPForJScript\SOAPForJScript\MetaDataDemo.htm

SDK\SampleCode\JS\SOAPForJScript\SOAPForJScript\Scripts\SDK.MetaData.js

Requirements

To use this code you must create Web resources for each file. The names for each Web resource must follow this pattern:

  • <solution publisher customization prefix>_/MetaDataDemo.htm

  • <solution publisher customization prefix>_/Scripts/SDK.MetaData.js

If you just want to see how this sample works, you can install (import) the SOAPEndpointforJScript_1_0_0_1_managed.zip managed solution included in the download files at SDK\SampleCode\JS\SOAPForJScript. If you install this managed solution and want to create the Web resources using the names in this topic, your solution publisher customization prefix cannot be “sample” unless you uninstall (delete) the managed solution.

Demonstrates

This sample shows how to how to use a sample JavaScript library that was created using the process described in Walkthrough: Use the Modern app SOAP endpoint with JavaScript. This library supports the use of the RetrieveAllEntitiesRequest and RetrieveEntityRequest messages using asynchronous JavaScript.

Example

The MetaDataDemo.htm page retrieves data using the SDK.MetaData.RetrieveAllEntities and SDK.MetaData.RetrieveEntity functions contained within the SDK.MetaData.js file.

When the page loads it retrieves information about all the entities in the system and then displays a list showing the SchemaName for each entity. When you click an entity list item, information about the entity attributes are retrieved and the attribute SchemaName is displayed. After the attributes have been retrieved, clicking an entity list item toggles the display of the list of attributes.


<html lang="en-US">
<head>
 <title>Metadata Demonstration</title>
  <script src="../ClientGlobalContext.js.aspx" type="text/javascript"></script>
 <script src="Scripts/SDK.MetaData.js" type="text/javascript"></script>
 <script type="text/javascript">
  // An unordered list element to add Entity list items to
  var results;
  // An area to display messages
  var message;

  // Alert flag to indicate the changes
  var alertFlag;

  function startSample() {
   ///<summary>
   /// Initializes the sample when the document is ready
   ///</summary>
   //Assign the global variables
   results = document.getElementById("results");
   message = document.getElementById("message");
   alertFlag = document.getElementById("dispalert");
   document.getElementById("btnstartSample").setAttribute("disabled", "disabled");
   //Retrieve entities
   SDK.Metadata.RetrieveAllEntities(SDK.Metadata.EntityFilters.Entity,
    false,
    successRetrieveAllEntities,
    errorRetrieveAllEntities);
   setText(message, "Loading...");

  }

  function successRetrieveAllEntities(entityMetadataCollection) {
   ///<summary>
   /// Receives the data from SDK.Metadata.RetrieveAllEntities and 
   /// appends a list item to results for each one.
   ///</summary>

   entityMetadataCollection.sort(function (a, b) {
    if (a.LogicalName < b.LogicalName)
    { return -1 }
    if (a.LogicalName > b.LogicalName)
    { return 1 }
    return 0;
   });

   for (var i = 0; i < entityMetadataCollection.length; i++) {

    var entity = entityMetadataCollection[i];
    var entityNode = document.createElement("li");
    var entitySpan = document.createElement("span");

    setText(entitySpan, entity.SchemaName);
    entitySpan.id = entity.LogicalName;
    entitySpan.title = "Click to Retrieve Attributes.";
    entitySpan.attributesRetrieved = false;
    // Add the event handler to retrieve attributes 
    entitySpan.onclick = retrieveAttributes;
    entitySpan.style.cursor = "pointer";

    entityNode.appendChild(entitySpan);
    results.appendChild(entityNode);

   }

   setText(message, entityMetadataCollection.length +
   " entities retrieved. Click each entity to retrieve the entity attributes.");
   if (alertFlag.checked == true)
    alert("Entity List Retrieved.");
  }
  function errorRetrieveAllEntities(error) {
   ///<summary>
   /// Displays the error returned from  SDK.Metadata.RetrieveAllEntities if it fails.
   ///</summary>
   setText(message, error.message);
   if (alertFlag.checked == true)
    alert("An Error occurred.");
  }

  function retrieveAttributes() {
   ///<summary>
   /// Retrieves attributes for the entity list item that is clicked
   ///</summary>
   if (this.attributesRetrieved == false) {
    var entityLogicalName = this.id;
    // Display an entity list item level notification while retrieving data.
    var notification = document.createElement("span");


    setText(notification, "   Retrieving attributes for " + getText(this) + "...");
    notification.id = entityLogicalName + "Notification";
    this.parentElement.appendChild(notification);

    SDK.Metadata.RetrieveEntity(SDK.Metadata.EntityFilters.Attributes,
    this.id,
    null,
    false,
    function (entityMetadata) { successRetrieveEntity(entityLogicalName, entityMetadata); },
    errorRetrieveEntity);


   }
   this.attributesRetrieved = true;
   this.title = "";
  }

  function successRetrieveEntity(logicalName, entityMetadata) {
   ///<summary>
   /// Retrieves attributes for the entity list item that is clicked
   ///</summary>

   // Update the entity list item notification when data is retrieved.

   entityMetadata.Attributes.sort(function (a, b) {
    if (a.LogicalName < b.LogicalName)
    { return -1 }
    if (a.LogicalName > b.LogicalName)
    { return 1 }
    return 0;
   });

   var notification = setText(document.getElementById(logicalName +
   "Notification"), "   Retrieved " + entityMetadata.Attributes.length + " attributes.");

   var attributeList = document.createElement("ul");

   for (var i = 0; i < entityMetadata.Attributes.length; i++) {
    var attribute = entityMetadata.Attributes[i];
    var attributeNode = document.createElement("li");
    setText(attributeNode, attribute.SchemaName);
    attributeList.appendChild(attributeNode);
   }
   // Access the entity list item element
   var entityNode = document.getElementById(logicalName).parentElement;

   entityNode.appendChild(attributeList);
   entityNode.attributesDisplayed = true;
   // Attach event handler to toggle display of attributes.
   entityNode.firstChild.onclick = toggleDisplayAttributes;
   entityNode.firstChild.title = "Click to hide attributes.";
   if (alertFlag.checked == true)
    alert(entityMetadata.SchemaName + " attributes retrieved.");
  }
  function errorRetrieveEntity(error) {
   ///<summary>
   /// Displays the error returned from SDK.Metadata.RetrieveEntity if it fails.
   ///</summary>
   setText(message, error.message);
   if (alertFlag.checked == true)
    alert("Error!");
  }

  function toggleDisplayAttributes() {
   ///<summary>
   /// toggles whether the list of attributes is displayed.
   ///</summary>

   if (this.parentElement.attributesDisplayed) {
    this.parentElement.lastChild.style.display = "none";
    this.parentElement.attributesDisplayed = false;
    this.title = "Click to show attributes.";

    if (alertFlag.checked == true)
     alert("Attributes were hidden.");
   }
   else {
    this.parentElement.lastChild.style.display = "block";
    this.parentElement.attributesDisplayed = true;
    this.title = "Click to hide attributes.";

    if (alertFlag.checked == true)
     alert("Attributes are displayed.");
   }

  }

  // setText and getText mitigate differences in how browsers set or get text content.
  function setText(node, text) {
   if (typeof (node.innerText) != "undefined") {
    node.innerText = text;
   }
   else {
    node.textContent = text;
   }

  }

  function getText(node) {
   if (typeof (node.innerText) != "undefined") {
    return node.innerText;
   }
   else {
    return node.textContent;
   }
  }

 </script>
</head>
<body style="font-family: Segoe UI;">
 <h1>
  Metadata Demonstration Sample</h1>
 <p>
  This form requires JavaScript and will update the page dynamically.</p>
 <p>
  <input id="dispalert" name="dispalert" type="checkbox" value="alert" /><label for="dispalert">Display alert window when data changes.</label></p>
 <p>
  <label id="lblstartSample" for="btnstartSample">
   Click to start the sample:
  </label>
  <input type="button" id="btnstartSample" name="btnstartSample" value="Start" onclick="startSample()" /></p>
 <div id="message">
 </div>
 <ul id="results">
 </ul>
</body>
</html>

Example

The SDK.MetaData.js file is a JScript library contains the SDK.MetaData.RetrieveAllEntities and SDK.MetaData.RetrieveEntity public functions used by the calling page. These functions send asynchronous requests and pass the results back to the function specified in the successCallBack parameter for each function.

The SDK.MetaData.EntityFilters provides a type of enumeration that corresponds to the EntityFilters enumeration used by RetrieveAllEntitiesRequest and RetrieveEntityRequest messages. The rest of the private functions are used to parse the XML returned in the request results.

This example shows how the SdkClientVersion value of ‘6.0’ must be included in the SOAP header in order to return image attributes as shown in the following snippet.

"<soapenv:Header><a:SdkClientVersion xmlns:a=\"https://schemas.microsoft.com/xrm/2011/Contracts\">6.0</a:SdkClientVersion></soapenv:Header>",


SDK = window.SDK || { __namespace: true };
SDK.Metadata = SDK.Metadata || { __namespace: true };

(function () {


 this.RetrieveAllEntities = function (EntityFilters, RetrieveAsIfPublished, successCallBack, errorCallBack, passThroughObject) {
  ///<summary>
  /// Sends an asynchronous RetrieveAllEntities Request to retrieve all entities in the system
  ///</summary>
  ///<returns>entityMetadataCollection</returns>
  ///<param name="EntityFilters" type="Number">
  /// SDK.Metadata.EntityFilters provides an enumeration for the filters available to filter which data is retrieved.
  /// Include only those elements of the entity you want to retrieve. Retrieving all parts of all entitities may take significant time.
  ///</param>
  ///<param name="RetrieveAsIfPublished" type="Boolean">
  /// Sets whether to retrieve the metadata that has not been published.
  ///</param>
  ///<param name="successCallBack" type="Function">
  /// The function that will be passed through and be called by a successful response.
  /// This function must accept the entityMetadataCollection as a parameter.
  ///</param>
  ///<param name="errorCallBack" type="Function">
  /// The function that will be passed through and be called by a failed response.
  /// This function must accept an Error object as a parameter.
  ///</param>
  ///<param name="passThroughObject" optional="true"  type="Object">
  /// An Object that will be passed through to as the second parameter to the successCallBack.
  ///</param>
  if ((typeof EntityFilters != "number") || (EntityFilters < 1 || EntityFilters > 15))
  { throw new Error("SDK.Metadata.RetrieveAllEntities EntityFilters must be a SDK.Metadata.EntityFilters value."); }
  if (typeof RetrieveAsIfPublished != "boolean")
  { throw new Error("SDK.Metadata.RetrieveAllEntities RetrieveAsIfPublished must be a boolean value."); }
  if (typeof successCallBack != "function")
  { throw new Error("SDK.Metadata.RetrieveAllEntities successCallBack must be a function."); }
  if (typeof errorCallBack != "function")
  { throw new Error("SDK.Metadata.RetrieveAllEntities errorCallBack must be a function."); }

  var entityFiltersValue = _evaluateEntityFilters(EntityFilters);

  var request = [
  "<soapenv:Envelope xmlns:soapenv=\"https://schemas.xmlsoap.org/soap/envelope/\">",
    //Allows retrieval if ImageAttributeMetadata objects
  "<soapenv:Header><a:SdkClientVersion xmlns:a=\"https://schemas.microsoft.com/xrm/2011/Contracts\">6.0</a:SdkClientVersion></soapenv:Header>",
   "<soapenv:Body>",
    "<Execute xmlns=\"https://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">",
     "<request i:type=\"a:RetrieveAllEntitiesRequest\" xmlns:a=\"https://schemas.microsoft.com/xrm/2011/Contracts\">",
      "<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">",
       "<a:KeyValuePairOfstringanyType>",
        "<b:key>EntityFilters</b:key>",
        "<b:value i:type=\"c:EntityFilters\" xmlns:c=\"https://schemas.microsoft.com/xrm/2011/Metadata\">" + _xmlEncode(entityFiltersValue) + "</b:value>",
       "</a:KeyValuePairOfstringanyType>",
       "<a:KeyValuePairOfstringanyType>",
        "<b:key>RetrieveAsIfPublished</b:key>",
        "<b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + _xmlEncode(RetrieveAsIfPublished.toString()) + "</b:value>",
       "</a:KeyValuePairOfstringanyType>",
      "</a:Parameters>",
      "<a:RequestId i:nil=\"true\" />",
      "<a:RequestName>RetrieveAllEntities</a:RequestName>",
    "</request>",
   "</Execute>",
  "</soapenv:Body>",
  "</soapenv:Envelope>"].join("");
  var req = new XMLHttpRequest();
  req.open("POST", _getUrl() + "/XRMServices/2011/Organization.svc/web", true);
  try { req.responseType = 'msxml-document'} catch(e){}
  req.setRequestHeader("Accept", "application/xml, text/xml, */*");
  req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
  req.setRequestHeader("SOAPAction", "https://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
  req.onreadystatechange = function () {
   if (req.readyState == 4 /* complete */) {
   req.onreadystatechange = null; //Addresses potential memory leak issue with IE
    if (req.status == 200) {
     //Success              
     var doc = req.responseXML;
     try{_setSelectionNamespaces(doc);}catch(e){}
     var entityMetadataNodes = _selectNodes(doc, "//c:EntityMetadata");
     var entityMetadataCollection = [];
     for (var i = 0; i < entityMetadataNodes.length; i++) {
      var a = _objectifyNode(entityMetadataNodes[i]);
      a._type = "EntityMetadata";
      entityMetadataCollection.push(a);
     }

     successCallBack(entityMetadataCollection, passThroughObject);
    }
    else {
     errorCallBack(_getError(req));
    }
   }
  };
  req.send(request);

 };

 this.RetrieveEntity = function (EntityFilters, LogicalName, MetadataId, RetrieveAsIfPublished, successCallBack, errorCallBack, passThroughObject) {
  ///<summary>
  /// Sends an asynchronous RetrieveEntity Request to retrieve a specific entity
  ///</summary>
  ///<returns>entityMetadata</returns>
  ///<param name="EntityFilters" type="Number">
  /// SDK.Metadata.EntityFilters provides an enumeration for the filters available to filter which data is retrieved.
  /// Include only those elements of the entity you want to retrieve. Retrieving all parts of all entitities may take significant time.
  ///</param>
  ///<param name="LogicalName" optional="true" type="String">
  /// The logical name of the entity requested. A null value may be used if a MetadataId is provided.
  ///</param>
  ///<param name="MetadataId" optional="true" type="String">
  /// A null value or an empty guid may be passed if a LogicalName is provided.
  ///</param>
  ///<param name="RetrieveAsIfPublished" type="Boolean">
  /// Sets whether to retrieve the metadata that has not been published.
  ///</param>
  ///<param name="successCallBack" type="Function">
  /// The function that will be passed through and be called by a successful response.
  /// This function must accept the entityMetadata as a parameter.
  ///</param>
  ///<param name="errorCallBack" type="Function">
  /// The function that will be passed through and be called by a failed response.
  /// This function must accept an Error object as a parameter.
  ///</param>
  ///<param name="passThroughObject" optional="true"  type="Object">
  /// An Object that will be passed through to as the second parameter to the successCallBack.
  ///</param>
  if ((typeof EntityFilters != "number") || (EntityFilters < 1 || EntityFilters > 15))
  { throw new Error("SDK.Metadata.RetrieveEntity EntityFilters must be a SDK.Metadata.EntityFilters value."); }
  if (LogicalName == null &amp;&amp; MetadataId == null) {
   throw new Error("SDK.Metadata.RetrieveEntity requires either the LogicalName or MetadataId parameter not be null.");
  }
  if (LogicalName != null) {
   if (typeof LogicalName != "string")
   { throw new Error("SDK.Metadata.RetrieveEntity LogicalName must be a string value."); }
   MetadataId = "00000000-0000-0000-0000-000000000000";
  }
  if (MetadataId != null &amp;&amp; LogicalName == null) {
   if (typeof MetadataId != "string")
   { throw new Error("SDK.Metadata.RetrieveEntity MetadataId must be a string value."); }
  }
  if (typeof RetrieveAsIfPublished != "boolean")
  { throw new Error("SDK.Metadata.RetrieveEntity RetrieveAsIfPublished must be a boolean value."); }
  if (typeof successCallBack != "function")
  { throw new Error("SDK.Metadata.RetrieveEntity successCallBack must be a function."); }
  if (typeof errorCallBack != "function")
  { throw new Error("SDK.Metadata.RetrieveEntity errorCallBack must be a function."); }
  var entityFiltersValue = _evaluateEntityFilters(EntityFilters);

  var entityLogicalNameValueNode = "";
  if (LogicalName == null)
  { entityLogicalNameValueNode = "<b:value i:nil=\"true\" />"; }
  else
  { entityLogicalNameValueNode = "<b:value i:type=\"c:string\"   xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + _xmlEncode(LogicalName.toLowerCase()) + "</b:value>"; }
  var request = [
  "<soapenv:Envelope xmlns:soapenv=\"https://schemas.xmlsoap.org/soap/envelope/\">",
    //Allows retrieval if ImageAttributeMetadata objects
  "<soapenv:Header><a:SdkClientVersion xmlns:a=\"https://schemas.microsoft.com/xrm/2011/Contracts\">6.0</a:SdkClientVersion></soapenv:Header>",
   "<soapenv:Body>",
    "<Execute xmlns=\"https://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">",
     "<request i:type=\"a:RetrieveEntityRequest\" xmlns:a=\"https://schemas.microsoft.com/xrm/2011/Contracts\">",
      "<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">",
       "<a:KeyValuePairOfstringanyType>",
        "<b:key>EntityFilters</b:key>",
        "<b:value i:type=\"c:EntityFilters\" xmlns:c=\"https://schemas.microsoft.com/xrm/2011/Metadata\">" + _xmlEncode(entityFiltersValue) + "</b:value>",
       "</a:KeyValuePairOfstringanyType>",
       "<a:KeyValuePairOfstringanyType>",
        "<b:key>MetadataId</b:key>",
        "<b:value i:type=\"ser:guid\"  xmlns:ser=\"https://schemas.microsoft.com/2003/10/Serialization/\">" + _xmlEncode(MetadataId) + "</b:value>",
       "</a:KeyValuePairOfstringanyType>",
       "<a:KeyValuePairOfstringanyType>",
        "<b:key>RetrieveAsIfPublished</b:key>",
        "<b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + _xmlEncode(RetrieveAsIfPublished.toString()) + "</b:value>",
       "</a:KeyValuePairOfstringanyType>",
       "<a:KeyValuePairOfstringanyType>",
        "<b:key>LogicalName</b:key>",
         entityLogicalNameValueNode,
       "</a:KeyValuePairOfstringanyType>",
      "</a:Parameters>",
      "<a:RequestId i:nil=\"true\" />",
      "<a:RequestName>RetrieveEntity</a:RequestName>",
     "</request>",
    "</Execute>",
   "</soapenv:Body>",
  "</soapenv:Envelope>"].join("");
  var req = new XMLHttpRequest();
  req.open("POST", _getUrl() + "/XRMServices/2011/Organization.svc/web", true);
  try { req.responseType = 'msxml-document'} catch(e){}
  req.setRequestHeader("Accept", "application/xml, text/xml, */*");
  req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
  req.setRequestHeader("SOAPAction", "https://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
  req.onreadystatechange = function () {
   if (req.readyState == 4 /* complete */) {
   req.onreadystatechange = null; //Addresses potential memory leak issue with IE
    if (req.status == 200) {
     var doc = req.responseXML;
     try{_setSelectionNamespaces(doc);}catch(e){}
     var a = _objectifyNode(_selectSingleNode(doc, "//b:value"));
     a._type = "EntityMetadata";
     successCallBack(a, passThroughObject);
    }
    else {
     //Failure
     errorCallBack(_getError(req));
    }
   }

  };
  req.send(request);


 };

 this.RetrieveAttribute = function (EntityLogicalName, LogicalName, MetadataId, RetrieveAsIfPublished, successCallBack, errorCallBack, passThroughObject) {
  ///<summary>
  /// Sends an asynchronous RetrieveAttribute Request to retrieve a specific entity
  ///</summary>
  ///<returns>AttributeMetadata</returns>
  ///<param name="EntityLogicalName"  optional="true" type="String">
  /// The logical name of the entity for the attribute requested. A null value may be used if a MetadataId is provided.
  ///</param>
  ///<param name="LogicalName" optional="true" type="String">
  /// The logical name of the attribute requested. 
  ///</param>
  ///<param name="MetadataId" optional="true" type="String">
  /// A null value may be passed if an EntityLogicalName and LogicalName is provided.
  ///</param>
  ///<param name="RetrieveAsIfPublished" type="Boolean">
  /// Sets whether to retrieve the metadata that has not been published.
  ///</param>
  ///<param name="successCallBack" type="Function">
  /// The function that will be passed through and be called by a successful response.
  /// This function must accept the entityMetadata as a parameter.
  ///</param>
  ///<param name="errorCallBack" type="Function">
  /// The function that will be passed through and be called by a failed response.
  /// This function must accept an Error object as a parameter.
  ///</param>
  ///<param name="passThroughObject" optional="true"  type="Object">
  /// An Object that will be passed through to as the second parameter to the successCallBack.
  ///</param>
  if (EntityLogicalName == null &amp;&amp; LogicalName == null &amp;&amp; MetadataId == null) {
   throw new Error("SDK.Metadata.RetrieveAttribute requires either the EntityLogicalName and LogicalName  parameters or the MetadataId parameter not be null.");
  }
  if (MetadataId != null &amp;&amp; EntityLogicalName == null &amp;&amp; LogicalName == null) {
   if (typeof MetadataId != "string")
   { throw new Error("SDK.Metadata.RetrieveEntity MetadataId must be a string value."); }
  }
  else
  { MetadataId = "00000000-0000-0000-0000-000000000000"; }
  if (EntityLogicalName != null) {
   if (typeof EntityLogicalName != "string") {
    { throw new Error("SDK.Metadata.RetrieveAttribute EntityLogicalName must be a string value."); }
   }
  }
  if (LogicalName != null) {
   if (typeof LogicalName != "string") {
    { throw new Error("SDK.Metadata.RetrieveAttribute LogicalName must be a string value."); }
   }

  }
  if (typeof RetrieveAsIfPublished != "boolean")
  { throw new Error("SDK.Metadata.RetrieveAttribute RetrieveAsIfPublished must be a boolean value."); }
  if (typeof successCallBack != "function")
  { throw new Error("SDK.Metadata.RetrieveAttribute successCallBack must be a function."); }
  if (typeof errorCallBack != "function")
  { throw new Error("SDK.Metadata.RetrieveAttribute errorCallBack must be a function."); }

  var entityLogicalNameValueNode;
  if (EntityLogicalName == null) {
   entityLogicalNameValueNode = "<b:value i:nil=\"true\" />";
  }
  else {
   entityLogicalNameValueNode = "<b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + _xmlEncode(EntityLogicalName.toLowerCase()) + "</b:value>";
  }
  var logicalNameValueNode;
  if (LogicalName == null) {
   logicalNameValueNode = "<b:value i:nil=\"true\" />";
  }
  else {
   logicalNameValueNode = "<b:value i:type=\"c:string\"   xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + _xmlEncode(LogicalName.toLowerCase()) + "</b:value>";
  }
  var request = [
  "<soapenv:Envelope xmlns:soapenv=\"https://schemas.xmlsoap.org/soap/envelope/\">",
  //Allows retrieval if ImageAttributeMetadata objects
  "<soapenv:Header><a:SdkClientVersion xmlns:a=\"https://schemas.microsoft.com/xrm/2011/Contracts\">6.0</a:SdkClientVersion></soapenv:Header>",
   "<soapenv:Body>",
    "<Execute xmlns=\"https://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">",
     "<request i:type=\"a:RetrieveAttributeRequest\" xmlns:a=\"https://schemas.microsoft.com/xrm/2011/Contracts\">",
      "<a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">",
       "<a:KeyValuePairOfstringanyType>",
        "<b:key>EntityLogicalName</b:key>",
         entityLogicalNameValueNode,
       "</a:KeyValuePairOfstringanyType>",
       "<a:KeyValuePairOfstringanyType>",
        "<b:key>MetadataId</b:key>",
        "<b:value i:type=\"ser:guid\"  xmlns:ser=\"https://schemas.microsoft.com/2003/10/Serialization/\">" + _xmlEncode(MetadataId) + "</b:value>",
       "</a:KeyValuePairOfstringanyType>",
        "<a:KeyValuePairOfstringanyType>",
        "<b:key>RetrieveAsIfPublished</b:key>",
      "<b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">" + _xmlEncode(RetrieveAsIfPublished.toString()) + "</b:value>",
       "</a:KeyValuePairOfstringanyType>",
       "<a:KeyValuePairOfstringanyType>",
        "<b:key>LogicalName</b:key>",
         logicalNameValueNode,
       "</a:KeyValuePairOfstringanyType>",
      "</a:Parameters>",
      "<a:RequestId i:nil=\"true\" />",
      "<a:RequestName>RetrieveAttribute</a:RequestName>",
     "</request>",
    "</Execute>",
   "</soapenv:Body>",
  "</soapenv:Envelope>"].join("");
  var req = new XMLHttpRequest();
  req.open("POST", _getUrl() + "/XRMServices/2011/Organization.svc/web", true);
      try { req.responseType = 'msxml-document'} catch(e){}
  req.setRequestHeader("Accept", "application/xml, text/xml, */*");
  req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
  req.setRequestHeader("SOAPAction", "https://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
  req.onreadystatechange = function () {
   if (req.readyState == 4 /* complete */) {
   req.onreadystatechange = null; //Addresses potential memory leak issue with IE
    if (req.status == 200) {
     //Success
     var doc = req.responseXML;
     try{_setSelectionNamespaces(doc);}catch(e){}
     var a = _objectifyNode(_selectSingleNode(doc, "//b:value"));

     successCallBack(a, passThroughObject);
    }
    else {
     //Failure
     errorCallBack(_getError(req));
    }
   }
  };
  req.send(request);


 };

 this.EntityFilters = function () {
  /// <summary>SDK.Metadata.EntityFilters enum summary</summary>
  /// <field name="Default" type="Number" static="true">enum field summary for Default</field>
  /// <field name="Entity" type="Number" static="true">enum field summary for Entity</field>
  /// <field name="Attributes" type="Number" static="true">enum field summary for Attributes</field>
  /// <field name="Privileges" type="Number" static="true">enum field summary for Privileges</field>
  /// <field name="Relationships" type="Number" static="true">enum field summary for Relationships</field>
  /// <field name="All" type="Number" static="true">enum field summary for All</field>
  throw new Error("Constructor not implemented this is a static enum.");
 };



 var _arrayElements = ["Attributes",
  "ManyToManyRelationships",
  "ManyToOneRelationships",
  "OneToManyRelationships",
  "Privileges",
  "LocalizedLabels",
  "Options",
  "Targets"];

  function _getError(resp) {
  ///<summary>
  /// Private function that attempts to parse errors related to connectivity or WCF faults.
  ///</summary>
  ///<param name="resp" type="XMLHttpRequest">
  /// The XMLHttpRequest representing failed response.
  ///</param>

  //Error descriptions come from https://support.microsoft.com/kb/193625
  if (resp.status == 12029)
  { return new Error("The attempt to connect to the server failed."); }
  if (resp.status == 12007)
  { return new Error("The server name could not be resolved."); }
  var faultXml = resp.responseXML;
  var errorMessage = "Unknown (unable to parse the fault)";
  if (typeof faultXml == "object") {

   var faultstring = null;
   var ErrorCode = null;

   var bodyNode = faultXml.firstChild.firstChild;

   //Retrieve the fault node
   for (var i = 0; i < bodyNode.childNodes.length; i++) {
    var node = bodyNode.childNodes[i];

    //NOTE: This comparison does not handle the case where the XML namespace changes
    if ("s:Fault" == node.nodeName) {
     for (var j = 0; j < node.childNodes.length; j++) {
      var testNode = node.childNodes[j];
      if ("faultstring" == testNode.nodeName) {
       faultstring = _getNodeText(testNode);
      }
      if ("detail" == testNode.nodeName) {
       for (var k = 0; k < testNode.childNodes.length; k++) {
        var orgServiceFault = testNode.childNodes[k];
        if ("OrganizationServiceFault" == orgServiceFault.nodeName) {
         for (var l = 0; l < orgServiceFault.childNodes.length; l++) {
          var ErrorCodeNode = orgServiceFault.childNodes[l];
          if ("ErrorCode" == ErrorCodeNode.nodeName) {
           ErrorCode = _getNodeText(ErrorCodeNode);
           break;
          }
         }
        }
       }

      }
     }
     break;
    }

   }
  }
  if (ErrorCode != null &amp;&amp; faultstring != null) {
   errorMessage = "Error Code:" + ErrorCode + " Message: " + faultstring;
  }
  else {
   if (faultstring != null) {
    errorMessage = faultstring;
   }
  }
  return new Error(errorMessage);
 };

 function _Context() {
  var errorMessage = "Context is not available.";
  if (typeof GetGlobalContext != "undefined")
  { return GetGlobalContext(); }
  else {
   if (typeof Xrm != "undefined") {
    return Xrm.Page.context;
   }
   else
   { return new Error(errorMessage); }
  }
 };

 function _getUrl() {
     var url = _Context().getClientUrl();
  return url;
 };

 function _evaluateEntityFilters(EntityFilters) {
  var entityFilterArray = [];
  if ((1 &amp; EntityFilters) == 1) {
   entityFilterArray.push("Entity");
  }
  if ((2 &amp; EntityFilters) == 2) {
   entityFilterArray.push("Attributes");
  }
  if ((4 &amp; EntityFilters) == 4) {
   entityFilterArray.push("Privileges");
  }
  if ((8 &amp; EntityFilters) == 8) {
   entityFilterArray.push("Relationships");
  }
  return entityFilterArray.join(" ");
 };

 function _isMetadataArray(elementName) {
  for (var i = 0; i < _arrayElements.length; i++) {
   if (elementName == _arrayElements[i]) {
    return true;
   }
  }
  return false;
 };

 function _objectifyNode(node) {
  //Check for null
  if (node.attributes != null &amp;&amp; node.attributes.length == 1) {
   if (node.attributes.getNamedItem("i:nil") != null &amp;&amp; node.attributes.getNamedItem("i:nil").nodeValue == "true") {
    return null;
   }
  }

  //Check if it is a value
  if ((node.firstChild != null) &amp;&amp; (node.firstChild.nodeType == 3)) {
   var nodeName = _getNodeName(node);

   switch (nodeName) {
    //Integer Values 
    case "ActivityTypeMask":
    case "ObjectTypeCode":
    case "ColumnNumber":
    case "DefaultFormValue":
    case "MaxValue":
    case "MinValue":
    case "MaxLength":
    case "Order":
    case "Precision":
    case "PrecisionSource":
    case "LanguageCode":
     return parseInt(node.firstChild.nodeValue, 10);
     // Boolean values
    case "AutoRouteToOwnerQueue":
    case "CanBeChanged":
    case "CanTriggerWorkflow":
    case "IsActivity":
    case "IsAIRUpdated":
    case "IsActivityParty":
    case "IsAvailableOffline":
    case "IsChildEntity":
    case "IsCustomEntity":
    case "IsCustomOptionSet":   
    case "IsDocumentManagementEnabled":
    case "IsEnabledForCharts":
    case "IsGlobal":
    case "IsImportable":
    case "IsIntersect":
    case "IsManaged":
    case "IsReadingPaneEnabled":
    case "IsValidForAdvancedFind":
    case "CanBeSecuredForCreate":
    case "CanBeSecuredForRead":
    case "CanBeSecuredForUpdate":
    case "IsCustomAttribute":
    case "IsManaged":
    case "IsPrimaryId":
    case "IsPrimaryName":
    case "IsSecured":
    case "IsValidForCreate":
    case "IsValidForRead":
    case "IsValidForUpdate":
    case "IsCustomRelationship":
    case "CanBeBasic":
    case "CanBeDeep":
    case "CanBeGlobal":
    case "CanBeLocal":
     return (node.firstChild.nodeValue == "true") ? true : false;
     //OptionMetadata.Value and BooleanManagedProperty.Value and AttributeRequiredLevelManagedProperty.Value
    case "Value":
     //BooleanManagedProperty.Value
     if ((node.firstChild.nodeValue == "true") || (node.firstChild.nodeValue == "false")) {
      return (node.firstChild.nodeValue == "true") ? true : false;
     }
     //AttributeRequiredLevelManagedProperty.Value
     if (
  (node.firstChild.nodeValue == "ApplicationRequired") ||
  (node.firstChild.nodeValue == "None") ||
  (node.firstChild.nodeValue == "Recommended") ||
  (node.firstChild.nodeValue == "SystemRequired")
  ) {
      return node.firstChild.nodeValue;
     }
     var numberValue = parseInt(node.firstChild.nodeValue, 10);
     if (isNaN(numberValue)) {
         //FormatName.Value
         return node.firstChild.nodeValue;
     }
     else {
         //OptionMetadata.Value
         return numberValue;
     }
     break;
    //String values 
    default:
     return node.firstChild.nodeValue;
   }

  }

  //Check if it is a known array
  if (_isMetadataArray(_getNodeName(node))) {
   var arrayValue = [];

   for (var i = 0; i < node.childNodes.length; i++) {
    var objectTypeName;
    if ((node.childNodes[i].attributes != null) &amp;&amp; (node.childNodes[i].attributes.getNamedItem("i:type") != null)) {
     objectTypeName = node.childNodes[i].attributes.getNamedItem("i:type").nodeValue.split(":")[1];
    }
    else {

     objectTypeName = _getNodeName(node.childNodes[i]);
    }

    var b = _objectifyNode(node.childNodes[i]);
    b._type = objectTypeName;
    arrayValue.push(b);

   }

   return arrayValue;
  }

    //Null entity description labels are returned as <label/> - not using i:nil = true;
  if(node.childNodes.length == 0)
  {
  return null;
  }

  //Otherwise return an object
  var c = {};
  if (node.attributes.getNamedItem("i:type") != null) {
   c._type = node.attributes.getNamedItem("i:type").nodeValue.split(":")[1];
  }
  for (var i = 0; i < node.childNodes.length; i++) {
   if (node.childNodes[i].nodeType == 3) {
    c[_getNodeName(node.childNodes[i])] = node.childNodes[i].nodeValue;
   }
   else {
    c[_getNodeName(node.childNodes[i])] = _objectifyNode(node.childNodes[i]);
   }

  }
  return c;
 };

 function _selectNodes(node, XPathExpression) {
  if (typeof (node.selectNodes) != "undefined") {
   return node.selectNodes(XPathExpression);
  }
  else {
   var output = [];
   var XPathResults = node.evaluate(XPathExpression, node, _NSResolver, XPathResult.ANY_TYPE, null);
   var result = XPathResults.iterateNext();
   while (result) {
    output.push(result);
    result = XPathResults.iterateNext();
   }
   return output;
  }
 };

 function _selectSingleNode(node, xpathExpr) {
  if (typeof (node.selectSingleNode) != "undefined") {
   return node.selectSingleNode(xpathExpr);
  }
  else {
   var xpe = new XPathEvaluator();
   var xPathNode = xpe.evaluate(xpathExpr, node, _NSResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
   return (xPathNode != null) ? xPathNode.singleNodeValue : null;
  }
 };

 function _selectSingleNodeText(node, xpathExpr) {
  var x = _selectSingleNode(node, xpathExpr);
  if (_isNodeNull(x))
  { return null; }
  if (typeof (x.text) != "undefined") {
   return x.text;
  }
  else {
   return x.textContent;
  }
 };

 function _getNodeText(node) {
  if (typeof (node.text) != "undefined") {
   return node.text;
  }
  else {
   return node.textContent;
  }
 };

 function _isNodeNull(node) {
  if (node == null)
  { return true; }
  if ((node.attributes.getNamedItem("i:nil") != null) &amp;&amp; (node.attributes.getNamedItem("i:nil").value == "true"))
  { return true; }
  return false;
 };

 function _getNodeName(node) {
  if (typeof (node.baseName) != "undefined") {
   return node.baseName;
  }
  else {
   return node.localName;
  }
 };

 function _setSelectionNamespaces(doc)
 {
 var namespaces = [
 "xmlns:s='https://schemas.xmlsoap.org/soap/envelope/'",
 "xmlns:a='https://schemas.microsoft.com/xrm/2011/Contracts'",
 "xmlns:i='http://www.w3.org/2001/XMLSchema-instance'",
 "xmlns:b='http://schemas.datacontract.org/2004/07/System.Collections.Generic'",
 "xmlns:c='https://schemas.microsoft.com/xrm/2011/Metadata'" 
 ];
 doc.setProperty("SelectionNamespaces",namespaces.join(" "));

 }

 function _NSResolver(prefix) {
  var ns = {
   "s": "https://schemas.xmlsoap.org/soap/envelope/",
   "a": "https://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": "https://schemas.microsoft.com/xrm/2011/Metadata"
  };
  return ns[prefix] || null;
 };

 function _xmlEncode(strInput) {
  var c;
  var XmlEncode = '';
  if (strInput == null) {
   return null;
  }
  if (strInput == '') {
   return '';
  }
  for (var cnt = 0; cnt < strInput.length; cnt++) {
   c = strInput.charCodeAt(cnt);
   if (((c > 96) &amp;&amp; (c < 123)) ||
            ((c > 64) &amp;&amp; (c < 91)) ||
            (c == 32) ||
            ((c > 47) &amp;&amp; (c < 58)) ||
            (c == 46) ||
            (c == 44) ||
            (c == 45) ||
            (c == 95)) {
    XmlEncode = XmlEncode + String.fromCharCode(c);
   }
   else {
    XmlEncode = XmlEncode + '&amp;#' + c + ';';
   }
  }
  return XmlEncode;
 };

}).call(SDK.Metadata);

//SDK.Metadata.EntityFilters
// this enum is written this way to enable Visual Studio IntelliSense
SDK.Metadata.EntityFilters.prototype = {
 Default: 1,
 Entity: 1,
 Attributes: 2,
 Privileges: 4,
 Relationships: 8,
 All: 15
};
SDK.Metadata.EntityFilters.Default = 1;
SDK.Metadata.EntityFilters.Entity = 1;
SDK.Metadata.EntityFilters.Attributes = 2;
SDK.Metadata.EntityFilters.Privileges = 4;
SDK.Metadata.EntityFilters.Relationships = 8;
SDK.Metadata.EntityFilters.All = 15;
SDK.Metadata.EntityFilters.__enum = true;
SDK.Metadata.EntityFilters.__flags = true;

See Also

Walkthrough: Use the Modern app SOAP endpoint with JavaScript
Use the Modern app SOAP endpoint for modern applications with web resources
Use web service data in web resources (OData and Modern app SOAP endpoint)
Technical Article: Using Option Set Options with the REST Endpoint - JScript