Como interagir com serviços externos usando a lógica do servidor

Neste guia, você configurará uma página da Web que usará a lógica do servidor para ler, gravar, atualizar e excluir registros do objeto de servidor httpclient de serviços externos.

Observação

Este exemplo usa a ferramenta https://services.odata.org/TripPinRESTierService, mas você pode usar outras ferramentas de teste gratuitas disponíveis publicamente.

Etapa 1: Criar uma lógica de servidor

  1. Entre no Power Pages.

  2. Selecione o site + Editar.

  3. Navegue até o espaço de trabalho Configuração e selecione Lógica do servidor (prévia)

    Captura de tela mostrando onde selecionar a lógica do servidor na área 'Configurar ambiente de trabalho'.

  4. Selecionar +Nova lógica do servidor

  5. Insira o nome da lógica do servidor. Esse nome é usado na API como identificador de recurso ao construir a API lógica do servidor. Por exemplo:

    Propriedade Exemplo de valor
    Nome services.odata.org
    Nome de exibição Performing CRUD operations using OData service
  6. Selecione +Adicionar funções para atribuir a função Web apropriada. Função administrador adicionada na lógica do servidor Neste exemplo, selecione Administradores e, posteriormente, entre como administrador para continuar.

  7. Selecione Adicionar.

  8. Selecione a lógica do servidor e selecione Editar código.

    Selecione editar código

  9. Na caixa de diálogo Editar no Microsoft Visual Studio Code para a Web , selecione Abrir o Visual Studio Code para criar a lógica personalizada.

    Você encontrará métodos e scripts predefinidos no arquivo.

  10. Defina o método lógico do servidor para ler, editar, criar e excluir operações usando o serviço externo.

    Adicionar a seguinte baseUrl constante antes do get() método

    
     const baseUrl  = "https://services.odata.org/TripPinRESTierService";
    
    
  11. Substitua as funções get, post, put e del de exemplo pelo código a seguir.

    
    async function get() { 
       try { 
          Server.Logger.Log("GET called"); // Logger reference 
          if (!Server.Context.QueryParameters["username"]) { 
                const response = await Server.Connector.HttpClient.GetAsync( 
                   `${baseUrl}/People?$select=UserName,FirstName,LastName,MiddleName,Age`, 
                   {'content-type':'application/json'}); 
                return response; 
          } 
          else {             
                const id = Server.Context.QueryParameters["username"]; // Context reference 
                const response = await Server.Connector.HttpClient.GetAsync( 
                   `${baseUrl}(${id})/People?$select=UserName,FirstName,LastName,MiddleName,Age`, 
                   {'content-type':'application/json'}); 
                return response; 
          }         
       } catch (err) { 
          Server.Logger.Error("GET failed: " + err.message); 
          return JSON.stringify({ status: "error", method: "GET", message: err.message }); 
       } 
    } 
    
    async function post() { 
       try { 
          Server.Logger.Log("POST called"); 
          const data = JSON.parse(Server.Context.Body);            
          const url = `${baseUrl}/${data.serviceSession}/People`; 
          const { serviceSession, ...body } = data;  
          const response = await Server.Connector.HttpClient.PostAsync( 
                url,  
                JSON.stringify(body), 
                {'content-type':'application/json'}); 
          return response; 
       } catch (err) { 
          Server.Logger.Error("POST failed: " + err.message); 
          return JSON.stringify({ status: "error", method: "POST", message: err.message }); 
       } 
    }  
    
    async function put() { 
       try { 
          Server.Logger.Log("PUT called"); 
          const data = JSON.parse(Server.Context.Body);         
          const url = `${baseUrl}/${data.serviceSession}/People('${data.UserName}')`; 
          const { UserName, ...body1 } = data; 
          const { serviceSession, ...body } = body1; 
          const response = await Server.Connector.HttpClient.PatchAsync( 
                url,  
                JSON.stringify(body), 
                {'content-type':'application/json'}); 
          return response; 
       } catch (err) { 
          Server.Logger.Error("PUT failed: " + err.message); 
          return JSON.stringify({ status: "error", method: "PUT", message: err.message }); 
       } 
    }    
    
    async function del() { 
       try { 
          // "delete" keyword should not be used in script file. 
          Server.Logger.Log("DEL called"); 
          const username = Server.Context.QueryParameters["username"]; 
          const serviceSession = Server.Context.QueryParameters["serviceSession"]; 
          const url = `${baseUrl}/${serviceSession}/People('${username}')`; 
          const response = await Server.Connector.HttpClient.DeleteAsync( 
                url,  
                {'content-type':'application/json'}); 
          return response; 
       } catch (err) { 
          Server.Logger.Error("Deletion failed: " + err.message); 
          return JSON.stringify({ status: "error", method: "DEL", message: err.message }); 
       } 
    } 
    
  12. Salve o arquivo.

    Dica

    Use Ctrl+S para salvar.

