Procedure: communiceren met externe services met behulp van serverlogica

In deze handleiding stelt u een webpagina in die de serverlogica gebruikt voor het lezen, schrijven, bijwerken en verwijderen van records uit het httpclient-serverobject van de externe services.

Opmerking

In dit voorbeeld wordt gebruikgemaakt van https://services.odata.org/TripPinRESTierService, maar u kunt ook andere openbaar beschikbare gratis testhulpprogramma's gebruiken.

Stap 1: Een serverlogica maken

  1. Meld u aan bij Power Pages.

  2. Selecteer site + Bewerken.

  3. Navigeer naar de Instellen werkruimte en selecteer vervolgens Server logica (preview)

    Schermopname die laat zien waar u server-logica selecteert in de werkruimte 'Instellen'.

  4. + Nieuwe serverlogica selecteren

  5. Voer de naam in voor de serverlogica. Deze naam wordt gebruikt in de API als resource-id tijdens het samenstellen van de logische API van de server. Voorbeeld:

    Vastgoed Voorbeeldwaarde
    Naam services.odata.org
    Weergavenaam Performing CRUD operations using OData service
  6. Selecteer +Rollen toevoegen om de juiste webrol toe te wijzen. Beheerdersrol toegevoegd in serverlogica In dit voorbeeld selecteert u Beheerders en meldt u zich later aan als beheerder om door te gaan.

  7. Selecteer Toevoegen.

  8. Selecteer de serverlogica en selecteer Code bewerken.

    Code bewerken selecteren

  9. In het dialoogvenster Bewerken in Microsoft Visual Studio Code voor het web selecteert u Visual Studio Code openen om de aangepaste logica te ontwerpen.

    U vindt vooraf gedefinieerde methoden en scripts in het bestand.

  10. Definieer de serverlogicamethode voor het lezen, bewerken, maken, verwijderen van bewerkingen met behulp van een externe service.

    Voeg de volgende baseUrl constante toe vóór de get() methode

    
     const baseUrl  = "https://services.odata.org/TripPinRESTierService";
    
    
  11. Vervang de voorbeeldfuncties get, post, put en del door de volgende code

    
    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. Sla het bestand op.

    Aanbeveling

    Gebruik Ctrl+S om op te slaan.

Stap 2: Webpagina maken

  1. Start Power Pages-ontwerpstudio.

  2. Selecteer + Page in de werkruimte Pagina's.

    Een nieuwe pagina toevoegen

  3. Selecteer in het dialoogvenster Een pagina beschrijven om deze te makende optie Andere manieren om een pagina toe te voegen.

  4. Voer in het dialoogvenster Een pagina toevoegen details in.

    1. Voer in het vak NaamServerlogica in en selecteer Begin met een lege indeling.
    2. Selecteer Toevoegen.

    Waarden invoeren om een pagina toe te voegen

  5. Selecteer de optie Code bewerken in de rechterbovenhoek.

  6. Selecteer in het dialoogvenster Bewerken in Visual Studio Code voor het web de optie Visual Studio Code openen.

  7. Vervang de code op de HTML-pagina door het volgende:

    <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. Het bestand opslaan

    Opmerking

    Met deze code maakt u een interactieve interface voor gegevenstabellen voor het demonstreren van CRUD-bewerkingen (maken, lezen, bijwerken, verwijderen) met een externe OData-service met behulp van Power Pages-serverlogica. Het bevat CSS-stijl voor een responsieve tabelindeling, een overlay voor verwerkingsmeldingen en JavaScript-functionaliteit waarmee gebruikers gegevens kunnen bekijken die zijn opgehaald uit de externe service, nieuwe records kunnen toevoegen door op de ➕ knop te klikken, bestaande records te bewerken door te dubbelklikken op tabelrijen (behalve het veld UserName), wijzigingen op te slaan met ✅, bewerkingen te annuleren met ❌en records te verwijderen met behulp van de 🗑knop ^ . De code maakt gebruik van jQuery en een veilige WebAPI-wrapper om geverifieerde AJAX-aanroepen naar het eindpunt /_api/serverlogics/services.odata.org uit te voeren, de antwoordgegevens te verwerken om OData-context te parseren en een servicesessie te beheren voor volgende bewerkingen.

  9. Ga terug naar de ontwerpfunctie voor Power Pages.

  10. Volg de instructies in het dialoogvenster U bewerkt code in Visual Studio Code voor het web en klik op de knop Synchroniseren .

Stap 3: De serverlogica gebruiken om te lezen, weergeven, bewerken, maken en verwijderen

De functionaliteit van de serverlogica testen:

  1. Selecteer Voorbeeld en kies Bureaublad.
  2. Meld u aan bij uw site met het gebruikersaccount waaraan de serverlogicagebruikersrol is toegewezen die u eerder hebt gemaakt. Terwijl we de rol Administrators in de vorige stap hebben geselecteerd, meldt u zich in dit voorbeeld aan als beheerder.
  3. Ga naar de serverlogica-webpagina die eerder is gemaakt.
  4. Controleer de bewerkingen.

Overzicht van serverlogica
Serverlogica ontwerpen
ServerobjectenInteractie met Dataverse-tabellen met behulp van Serverlogica