Compartilhar via


Passo a passo: Usar o ponto de extremidade do SOAP do aplicativo moderno com JavaScript

 

Publicado: novembro de 2016

Aplicável a: Dynamics CRM 2015

Este passo a passo mostra a criação de uma biblioteca do JavaScript para usar com o ponto de extremidade SOAP com os recursos da Web. No momento, o Atualização do Microsoft Dynamics CRM 2015 e Microsoft Dynamics CRM Online 2015 não fornece as bibliotecas do JavaScript que você pode usar para chamar mensagens disponíveis usando o ponto de extremidade SOAP. Este passo a passo mostra como criar uma biblioteca do JScript para a mensagem Assign usando o método de Serviço da organização Execute. Qualquer outra mensagem usando o método Execute seguirá um padrão semelhante. A criação de uma biblioteca do JavaScript para qualquer mensagem exigirá um processo semelhante. Para ver um exemplo de uma biblioteca do JavaScript desenvolvida usando esse processo, consulte Exemplo: Recuperar metadados da entidade usando o JavaScript.

Observação

Para uma biblioteca de amostra do JavaScript usando o ponto de extremidade SOAP, consulte a Biblioteca Sdk.Soap.js. A biblioteca Sdk.Soap.js foi criada usando o processo descrito aqui.

O processo consiste em capturar as solicitações e respostas HTTP enviadas de um aplicativo de console do código gerenciado e depois criar uma biblioteca do JavaScript com as funções para enviar as mesmas solicitações e processar respostas semelhantes. É comum usar um aplicativo como o Fiddler para capturar as solicitações e respostas HTTP, mas o Fiddler e aplicativos similares não podem capturar o tráfego HTTP criptografado usado para o Microsoft Dynamics CRM 2015 local. A solução de exemplo do SOAPLogger fornecida captura as solicitações HTTP antes de serem criptografadas e as respostas HTTP depois de terem sido descriptografadas. A solução de exemplo SOAPLogger funciona para o Atualização do Microsoft Dynamics CRM 2015 e Microsoft Dynamics CRM Online 2015.SOAPLogger também filtra todo o tráfego HTTP que não seja relevante para a tarefa de criação de uma biblioteca JScript.

Este passo a passo guia você pelas seguintes tarefas:

  1. No Capture o exemplo de solicitação e resposta HTTP você edita o método Run do exemplo SOAPLogger para realizar uma solicitação Assign usando o código gerenciado.

  2. Então, você executará a solução SOAPLogger para gerar informações sobre as solicitações HTTP enviadas e as respostas recebidas.

  3. No Criar uma biblioteca do JScript você criará uma biblioteca do JScript com base no tráfego capturado HTTP para enviar e receber a mensagem Assign usando o método Serviço da organização Execute.

  4. No Teste a biblioteca do JScript você testará a biblioteca do JScript para confirmar se pode ser usada para atribuir registros.

  5. No Criar um recurso da Web interativo você criará um recurso da Web do HTML que utiliza a biblioteca para atribuir registros da Account para um usuário selecionado, como mostrado na imagem a seguir.

    Página Atribuir Contas

Uma solução gerenciada que representa este passo a passo concluído está disponível no pacote SDK em SDK\SampleCode\JS\SOAPForJScript\SOAPEndpointforJScript_1_0_0_1_managed.zip. Baixe o pacote do SDK do Microsoft Dynamics CRM. Você pode instalar (importar) essa solução e visualizar os resultados concluídos. Por se tratar de uma solução gerenciada, você pode facilmente desinstalar (excluir) para removê-la completamente do seu sistema.

O SDK\SampleCode\JS\SOAPForJScript\SOAPForJScript.sln é uma solução Visual Studio contendo os arquivos HTML e JS com o código deste passo a passo.

Pré-requisitos

  • Você deve ser capaz de escrever o código gerenciado correspondente às funções que deseja realizar usando o JScript.

  • Você precisa do acesso ao exemplo SOAPLogger disponível nos arquivos de download do SDK em SDK\SampleCode\CS\Client\SOAPLogger.

    Observação

    O exemplo SOAPLogger no SDK do Microsoft Dynamics CRM está disponível apenas para o Microsoft Visual C#. Se preferir uma versão do Microsoft Visual Basic .NET , consulte Microsoft Dynamics CRM VB.Net SoapLogger no CodePlex.

  • Você precisará do Microsoft Visual Studio para executar a solução SOAPLogger.

  • Você precisa de um bom conhecimento em JScript e programação assíncrona usando o XMLHttpRequest.

Capture o exemplo de solicitação e resposta HTTP

