Sådan interagerer du med eksterne tjenester ved hjælp af serverlogik

I denne vejledning skal du konfigurere en webside, der bruger serverlogikken til at læse, skrive, opdatere og slette poster fra httpclient-serverobjektet for eksterne tjenester.

Notat

I dette eksempel bruges https://services.odata.org/TripPinRESTierService , men du kan bruge andre offentligt tilgængelige gratis testværktøjer.

Trin 1: Opret en serverlogik

  1. Log på Power Pages.

  2. Vælg websted + Rediger.

  3. Gå til Konfigurer arbejdsområde, og vælg derefter Serverlogik (prøveversion)

    Skærmbillede, der viser, hvor du kan vælge serverlogik i konfigurer arbejdsområdet.

  4. Vælg +Ny serverlogik

  5. Angiv navnet på serverlogikken. Dette navn bruges i API'en som ressource-id under oprettelse af serverlogik-API'en. Det kan f.eks. være:

    Egenskab Eksempelværdi
    Navn services.odata.org
    Vist navn Performing CRUD operations using OData service
  6. Vælg +Tilføj roller for at tildele den relevante webrolle. Tilføjet administratorrolle i serverlogik I dette eksempel skal du vælge Administratorer og senere logge på som administrator for at fortsætte.

  7. Vælg Tilføj.

  8. Vælg serverlogikken, og vælg Rediger kode.

    Vælg rediger kode

  9. I dialogboksen Rediger i Microsoft Visual Studio Code til internettet skal du vælge Åbn Visual Studio Code for at oprette den brugerdefinerede logik.

    Du kan finde foruddefinerede metoder og scripts i filen.

  10. Definer serverlogikmetoden til at læse, redigere, oprette og slette handlinger ved hjælp af ekstern tjeneste.

    Tilføj følgende baseUrl konstant før get() metoden

    
     const baseUrl  = "https://services.odata.org/TripPinRESTierService";
    
    
  11. Erstat funktionerne get, post, putog del eksempel med følgende kode

    
    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. Gem filen.

    Tips

    Brug Ctrl+S til at gemme.

Trin 2: Opret webside

  1. Start Power Pages Design Studio.

  2. I arbejdsområdet Sider skal du vælge + Side.

    Tilføj en ny side

  3. I dialogboksen Beskriv en side for at oprette den skal du vælge Andre måder at tilføje en side på.

  4. Angiv detaljer i dialogboksen Tilføj en side .

    1. I feltet Navn skal du angive Serverlogik og vælge Start fra tomt layout.
    2. Vælg Tilføj.

    Angiv værdier for at tilføje en side

  5. Vælg indstillingen Rediger kode i øverste højre hjørne.

  6. I dialogboksen Rediger i Visual Studio Code til internettet skal du vælge Åbn Visual Studio Code.

  7. Erstat den kode, der findes på HTML-siden, med følgende:

    <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. Gem filen

    Notat

    Denne kode opretter en interaktiv datatabelgrænseflade til demonstration af CRUD-handlinger (Create, Read, Update, Delete) med en ekstern OData-tjeneste ved hjælp af Power Pages-serverlogik. Den indeholder CSS-formatering for et dynamisk tabellayout, en meddelelsesoverlejring til behandling og JavaScript-funktionalitet, der giver brugerne mulighed for at få vist data, der er hentet fra den eksterne tjeneste, tilføje nye poster ved at klikke på ➕ knappen, redigere eksisterende poster ved at dobbeltklikke på tabelrækker (undtagen feltet UserName), gemme ændringer med ✅, annullere redigeringer med ❌og slette poster ved hjælp af 🗑knappen ️. Koden bruger jQuery og en sikker WebAPI-ombryder til at foretage godkendte AJAX-kald til slutpunktet /_api/serverlogics/services.odata.org, der håndterer svardataene for at fortolke OData-konteksten og administrere en tjenestesession for efterfølgende handlinger.

  9. Gå tilbage til Power Pages Designer.

  10. I dialogboksen Du redigerer kode i Visual Studio Code til internettet skal du følge vejledningen og klikke på knappen Synkroniser .

Trin 3: Brug serverlogikken til at læse, få vist, redigere, oprette og slette

Sådan tester du funktionaliteten af serverlogik:

  1. Vælg Eksempel, og vælg derefter Desktop.
  2. Log på dit websted med den brugerkonto, der er tildelt rollen Serverlogik Bruger , som du oprettede tidligere. Da vi valgte rollen Administratorer i det forrige trin, skal du i dette eksempel logge på som administrator.
  3. Gå til websiden Serverlogik , der blev oprettet tidligere.
  4. Kontrollér handlingerne.

Oversigt over serverlogik
Forfatterserverlogik
ServerobjekterSådan interagerer du med Dataverse-tabeller ved hjælp af serverlogik