Etapa 2: Criar página da Web

  1. Inicie o estúdio de design do Power Pages.

  2. No workspace Páginas, selecione + Página.

    Adicionar uma nova página

  3. Na caixa de diálogo Descrever uma página para criá-la , selecione Outras maneiras de adicionar uma página.

  4. Na caixa de diálogo Adicionar uma página, insira detalhes.

    1. Na caixa Nome , insira a lógica do servidor e selecione Iniciar do layout em branco .
    2. Selecione Adicionar.

    Inserir valores para adicionar uma página

  5. Selecione a opção Editar Código no canto superior direito.

  6. Na caixa de diálogo Editar no Visual Studio Code para a Web, selecione Abrir o Visual Studio Code.

  7. Substitua o código encontrado na página HTML pelo seguinte:

    <div class="row sectionBlockLayout text-left" style="min-height: auto; padding: 8px;">
    <div class="container" style="display: flex; flex-wrap: wrap;">
       <div class="col-md-12 columnBlockLayout" style="padding: 16px; margin: 60px 0px; min-height: 200px;">
          <!-- Sample code for Web API demonstration -->
          <style>
          #processingMsg {
             padding: 6px 12px;
             background: #eee;
             border-radius: 4px;
             position: fixed;
             top: 10px;
             left: 50%;
             transform: translateX(-50%);
             display: none;
             z-index: 9999;
             text-align: center;
             font-weight: bold;
          }
    
          table {
             border-collapse: collapse;
             width: 100%;
             margin-top: 10px;
             font-family: Arial, sans-serif;
          }
    
          th,
          td {
             border: 1px solid #ccc;
             padding: 6px;
             text-align: left;
          }
    
          button {
             cursor: pointer;
             border: 1px solid #aaa;
             padding: 4px 8px;
             border-radius: 4px;
             background: #fff;
             font-size: 14px;
             margin-right: 2px;
          }
    
          button.add {
             color: green;
          }
    
          button.save {
             color: green;
          }
    
          button.cancel {
             color: orange;
          }
    
          button.delete {
             color: red;
          }
    
          input {
             width: 95%;
             box-sizing: border-box;
          }
    
          td.actions {
             white-space: nowrap;
          }
    
          td[data-attribute="UserName"] {
             background: #f9f9f9;
             cursor: default;
          }
          </style>
    
          <div id="processingMsg">Processing...</div>
          <div id="dataTable"></div>
    
          <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
          <script>
          $(function () {
    
             // Safe WebAPI wrapper for Power Pages
             (function (webapi, $) {
                function safeAjax(opts) {
                var d = $.Deferred();
                shell.getTokenDeferred().done(function (token) {
                   opts.headers = opts.headers || {};
                   opts.headers["__RequestVerificationToken"] = token;
                   $.ajax(opts)
                      .done((data, ts, jq) => validateLoginSession(data, ts, jq, d.resolve))
                      .fail(d.reject);
                }).fail(() => d.rejectWith(this, arguments));
                return d.promise();
                }
                webapi.safeAjax = safeAjax;
             })(window.webapi = window.webapi || {}, jQuery);
    
             // Notification overlay
             const notify = (() => {
                const $m = $('#processingMsg'); let s = 0, t;
                return {
                show: (msg = 'Processing...') => { $m.text(msg); if (!s) $m.show(); s++; },
                hide: () => { s = Math.max(0, s - 1); if (!s) t = setTimeout(() => $m.hide(), 200); }
                };
             })();
    
             function ajaxCall(msg, opts) {
                notify.show(msg);
                return webapi.safeAjax(opts)
                .fail(r => alert(r.responseJSON?.error?.message || 'Server error'))
                .always(notify.hide);
             }
    
             // Table columns
             const cols = [
                { name: 'UserName', label: 'User Name', editable: false },
                { name: 'FirstName', label: 'First Name' },
                { name: 'LastName', label: 'Last Name' },
                { name: 'MiddleName', label: 'Middle Name' },
                { name: 'Age', label: 'Age' }
             ];
    
             let data = [];
             let serviceSession = '';
             function render() {
                const html = `<table>
                <thead>
                   <tr>
                      ${cols.map(c => `<th>${c.label}</th>`).join('')}
                      <th>Actions <button class="add">➕</button></th>
                   </tr>
                </thead>
                <tbody>
                   ${data.map(r => `<tr data-UserName="${r.UserName}">
                      ${cols.map(c => `<td data-attribute="${c.name}" data-value="${r[c.name] || ''}">
                            ${r[c.name] || ''}
                      </td>`).join('')}
                      <td class="actions">
                            <button class="delete">🗑️</button>
                      </td>
                   </tr>`).join('')}
                </tbody>
          </table>`;
                $('#dataTable').html(html);
             }
    
             // Double click row to edit except username
             $('#dataTable').on('dblclick', 'tr', function () {
                const $tr = $(this);
                if ($tr.hasClass('editing')) return;
                $tr.addClass('editing');
                $tr.find('td[data-attribute]').each(function () {
                const $td = $(this);
                if ($td.data('attribute') === 'UserName') return;
                const old = $td.text().trim();
                $td.html(`<input type="text" value="${old}" data-attr="${$td.data('attribute')}"/>`);
                });
                $tr.find('.actions').append('<button class="save">✅</button><button class="cancel">❌</button>');
             });
    
             $('#dataTable').on('click', '.save', function () {
                const $tr = $(this).closest('tr');
                const username = $tr.data('username');
                const updates = {};
                $tr.find('input').each(function () {
                const attr = $(this).data('attr');
                let value = $(this).val().trim();
    
                if (attr === 'Age') {
                   value = Number(value);
                   if (isNaN(value)) value = null; // safety fallback
                }
    
                updates[attr] = value;
                });
    
                ajaxCall('Updating...', {
                type: 'PUT',
                url: `/_api/serverlogics/services.odata.org`,
                contentType: 'application/json',
                data: JSON.stringify(Object.assign({ UserName: username, serviceSession: `${serviceSession}` }, updates)),
                success: () => { Object.assign(data.find(x => x.UserName === username), updates); render(); }
                });
             });
    
             $('#dataTable').on('click', '.cancel', () => render());
    
             $('#dataTable').on('click', '.delete', function () {
                const username = $(this).closest('tr').data('username');
                if (!confirm('Delete ' + username + '?')) return;
                ajaxCall('Deleting...', {
                type: 'DELETE',
                url: `/_api/serverlogics/services.odata.org?username=${username}&serviceSession=${serviceSession}`,
                success: () => { data = data.filter(x => x.UserName !== username); render(); }
                });
             });
    
             $('#dataTable').on('click', '.add', function () {
                const r = {
                serviceSession: `${serviceSession}`,
                UserName: 'user' + Math.floor(Math.random() * 9000 + 1000),
                FirstName: 'New',
                LastName: 'Person',
                MiddleName: '',
                Age: 25
                };
                ajaxCall('Adding...', {
                type: 'POST',
                url: `/_api/serverlogics/services.odata.org`,
                contentType: 'application/json',
                data: JSON.stringify(r),
                success: () => { data.unshift(r); render(); }
                });
             });
    
             // Initial load
             ajaxCall('Loading...', {
                type: 'GET',
                url: `/_api/serverlogics/services.odata.org`,
                contentType: 'application/json'
             }).done(resp => {
                const parsed = JSON.parse(resp.data);
                const body = JSON.parse(parsed.Body);
    
                const ctx = body['@odata.context'];
                const match = ctx.match(/\\S\\[^)]*\\/);
                serviceSession = match ? match[0] : '';
    
                data = (body.value || []).map(r => ({
                UserName: r.UserName,
                FirstName: r.FirstName,
                LastName: r.LastName,
                MiddleName: r.MiddleName,
                Age: r.Age
                }));
                render();
             });
    
          });
          </script>
       </div>
    </div>
    </div>
    
  8. Salve o arquivo

    Observação

    Esse código cria uma interface de tabela de dados interativa para demonstrar operações CRUD (Criar, Ler, Atualizar, Excluir) com um serviço OData externo usando a lógica do servidor do Power Pages. Ele inclui o estilo CSS para um layout de tabela responsiva, uma sobreposição de notificação de processamento e funcionalidade javaScript que permite que os usuários exibam dados recuperados do serviço externo, adicionem novos registros clicando no ➕ botão, editem registros existentes clicando duas vezes em linhas de tabela (exceto o campo Nome de Usuário), salvem alterações com ✅, cancelem edições com ❌e excluam registros usando o 🗑botão ️. O código utiliza jQuery e um wrapper seguro de WebAPI para efetuar chamadas AJAX autenticadas ao endpoint /_api/serverlogics/services.odata.org, manipulando os dados de resposta para interpretar o contexto OData e gerenciar uma sessão de serviço para operações subsequentes.

  9. Retorne ao designer do Power Pages.

  10. Na caixa de diálogo Você está editando código no Visual Studio Code para a Web , siga as instruções e clique no botão Sincronizar .

Etapa 3: Usar a lógica do servidor para ler, exibir, editar, criar e excluir

Para testar a funcionalidade lógica do servidor:

  1. Selecione Visualizar e escolha Área de Trabalho.
  2. Entre em seu site com a conta de usuário que foi atribuída à função Usuário lógico do servidor que você criou anteriormente. Como selecionamos a função Administradores na etapa anterior, neste exemplo, entre como administrador.
  3. Vá para a página da Web lógica do servidor criada anteriormente.
  4. Verifique as operações.

Visão geral da lógica do servidor
Lógica do servidor Author
Objetos de servidorComo interagir com tabelas do Dataverse usando a lógica do servidor