Slik samhandler du med eksterne tjenester ved hjelp av serverlogikk

I denne veiledningen skal du konfigurere en nettside som skal bruke serverlogikken til å lese, skrive, oppdatere og slette poster fra det eksterne httpclient-serverobjektet for eksterne tjenester.

Note

Dette eksemplet bruker https://services.odata.org/TripPinRESTierService , men du kan bruke andre offentlig tilgjengelige gratis testverktøy.

Trinn 1: Opprette en serverlogikk

  1. Logg på Power Pages.

  2. Velg område + Rediger.

  3. Gå til konfigurer arbeidsområdet, og velg serverlogikk (forhåndsvisning)

    Skjermbilde som viser hvor du velger serverlogikk i konfigurer arbeidsområdet.

  4. Velg +Ny serverlogikk

  5. Skriv inn navnet på serverlogikken. Dette navnet brukes i API som ressursidentifikator under bygging av serverlogikk-API-en. Eksempel:

    Egenskap Eksempelverdi
    Navn services.odata.org
    Visningsnavn Performing CRUD operations using OData service
  6. Velg +Legg til roller for å tilordne riktig nettrolle. Lagt til administratorrolle i serverlogikk I dette eksemplet velger du Administratorer og logger på senere som administrator for å fortsette.

  7. Velg Legg til.

  8. Velg serverlogikken, og velg Rediger kode.

    Velg redigeringskode

  9. Velg Åpne Visual Studio Code for å redigere den egendefinerte logikken i dialogboksen Rediger i Microsoft Visual Studio Code for weben.

    Du finner forhåndsdefinerte metoder og skript i filen.

  10. Definer serverlogikkmetoden for å lese, redigere, opprette, slette operasjoner ved hjelp av ekstern tjeneste.

    Legg til følgende baseUrl konstant før get() metoden

    
     const baseUrl  = "https://services.odata.org/TripPinRESTierService";
    
    
  11. getErstatt funksjonene , post, putog del eksempelfunksjonene 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. Lagre filen.

    Tips

    Bruk CTRL+S til å lagre.

Trinn 2: Opprette nettside

  1. Åpne Power Pages design studio.

  2. Velg + Side i Sider-arbeidsområdet.

    Legge til en ny side

  3. Velg Andre måter å legge til en side på, i dialogboksen Beskriv en side for å opprette den.

  4. Skriv inn detaljer i dialogboksen Legg til en side .

    1. Skriv inn Serverlogikk i Navn-boksen, og velg Start fra tomt oppsett.
    2. Velg Legg til.

    Angi verdier for å legge til en side

  5. Velg alternativet Rediger kode øverst til høyre.

  6. Velg Åpne Visual Studio Codei dialogboksen Rediger i Visual Studio Code for weben.

  7. Erstatt koden som ble funnet 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. Lagre filen

    Note

    Denne koden oppretter et interaktivt datatabellgrensesnitt for å demonstrere CRUD-operasjoner (Opprett, Les, Oppdater, Slett) med en ekstern OData-tjeneste ved hjelp av Serverlogikk for Power Pages. Det inkluderer CSS-stil for et responsivt tabelloppsett, et behandlingsvarslingsoverlegg og JavaScript-funksjonalitet som gjør det mulig for brukere å vise data hentet fra den eksterne tjenesten, legge til nye poster ved å ➕ klikke knappen, redigere eksisterende poster ved å dobbeltklikke på tabellrader (unntatt Brukernavn-feltet), lagre endringer med ✅, avbryte redigeringer med ❌og slette poster ved hjelp av 🗑️ -knappen. Koden bruker jQuery og en sikker WebAPI-wrapper til å foreta godkjente AJAX-kall til endepunktet /_api/serverlogics/services.odata.org, som håndterer svardataene for å analysere OData-konteksten og administrere en tjenesteøkt for etterfølgende operasjoner.

  9. Gå tilbake til Power Pages Designer.

  10. Følg instruksjonene i dialogboksen Du redigerer kode i Visual Studio Code for weben , og klikk synkroniser-knappen .

Trinn 3: Bruke serverlogikken til å lese, vise, redigere, opprette og slette

Slik tester du serverlogikkfunksjonaliteten:

  1. Velg Forhåndsvisning, og velg deretter Skrivebord.
  2. Logg deg på nettstedet med brukerkontoen som er tilordnet serverlogikkens brukerrolle du opprettet tidligere. Da vi valgte administratorrollen i forrige trinn, logger du deg på som administrator i dette eksemplet.
  3. Gå til serverlogikkens nettside som ble opprettet tidligere.
  4. Bekreft operasjonene.

Oversikt over serverlogikk
Redigeringsserverlogikk
ServerobjekterSlik samhandler du med Dataverse-tabeller ved hjelp av serverlogikk