Edite a solução SOAPLogger para adicionar código para executar um AssignRequest usando o SoapLoggerOrganizationService. O SoapLoggerOrganizationService herda do IOrganizationService e adiciona a capacidade de gerar um arquivo de log que exibe o tráfego HTTP enviado e recebido relevante.

  1. Usando o Microsoft Visual Studio, abra a solução SOAPLogger localizada no SDK\SampleCode\CS\Client\SOAPLogger\SOAPLogger.sln.

  2. No arquivo SoapLogger.cs, localize o método Run como mostrado no exemplo a seguir:

    
    public void Run(ServerConnection.Configuration serverConfig)
    {
     try
     {
    
      // Connect to the Organization service. 
      // The using statement assures that the service proxy will be properly disposed.
         using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri, serverConfig.HomeRealmUri, serverConfig.Credentials, serverConfig.DeviceCredentials))
      {
       // This statement is required to enable early-bound type support.
       _serviceProxy.EnableProxyTypes();
    
       IOrganizationService service = (IOrganizationService)_serviceProxy;
    
    
       using (StreamWriter output = new StreamWriter("output.txt"))
       {
    
        SoapLoggerOrganizationService slos = new SoapLoggerOrganizationService(serverConfig.OrganizationUri, service, output);
    
        //Add the code you want to test here:
        // You must use the SoapLoggerOrganizationService 'slos' proxy rather than the IOrganizationService proxy you would normally use.
    
    
    
       }
    
    
      }
    
     }
    
     // Catch any service fault exceptions that Microsoft Dynamics CRM throws.
     catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>)
     {
      // You can handle an exception here or pass it back to the calling method.
      throw;
     }
    }
    
  3. Identifique um id válido de um registro do SystemUser e o ID do registro de um Account não atribuído a esse usuário.

    Dica

    Para obter Id de qualquer registro no aplicativo, abra o registro e use o comando Copiar um link. Cole o link no Bloco de Notas e isole a parte que contém o valor do parâmetro id excluindo as chaves codificadas (“%7b” = “{”) e (“%7d” = “}”). Por exemplo, o seguinte representa um URL para um registro do Account.<your organization root url>/main.aspx?etc=1&id=%7bF2CA52DE-552D-E011-A8FB-00155DB059BE%7d&pagetype=entityrecord>. O valor do ID F2CA52DE-552D-E011-A8FB-00155DB059BE.

    Use esses valores para substituir os valores de espaço reservado no código abaixo e adicione o código ao método de execução onde indicado. Para obter mais informações sobre a solicitação Assign, consulte AssignRequest.

    Guid userId = new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
    Guid accountId = new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
    AssignRequest assign = new AssignRequest{Assignee = new EntityReference(SystemUser.EntityLogicalName, userId),Target = new EntityReference(Account.EntityLogicalName, accountId)};
    AssignResponse assignResp = (AssignResponse)slos.Execute(assign);
    
  4. Pressione F5 para depurar o aplicativo. Insira informações sobre o servidor e suas credenciais de autenticação. Se o código for executado com sucesso, o registro da conta será agora atribuído ao usuário que você especificou. Para obter mais informações sobre a execução de código de exemplo, consulte Executar um único programa usando os serviços Web do Microsoft Dynamics CRM 2015

  5. Nas pastas do projeto SOAPLogger, navegue até as pastas bin e Debug e procure pelo arquivo output.txt.

  6. Abra o arquivo output.txt e revise o conteúdo. Ele deve ser algo como o seguinte, exceto que os valores reais da GUID substituirão o espaço reservado “XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX”.

    HTTP REQUEST
    --------------------------------------------------
    POST <your server root>/XRMServices/2011/Organization.svc/web
    Content-Type: text/xml; charset=utf-8
    SOAPAction: https://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute
    
    <s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
     <s:Body>
      <Execute xmlns="https://schemas.microsoft.com/xrm/2011/Contracts/Services"
               xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
       <request i:type="b:AssignRequest"
                xmlns:a="https://schemas.microsoft.com/xrm/2011/Contracts"
                xmlns:b="https://schemas.microsoft.com/crm/2011/Contracts">
        <a:Parameters xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
         <a:KeyValuePairOfstringanyType>
          <c:key>Target</c:key>
          <c:value i:type="a:EntityReference">
           <a:Id>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</a:Id>
           <a:LogicalName>account</a:LogicalName>
           <a:Name i:nil="true" />
          </c:value>
         </a:KeyValuePairOfstringanyType>
         <a:KeyValuePairOfstringanyType>
          <c:key>Assignee</c:key>
          <c:value i:type="a:EntityReference">
           <a:Id>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</a:Id>
           <a:LogicalName>systemuser</a:LogicalName>
           <a:Name i:nil="true" />
          </c:value>
         </a:KeyValuePairOfstringanyType>
        </a:Parameters>
        <a:RequestId i:nil="true" />
        <a:RequestName>Assign</a:RequestName>
       </request>
      </Execute>
     </s:Body>
    </s:Envelope>
    --------------------------------------------------
    
    HTTP RESPONSE
    --------------------------------------------------
    <s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
     <s:Body>
      <ExecuteResponse xmlns="https://schemas.microsoft.com/xrm/2011/Contracts/Services"
                       xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
       <ExecuteResult i:type="b:AssignResponse"
                      xmlns:a="https://schemas.microsoft.com/xrm/2011/Contracts"
                      xmlns:b="https://schemas.microsoft.com/crm/2011/Contracts">
        <a:ResponseName>Assign</a:ResponseName>
        <a:Results xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
       </ExecuteResult>
      </ExecuteResponse>
     </s:Body>
    </s:Envelope>
    --------------------------------------------------
    
  7. Observe a localização das variáveis que você transmitiu usando o código, incluindo o nome lógico da entidade Account.

