Interacción con servicios externos mediante la lógica del servidor

En esta guía, configurará una página web que usará la lógica del servidor para leer, escribir, actualizar y eliminar registros del objeto de servidor httpclient de servicios externos.

Nota:

En este ejemplo se usa https://services.odata.org/TripPinRESTierService , pero podría usar otras herramientas de prueba gratuitas disponibles públicamente.

Paso 1: Crear una lógica de servidor

  1. Inicie sesión en Power Pages.

  2. Seleccione sitio + Editar.

  3. Vaya al área de trabajo Configurar y, a continuación, seleccione Lógica del servidor (versión preliminar)

    Captura de pantalla que muestra dónde seleccionar la lógica del servidor en el área de trabajo

  4. Seleccione +Nueva lógica de servidor.

  5. Escriba el nombre de la lógica del servidor. Este nombre se usa en la API como identificador de recursos al construir la API lógica del servidor. Por ejemplo:

    Propiedad Valor de ejemplo
    Nombre services.odata.org
    Nombre Performing CRUD operations using OData service
  6. Seleccione +Agregar roles para asignar el rol web adecuado. Se ha agregado el rol administrador en la lógica del servidor . En este ejemplo, seleccione Administradores y, después, inicie sesión como administrador para continuar.

  7. Selecciona Agregar.

  8. Seleccione la lógica del servidor y seleccione Editar código.

    Selección del código de edición

  9. En el cuadro de diálogo Editar en Microsoft Visual Studio Code para web , seleccione Abrir Visual Studio Code para crear la lógica personalizada.

    Encontrará métodos y scripts predefinidos en el archivo.

  10. Defina el método lógico de servidor para leer, editar, crear, eliminar operaciones mediante el servicio externo.

    Agregue la siguiente baseUrl constante antes del get() método .

    
     const baseUrl  = "https://services.odata.org/TripPinRESTierService";
    
    
  11. Reemplace las funciones de ejemplo get, post, put, y del con el siguiente código.

    
    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. Guarde el archivo.

    Sugerencia

    Use Ctrl+S para guardar.

Paso 2: Crear página web

  1. Inicie Estudio de diseño de Power Pages.

  2. En el área de trabajo Páginas , seleccione + Página.

    Agregar una nueva página

  3. En el cuadro de diálogo Describir una página para crearla , seleccione Otras formas de agregar una página.

  4. En el cuadro de diálogo Agregar una página , escriba los detalles.

    1. En el cuadro Nombre , escriba Lógica del servidor y seleccione Iniciar desde el diseño en blanco .
    2. Selecciona Agregar.

    Escribir valores para agregar una página

  5. Seleccione la opción Editar código en la esquina superior derecha.

  6. En el diálogo Editar en Visual Studio Code para la web, seleccione Abrir Visual Studio Code.

  7. Reemplace el código encontrado en la página HTML por lo siguiente:

    <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. Guardar el archivo

    Nota:

    Este código crea una interfaz de tabla de datos interactiva para mostrar las operaciones CRUD (Crear, Leer, Actualizar, Eliminar) con un servicio OData externo mediante la lógica del servidor de Power Pages. Incluye estilos CSS para un diseño de tabla con capacidad de respuesta, una superposición de notificaciones de procesamiento y una funcionalidad de JavaScript que permite a los usuarios ver los datos recuperados del servicio externo, agregar nuevos registros haciendo clic en el ➕ botón, editar registros existentes haciendo doble clic en las filas de tabla (excepto el campo UserName), guardar los cambios con ✅, cancelar modificaciones con ❌y eliminar registros mediante el 🗑botón ️ . El código usa jQuery y un contenedor seguro de WebAPI para realizar llamadas AJAX autenticadas al punto de conexión /_api/serverlogics/services.odata.org, controlando los datos de respuesta para analizar el contexto de OData y administrar una sesión de servicio para las operaciones posteriores.

  9. Vuelva al diseñador de Power Pages.

  10. En el cuadro de diálogo Edición de código en Visual Studio Code para web , siga las instrucciones y haga clic en el botón Sincronizar .

Paso 3: Usar la lógica del servidor para leer, ver, editar, crear y eliminar

Para probar la funcionalidad de lógica del servidor:

  1. Seleccione Vista previa y luego elija Escritorio.
  2. Inicie sesión en el sitio con la cuenta de usuario a la que se asignó el rol usuario lógico de servidor que creó anteriormente. Como hemos seleccionado el rol Administradores en el paso anterior, en este ejemplo, inicie sesión como administrador.
  3. Vaya a la página web lógica del servidor creada anteriormente.
  4. Compruebe las operaciones.

Introducción a la lógica del servidor
Lógica del servidor de autor
Objetos de servidorCómo interactuar con tablas de Dataverse mediante la lógica de servidor