Procedura: Interagire con i servizi esterni usando la logica del server

In questa guida verrà configurata una pagina Web che userà la logica del server per leggere, scrivere, aggiornare ed eliminare record dall'oggetto server httpclient dei servizi esterni.

Annotazioni

Questo esempio usa https://services.odata.org/TripPinRESTierService , ma è possibile usare altri strumenti di test gratuiti disponibili pubblicamente.

Passaggio 1: Creare una logica del server

  1. Accedere a Power Pages.

  2. Selezionare sito e modifica.

  3. Passare all'area di lavoro Configura , quindi selezionare Logica server (anteprima)

    Screenshot che mostra il punto in cui selezionare la logica del server nell'area di lavoro di configurazione.

  4. Selezionare +Nuova logica del server

  5. Immettere il nome per la logica del server. Questo nome viene usato nell'API come identificatore di risorsa durante la costruzione dell'API per la logica del server. Per esempio:

    Proprietà Valore di esempio
    Nome services.odata.org
    Nome visualizzato Performing CRUD operations using OData service
  6. Selezionare +Aggiungi ruoli per assegnare il ruolo Web appropriato. Aggiunta del ruolo di amministratore nella logica del server In questo esempio selezionare Amministratori e quindi accedere come amministratore per continuare.

  7. Seleziona Aggiungi.

  8. Selezionare la logica del server e selezionare Modifica codice.

    Selezionare modifica il codice

  9. Nella finestra di dialogo Modifica in Microsoft Visual Studio Code per il Web selezionare Apri Visual Studio Code per creare la logica personalizzata.

    Nel file sono disponibili metodi e script predefiniti.

  10. Definire il metodo di logica del server per leggere, modificare, creare, eliminare operazioni usando il servizio esterno.

    Aggiungere la costante seguente baseUrl prima del get() metodo

    
     const baseUrl  = "https://services.odata.org/TripPinRESTierService";
    
    
  11. Sostituire le funzioni di esempio get, post, put e del con il codice seguente.

    
    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. Salva il file.

    Suggerimento

    Usare CTRL+S per salvare.

Passaggio 2: Creare una pagina Web

  1. Avviare Power Pages Design Studio.

  2. Nell'area di lavoro Pagine selezionare + Pagina.

    Aggiungere una nuova pagina

  3. Nella finestra di dialogo Descrivere una pagina per crearla selezionare Altri modi per aggiungere una pagina.

  4. Nella finestra di dialogo Aggiungi una pagina immettere i dettagli.

    1. Nella casella Nome immettere Logica server e selezionare Avvia dal layout vuoto .
    2. Seleziona Aggiungi.

    Immettere i valori per aggiungere una pagina

  5. Selezionare l'opzione Modifica codice nell'angolo superiore destro.

  6. Nella finestra di dialogo Modifica in Visual Studio Code per il Web selezionare Apri Visual Studio Code.

  7. Sostituire il codice trovato nella pagina HTML con quanto segue:

    <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. Salvare il file

    Annotazioni

    Questo codice crea un'interfaccia interattiva della tabella dati per illustrare le operazioni CRUD (Create, Read, Update, Delete) con un servizio OData esterno usando la logica del server Power Pages. Include stili CSS per un layout di tabella reattivo, una sovrimpressione delle notifiche di elaborazione e funzionalità JavaScript che consente agli utenti di visualizzare i dati recuperati dal servizio esterno, aggiungere nuovi record facendo clic sul ➕ pulsante, modificare i record esistenti facendo doppio clic sulle righe della tabella (tranne il campo UserName), salvare le modifiche con ✅, annullare le modifiche con ❌e eliminare i record usando il 🗑pulsante ️ . Il codice usa jQuery e un wrapper WebAPI sicuro per effettuare chiamate AJAX autenticate all'endpoint /_api/serverlogics/services.odata.org, gestendo i dati di risposta per analizzare il contesto OData e gestire una sessione del servizio per le operazioni successive.

  9. Tornare alla finestra di progettazione pagine di Power.

  10. Nella finestra di dialogo You're editing code in Visual Studio Code for the Web (Si sta modificando il codice in Visual Studio Code per il Web ) seguire le istruzioni e fare clic sul pulsante Sincronizza .

Passaggio 3: Usare la logica del server per leggere, visualizzare, modificare, creare ed eliminare

Per testare la funzionalità della logica del server:

  1. Selezionare Anteprima e quindi desktop.
  2. Accedere al sito con l'account utente a cui è stato assegnato il ruolo Utente logica server creato in precedenza. Quando è stato selezionato il ruolo Administrators nel passaggio precedente, in questo esempio accedere come amministratore.
  3. Passare alla pagina Web Logica server creata in precedenza.
  4. Verificare le operazioni.

Panoramica della logica del server
Crea la logica del server
Oggetti serverCome interagire con le tabelle di Dataverse usando la logica del server