Você capturou com sucesso as partes relevantes do tráfego do HTTP que executaram a operação Assign.

Criar uma biblioteca do JScript

A maneira exata como você deseja construir a sua biblioteca depende de você. Cada JScript deve ter os seguintes elementos:

  • Uma estratégia para ajudar a garantir que o nome de qualquer função seja exclusivo.

  • Um meio de recuperar o URL para o ponto de extremidade SOAP para recursos da Web.

  • Métodos distintos para enviar a solicitação e receber a resposta de forma assíncrona.

  • Uma função para processar quaisquer falhas WCF retornadas.

A seguinte biblioteca do JScript inclui os seguintes elementos e inclui as funções assignRequest e assignResponse para usar a mensagem Assign com base nas solicitações e respostas HTTP capturadas utilizando o SOAPLogger.


if (typeof (SDK) == "undefined")
{ SDK = { __namespace: true }; }
//This will establish a more unique namespace for functions in this library. This will reduce the 
// potential for functions to be overwritten due to a duplicate name when the library is loaded.
SDK.SOAPSamples = {
 _getClientUrl: function () {
  ///<summary>
  /// Returns the URL for the SOAP endpoint using the context information available in the form
  /// or HTML Web resource.
  ///</summary
  var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
  var clientUrl = "";
  if (typeof GetGlobalContext == "function") {
   var context = GetGlobalContext();
   clientUrl = context.getClientUrl();
  }
  else {
   if (typeof Xrm.Page.context == "object") {
    clientUrl = Xrm.Page.context.getClientUrl();
   }
   else
   { throw new Error("Unable to access the server URL"); }
  }

  return clientUrl + OrgServicePath;
 },
 assignRequest: function (Assignee, Target, Type, successCallback, errorCallback) {
  ///<summary>
  /// Sends the Assign Request
  ///</summary>
  this._parameterCheck(Assignee, "GUID", "The SDK.SOAPSamples.assignRequest method Assignee parameter must be a string Representing a GUID value.");
  ///<param name="Assignee" Type="String">
  /// The GUID representing the  System user that the record will be assigned to.
  ///</param>
  this._parameterCheck(Target, "GUID", "The SDK.SOAPSamples.assignRequest method Target parameter must be a string Representing a GUID value.");
  ///<param name="Target" Type="String">
  /// The GUID representing the user-owned entity record that will be assigne to the Assignee.
  ///</param>
  this._parameterCheck(Type, "String", "The SDK.SOAPSamples.assignRequest method Type parameter must be a string value.");
  Type = Type.toLowerCase();
  ///<param name="Type" Type="String">
  /// The Logical name of the user-owned entity. For example, 'account'.
  ///</param>
  if (successCallback != null)
  this._parameterCheck(successCallback, "Function", "The SDK.SOAPSamples.assignRequest method successCallback parameter must be a function.");
  ///<param name="successCallback" Type="Function">
  /// The function to perform when an successfult response is returned.
  ///</param>
  this._parameterCheck(errorCallback, "Function", "The SDK.SOAPSamples.assignRequest method errorCallback parameter must be a function.");
  ///<param name="errorCallback" Type="Function">
  /// The function to perform when an error is returned.
  ///</param>
  //The request is simply the soap envelope captured by the SOAPLogger with variables added for the 
  // values passed. All quotations must be escaped to create valid JScript strings.
  var request = [];

     request.push("<s:Envelope xmlns:s=\"https://schemas.xmlsoap.org/soap/envelope/\">");
     request.push("<s:Body>");
     request.push("<Execute xmlns=\"https://schemas.microsoft.com/xrm/2011/Contracts/Services\"");
     request.push(" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">");
     request.push("<request i:type=\"b:AssignRequest\"");
     request.push(" xmlns:a=\"https://schemas.microsoft.com/xrm/2011/Contracts\"");
     request.push(" xmlns:b=\"https://schemas.microsoft.com/crm/2011/Contracts\">");
     request.push("<a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">");
     request.push("<a:KeyValuePairOfstringanyType>");
     request.push("<c:key>Target</c:key>");
     request.push("<c:value i:type=\"a:EntityReference\">");
     request.push("<a:Id>" + this._xmlEncode(Target) + "</a:Id>");
     request.push("<a:LogicalName>" + this._xmlEncode(Type) + "</a:LogicalName>");
     request.push("<a:Name i:nil=\"true\" />");
     request.push("</c:value>");
     request.push("</a:KeyValuePairOfstringanyType>");
     request.push("<a:KeyValuePairOfstringanyType>");
     request.push("<c:key>Assignee</c:key>");
     request.push("<c:value i:type=\"a:EntityReference\">");
     request.push("<a:Id>" + this._xmlEncode(Assignee) + "</a:Id>");
     request.push("<a:LogicalName>systemuser</a:LogicalName>");
     request.push("<a:Name i:nil=\"true\" />");
     request.push("</c:value>");
     request.push("</a:KeyValuePairOfstringanyType>");
     request.push("</a:Parameters>");
     request.push("<a:RequestId i:nil=\"true\" />");
     request.push("<a:RequestName>Assign</a:RequestName>");
     request.push("</request>");
     request.push("</Execute>");
     request.push("</s:Body>");
     request.push("</s:Envelope>");

  var req = new XMLHttpRequest();
  req.open("POST", SDK.SOAPSamples._getClientUrl(), true)
  // Responses will return XML. It isn't possible to return JSON.
  req.setRequestHeader("Accept", "application/xml, text/xml, */*");
  req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
  req.setRequestHeader("SOAPAction", "https://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
  req.onreadystatechange = function () { SDK.SOAPSamples.assignResponse(req, successCallback, errorCallback); };
  req.send(request.join(""));

 },
 assignResponse: function (req, successCallback, errorCallback) {
  ///<summary>
  /// Recieves the assign response
  ///</summary>
  ///<param name="req" Type="XMLHttpRequest">
  /// The XMLHttpRequest response
  ///</param>
  ///<param name="successCallback" Type="Function">
  /// The function to perform when an successfult response is returned.
  /// For this message no data is returned so a success callback is not really necessary.
  ///</param>
  ///<param name="errorCallback" Type="Function">
  /// The function to perform when an error is returned.
  /// This function accepts a JScript error returned by the _getError function
  ///</param>
     if (req.readyState == 4) {
         req.onreadystatechange = null; //avoids memory leaks
   if (req.status == 200) {
    if (successCallback != null)
    { successCallback(); }
   }
   else {
    errorCallback(SDK.SOAPSamples._getError(req.responseXML));
   }
  }
 },
 _getError: function (faultXml) {
  ///<summary>
  /// Parses the WCF fault returned in the event of an error.
  ///</summary>
  ///<param name="faultXml" Type="XML">
  /// The responseXML property of the XMLHttpRequest response.
  ///</param>
  var errorMessage = "Unknown Error (Unable to parse the fault)";
  if (typeof faultXml == "object") {
   try {
    var bodyNode = faultXml.firstChild.firstChild;
    //Retrieve the fault node
    for (var i = 0; i < bodyNode.childNodes.length; i++) {
     var node = bodyNode.childNodes[i];

     //NOTE: This comparison does not handle the case where the XML namespace changes
     if ("s:Fault" == node.nodeName) {
      for (var j = 0; j < node.childNodes.length; j++) {
       var faultStringNode = node.childNodes[j];
       if ("faultstring" == faultStringNode.nodeName) {
        errorMessage = faultStringNode.textContent;
        break;
       }
      }
      break;
     }
    }
   }
   catch (e) { };
  }
  return new Error(errorMessage);
 },
 _xmlEncode: function (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;
 },
 _parameterCheck: function (parameter, type, errorMessage) {
  switch (type) {
   case "String":
    if (typeof parameter != "string") {
     throw new Error(errorMessage);
    }
    break;
   case "Function":
    if (typeof parameter != "function") {
     throw new Error(errorMessage);
    }
    break;
   case "EntityFilters":
    var found = false;
    for (x in this.EntityFilters) {
     if (this.EntityFilters[x] == parameter) {
      found = true;
      break;
     }
    }
    if (!found) {
     throw new Error(errorMessage);
    }
    break;
   case "Boolean":
    if (typeof parameter != "boolean") {
     throw new Error(errorMessage);
    }
    break;
   case "GUID":
    var re = new RegExp("[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}");
    if (!(typeof parameter == "string" &amp;&amp; re.test(parameter))) {
     throw new Error(errorMessage);
    }

    break;
   default:
    throw new Error("An invalid type parameter value was passed to the SDK.MetaData._parameterCheck function.");
    break;
  }
 },
 __namespace: true
};

Teste a biblioteca do JScript

Depois de ter preparado a sua biblioteca do JScript você deve executar alguns testes iniciais para confirmar se ela funciona como esperado. Como a autenticação ocorre apenas dentro do aplicativo, você deve criar um recurso de script da Web no Microsoft Dynamics CRM 2015 usando o conteúdo de sua biblioteca. Para usar as funções na biblioteca você precisará de um elemento da interface do usuário, um formulário ou recurso da Web do HTML para chamar as funções do JScript na biblioteca. O procedimento a seguir descreve como usar um recurso da Web simples do HTML para testar as funções na biblioteca.

  1. Crie um documento HTML usando o código a seguir:

    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
     <title>Assign Test</title>
     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <script src="../ClientGlobalContext.js.aspx" type="text/javascript"></script>
     <script src="Scripts/SDK.REST.js" type="text/javascript"></script>
     <script src="Scripts/SDK.SOAPSample.Assign.js" type="text/javascript"></script>
     <script type="text/javascript">
      var resultsArea = null;
      var userid;
      var accountid;
      var userLookup;
      var accountLookup;
      var accountsToShow = 10;
      var usersToShow = 10;
      var users = [];
      var accounts = [];
    
      document.onreadystatechange = function () {
       ///<summary>
       /// Initializes the sample when the document is ready
       ///</summary>
       if (document.readyState == "complete") {
        userid = document.getElementById("userid");
        accountid = document.getElementById("accountid");
        resultsArea = document.getElementById("results");
        userLookup = document.getElementById("userLookup");
        accountLookup = document.getElementById("accountLookup");
    
        populateUserLookup();
        populateAccountLookup();
    
       }
      }
    
      function testAssign() {
       //The field to enter the user id of the person the account record should be assigned to.
       userid.value;
       // The field to enter the account id of the account record to assign to the user
       accountid.value;
       // Since the response does not include any data to parse, simply display a success message.
       var successCallback = function () { setText(resultsArea, "Success!"); };
       // Display the error from the message passed back from the response.
       var errorCallback = function (error) { setText(resultsArea,"errorCallback error: "+error.message); };
       // Call the function
       try {
        SDK.SOAPSamples.assignRequest(userid.value, accountid.value, "account", successCallback, errorCallback);
       }
       catch (e) {
        setText(resultsArea, e.message);
       }
    
      }
    
      function populateUserLookup() {
       SDK.REST.retrieveMultipleRecords("SystemUser",
       "$top=" + usersToShow + "&amp;$select=FullName,SystemUserId&amp;$filter=FullName ne 'INTEGRATION' and FullName ne 'SYSTEM'",
       function (results) {
        for (var i = 0; i < results.length; i++) {
         users.push(results[i]);
        }
       },
       function (error) {
        alert(error.message);
       },
       function () {
        for (var i = 0; i < users.length; i++) {
         var user = users[i];
         userLookup.options[i] = new Option(user.FullName, user.SystemUserId);
        }
        userid.value = userLookup.options[0].value;
    
        userLookup.onchange = function () {
         userid.value = userLookup.options[userLookup.selectedIndex].value;
         clearMessage();
        };
    
       });
      }
    
      function populateAccountLookup() {
       SDK.REST.retrieveMultipleRecords("Account",
        "$top=" + accountsToShow + "&amp;$select=AccountId,Name,OwnerId",
       function (results) {
        for (var i = 0; i < results.length; i++) {
         accounts.push(results[i]);
    
        }
       },
       function (error) {
        alert(error.message);
       },
       function () {
        for (var i = 0; i < accounts.length; i++) {
         var account = accounts[i];
         accountLookup.options[i] = new Option(account.Name + " : " + account.OwnerId.Name, account.AccountId);
    
        }
        accountid.value = accountLookup.options[0].value;
    
        accountLookup.onchange = function () {
         accountid.value = accountLookup.options[accountLookup.selectedIndex].value;
         clearMessage();
        };
       });
      }
    
      function clearMessage() {
       setText(resultsArea, "");
      }
    
      function setText(element, text) {
       if (typeof (element.innerText) != "undefined") {
        element.innerText = text;
       }
       else {
        element.textContent = text;
       }
    
      }
    
     </script>
    </head>
    <body>
     <table>
      <tr>
       <td>
        <label for="userid">
         SystemUserId:</label>
       </td>
       <td>
        <input id="userid" type="text" style="width:270px;"  />
       </td>
       <td>
       <select id="userLookup"></select>
       </td>
      </tr>
      <tr>
       <td>
        <label for="accountid">
         AccountId:</label>
       </td>
       <td>
        <input id="accountid" type="text" style="width:270px;" />
       </td>
          <td>
       <select id="accountLookup"></select>
       </td>
      </tr>
     </table>
    
    
     <button id="testAssign" title="Click this button to test the testAssign function." onclick="testAssign();">
      Test Assign</button>
     <div id="results">
      &amp;nbsp;</div>
    </body>
    </html>
    
  2. Crie recurso da Web do HTML usando esse código. O nome completo do recurso de Web do HTML dependerá do prefixo de personalização de sua solução. Assumindo que o seu prefixo de personalização da solução seja "novo", nomeie esse desse recurso da Web do HTML como “new_/AssignTest.htm”. O prefixo de personalização específico usado não tem impacto neste exemplo, desde que todos os recursos da Web usem o mesmo prefixo de personalização.

  3. Crie um recurso da Web do script usando o conteúdo da biblioteca do JScript. Nomeie este recurso da Web como “new_/Scripts/SDK.SOAPSample.Assign.js”.

  4. Publique todas as personalizações e abra o recurso da Web do new_/AssignTest.htm. Clique no botão Visualizar.

  5. Usando o mesmo processo que você usou na etapa três do procedimento No text is specified for bookmark or legacy link 'c9a435ab-a4cb-4e0c-9ef7-b7ba66278407#BKMK_EditSoapLogger'., identifique valores válidos de Usuário do Sistema e ID de registro da conta e cole-os na página. Em seguida, clique em Test Assign para confirmar se obtém uma resposta com sucesso.

  6. Insira valores válidos para confirmar se o erro está sendo analisado corretamente.

    Por exemplo, se você digitar "Armazenamento A (exemplo)" em vez do ID de uma conta, deve esperar a seguinte mensagem de erro:

    The formatter threw an exception while trying to deserialize the message: 
    There was an error while trying to deserialize parameter https://schemas.microsoft.com/xrm/2011/Contracts/Services:request. 
    The InnerException message was 'There was an error deserializing the object of type Microsoft.Xrm.Sdk.OrganizationRequest. 
    The value 'A Store (sample)' cannot be parsed as the type 'Guid'.'.  Please see InnerException for more details.
    

    Se não houver um registro da conta para AccountId, a mensagem esperada seria:

    Account With Id = 883c3084-1f2f-e011-ad66-00155dba3814 Does Not Exist
    

Criar um recurso da Web interativo

A próxima etapa é usar a biblioteca do JScript em um script de formulário, no comando da faixa de opções ou em um recurso da Web. O seguinte exemplo de código representa um recurso da Web do HTML que utiliza o ponto de extremidade REST para recuperar listas de SystemUser e registros de Account para fornecer uma interface de usuário interativa para atribuir registros de contas de usuários. Essa página usa o recurso da Web do script Scripts/SDK.SOAPSample.Assign.js e um recurso da Web do script que usa a biblioteca json2.js para dar suporte ao uso de objetos REST com o ponto de extremidade JSON. A biblioteca do SDK.REST.js é usada para recuperar dados usando o ponto de extremidade REST.


<html lang="en-us">
<head>
 <title>Assign Accounts Page</title>
 <meta http-equiv="X-UA-Compatible" content="IE=edge" />
 <style type="text/css">
  body
  {
   font-family: Segoe UI;
   background-color: #EFF2F6;
  }
  .dataTable
  {
   border-collapse: collapse;
   border: 1px solid black;
  }
  .tableHead
  {
   background-color: #C0C0C0;
   width: 100%;
  }
  .grid
  {
   border-bottom: 1px solid black;
  }
  td
  {
   padding-left: 5px;
   padding-right: 5px;
  }
  #accountList
  {
   background-color: White;
  }
  #checkboxCol
  {
   border-right: 1px solid black;
   width: 20px;
  }
  #nameCol
  {
   border-right: 1px solid black;
   width: 300px;
  }
  #ownerCol
  {
   width: 300px;
  }
 </style>
 <script src="../ClientGlobalContext.js.aspx" type="text/javascript"></script>
 <script src="Scripts/SDK.REST.js" type="text/javascript"></script>
 <script src="Scripts/SDK.SOAPSample.Assign.js" type="text/javascript"></script>
 <script type="text/javascript">
  //Set variables for page elements
  var userSelect; //The select control used to select the user to assign records to.
  var accountList; //The tbody element that rows will be added to for each retrieved account
  var selectAll; //The checkbox to select all the retrieved accounts
  var btnAssign; //The button to assign assign the accounts
  var tableCaption; //A label hidden on load
  var dataTable; //the table element hidden on load
  var alertFlag; // Alert flag to indicate the changes
  var users = []; //SystemUser records retrieved
  var accounts = []; //Accounts not assigned to the currently selected user.
  var accountsToShow = 5;
  var suppressRetrievedAccountsAlert = false;
  var accountsToAssign = [];
  var userId = null;

  function startSample() {
   ///<summary>
   /// Starts the sample
   ///</summary>
   alertFlag = document.getElementById("dispalert");
   userSelect = document.getElementById("userList");
   //A new set of a 5 accounts will be retrieved when the user changes
   userSelect.onchange = getAccounts;

   accountList = document.getElementById("accountList");
   selectAll = document.getElementById("selectAll");
   //When the select all checkbox is clicked, toggle the selection for each row of the table.
   selectAll.onclick = toggleSelectAllRecords;
   btnAssign = document.getElementById("btnAssign");
   //Add a helper function to enable or disable the assign button.
   btnAssign.setEnabled = setEnabled;
   //Set the event handler to the Assign button
   btnAssign.onclick = assignAccounts;
   tableCaption = document.getElementById("tableCaption");
   dataTable = document.getElementById("dataTable");
   var divSample = document.getElementById("divSample");
   //Load the list of users
   getUsers();
   divSample.style.display = "block";

   document.getElementById("btnStart").setAttribute("disabled", "disabled");

  }
  function getUsers() {
   SDK.REST.retrieveMultipleRecords("SystemUser",
   "$select=FullName,SystemUserId&amp;$filter=FullName ne 'INTEGRATION' and FullName ne 'SYSTEM'",
   function (results) {
    for (var i = 0; i < results.length; i++) {
     users.push(results[i]);
    }
   },
   function (error) {
    showMessage(error.message);
   },
   function () {
    if (users.length > 1) {
     for (var i = 0; i < users.length; i++) {
      var user = users[i];
      userSelect.options[i + 1] = new Option(user.FullName, user.SystemUserId);
     }
     userSelect.removeAttribute("disabled");

     if (alertFlag.checked == true) {
      alert(users.length + " system users retrieved");
     }

    }
    else {
     var notification = "This sample requires that more than one user is available in the organization.";
     showMessage(notification);
     if (alertFlag.checked == true) {
      alert("This sample requires that more than one user is available in the organization.");
     }

    }
   });
  }
  function getAccounts() {
   //Clear out any records displayed in the table
   clearAccountList();
   var selectedUserId = userSelect.options[userSelect.selectedIndex].value;
   if (selectedUserId != "none") {

    SDK.REST.retrieveMultipleRecords("Account",
    "$top=" + accountsToShow + "&amp;$select=AccountId,Name,OwnerId&amp;$filter=OwnerId/Id ne (guid'" + encodeURIComponent(selectedUserId) + "')",
    function (results) {
     accounts.length = 0;
     for (var i = 0; i < results.length; i++) {
      accounts.push(results[i]);
     }
    },
    function (error) {
     showMessage(error.message);
    },
    function () {
     //onComplete
     if (accounts.length > 0) {

      for (var i = 0; i < accounts.length; i++) {
       var account = accounts[i];

       var row = document.createElement("tr");
       row.setAttribute("class", "grid");
       row.setAttribute("id", account.AccountId);
       var checkboxCell = document.createElement("td");
       var checkbox = document.createElement("input");
       checkbox.setAttribute("type", "checkbox");
       checkbox.onclick = validateAssignButton;
       checkboxCell.appendChild(checkbox);
       row.appendChild(checkboxCell);
       var nameCell = document.createElement("td");
       setText(nameCell, account.Name);
       row.appendChild(nameCell);
       var userNameCell = document.createElement("td");
       setText(userNameCell, account.OwnerId.Name);
       row.appendChild(userNameCell);
       accountList.appendChild(row);



      }

      if (alertFlag.checked == true &amp;&amp; !suppressRetrievedAccountsAlert) {
       alert(accounts.length + " account records retrieved.");
       suppressRetrievedAccountsAlert = false;

      }
     }
     else {
      //If no records are returned display a message.
      clearAccountList();
      var row = document.createElement("tr");
      var cell = document.createElement("td");
      cell.setAttribute("colSpan", "3");
      setText(cell, "No Accounts were retrieved");
      row.appendChild(cell);
      accountList.appendChild(row);

     }
     //Show any of the UI elements that are initially hidden
     setVisibleUIElements(true);
    });
   }
   else { setVisibleUIElements(false); }
  }
  function assignAccounts() {
   ///<summary>
   /// queues the selected accounts to be assigned sequentially
   ///</summary>
   userId = userSelect.options[userSelect.selectedIndex].value;

   var checkboxes = accountList.getElementsByTagName("input");
   for (var i = checkboxes.length - 1; i >= 0; i--) {
    if (checkboxes[i].checked) {
     var accountId = checkboxes[i].parentElement.parentElement.id;
     accountsToAssign.push(accountId);
    }
   }
   assignNextAccount();
   selectAll.checked = false;
  }
  function assignNextAccount() {
   /// <summary>Assigns the queued accounts</summary>
   //Prevents a generic SQL error that can occur when too many assign requests occur in rapid succession
   if (accountsToAssign.length > 0) {
    SDK.SOAPSamples.assignRequest(userId, accountsToAssign.shift(), "account", function () {
     assignNextAccount();
    }, function (error) {
     showMessage("There was an error assigning the account with Id :" + accountId + ". The error message is " + error.message + ".");
     assignNextAccount();
    });

   }
   else {
    suppressRetrievedAccountsAlert = true;
    getAccounts();
    btnAssign.setEnabled(false)
    if (alertFlag.checked == true) {
     alert("Record assignment completed and next set of records retrieved.");
    }
   }


  }
  function showMessage(message) {
   ///<summary>
   /// Helper function to display message on the page if necessary.
   ///</summary
   var dvMessage = document.createElement("div");
   dvMessage.innerHTML = SDK.SOAPSamples._xmlEncode(message);
   document.getElementById("status").appendChild(dvMessage);
  }
  function clearAccountList() {
   ///<summary>
   /// Helper function remove rows from the Account List table.
   ///</summary
   for (var i = (accountList.rows.length - 1) ; i >= 0; i--) {
    accountList.deleteRow(i);
   }
   accounts.length = 0;

  }
  function toggleSelectAllRecords() {
   ///<summary>
   /// Helper function to toggle all selected rows in the account list table.
   ///</summary
   var checkboxes = accountList.getElementsByTagName("input");
   for (var i = 0; i < checkboxes.length; i++) {
    checkboxes[i].checked = this.checked;
   }
   btnAssign.setEnabled(this.checked);

  }
  function validateAssignButton() {
   ///<summary>
   /// Helper function to enable the Assign Records button when rows are selected.
   ///</summary
   if (this.checked == true)
   { btnAssign.setEnabled(true); }
   else {
    selectAll.checked = false;
    var checkboxes = accountList.getElementsByTagName("input");
    var checked = false;
    for (var i = 0; i < checkboxes.length; i++) {
     if (checkboxes[i].checked == true) {
      checked = true;
      break;
     }
    }
    btnAssign.setEnabled(checked);
   }
  }
  function setEnabled(bool) {
   ///<summary>
   /// Helper method attached to the Assign button to make it easier to enable/disable the button.
   ///</summary
   if (bool)
   { this.removeAttribute("disabled"); }
   else
   { this.setAttribute("disabled", "disabled"); }
  }
  function setVisibleUIElements(display) {
   ///<summary>
   /// Helper function to show those UI elements initially hidden.
   ///</summary
   if (display) {
    show(tableCaption);
    show(dataTable);
    show(btnAssign);
   }
   else {
    hide(tableCaption);
    hide(dataTable);
    hide(btnAssign);
   }

  }
  function show(element) {
   if (element.tagName.toLowerCase() == "table") {
    element.style.display = "table";
   }
   else {
    element.style.display = "block";
   }

  }
  function hide(element) {
   element.style.display = "none";
  }
  // setText  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;
   }

  }

 </script>
</head>
<body>
 <h1>
  Assign Accounts Sample
 </h1>
 <p>
  This page requires JavaScript and will update dynamically.
 </p>
 <p>
  <input id="dispalert" name="dispalert" type="checkbox" value="alert" /><label for="dispalert">Display alert window when data changes.</label>
 </p>
 <p>
  Click the <b>Start</b> button to begin the sample.
 </p>
 <input type="button" id="btnStart" name="btnStart" value="Start" onclick="startSample()" />
 <div id="divSample" style="display: none">
  <label for="userList">
   User:
  </label>
  <select id="userList" name="userList" title="Select a system user from this list." disabled>
   <option value="none">Select a User...</option>
  </select>
  <p id="tableCaption" style="display: none;">
   Top 5 Accounts not assigned to the selected user:
  </p>
  <table class="dataTable" id="dataTable" style="display: none; width: 100%;">
   <thead>
    <tr class="tableHead">
     <th scope="col" id="checkboxCol">
      <input id="selectAll" name="selectAll" title="Select this to select all records" type="checkbox" /><label for="selectAll">Select&amp;nbsp;All</label>
     </th>
     <th scope="col" id="nameCol">
      Name
     </th>
     <th scope="col" id="ownerCol">
      Owner
     </th>
    </tr>
   </thead>
   <tbody id="accountList"></tbody>
  </table>


  <label style="display: none;" for="btnAssign">
   Click to assign selected records
  </label>
  <button id="btnAssign" name="btnAssign" disabled style="display: none; float: right;">
   Assign Records
  </button>
  <label style="display: none;" for="btnAssign">
   Click to assign selected records
  </label>
  <button id="Button1" name="btnAssign" disabled style="display: none; float: right;">
   Assign Records
  </button>
 </div>
 <div id="status">
  &amp;nbsp;
 </div>
</body>
</html>

Confira Também

AssignRequest
Exemplo: Recuperar metadados da entidade usando o JavaScript
Usar o ponto de extremidade Modern App do SOAP para aplicativos modernos com os recursos da Web
Use dados do serviço Web nos recursos da Web (OData e ponto de extremidade SOAP do aplicativo ENSABOAM)
Crie aplicativos e extensões do servidor
Bibliotecas JavaScript para Microsoft Dynamics CRM 2015
Artigo técnico: Using Option Set Options with the REST Endpoint - JScript

© 2017 Microsoft. Todos os direitos reservados. Direitos autorais