方法: サーバー ロジックを使用して Dataverse テーブルを操作する

このガイドでは、サーバー ロジックを使用して連絡先テーブルからレコードの読み取り、書き込み、更新、削除を行う Web ページとカスタム Web テンプレートを設定します。

手順 1: サーバー ロジックを作成する

  1. Power Pages にサインインします。

  2. [サイト + 編集] を選択します

  3. [セットアップ] ワークスペースに移動し、[サーバー ロジック (プレビュー)] を選択します。

  4. [+新しいサーバー ロジック] を選択します。

  5. サーバー ロジックの名前を入力します。 この名前は、サーバー ロジック API の構築時にリソース識別子として API で使用されます。

    例: dataverse-crud-operations

  6. [+ ロールの追加] を選択して、適切な Web ロールを割り当てます。

  7. 名前の横にある 3 つのドット (...) を選択し、[コードの編集] を選択します。

  8. [ Visual Studio Code を開く ] を選択して、カスタム ロジックを作成します。 定義済みのメソッドとスクリプトがファイル内にあります。

  9. 連絡先レコードの読み取り、編集、作成、削除を行うサーバー ロジック メソッドを定義します。

    読み取り: get メソッド内に以下のスクリプトを追加する

    const entitySetName = Server.Context.QueryParameters["entitySetName"];
    if (!Server.Context.QueryParameters["id"]) {
        return Server.Connector.Dataverse.RetrieveMultipleRecords(entitySetName);
    } else {
        const id = Server.Context.QueryParameters["id"]; // Context reference
        return Server.Connector.Dataverse.RetrieveRecord(entitySetName, id);
    }
    

    作成: post メソッドに以下のスクリプトを追加する

    const data = Server.Context.Body;
    const entitySetName = Server.Context.QueryParameters["entitySetName"];
    return Server.Connector.Dataverse.CreateRecord(entitySetName, data);
    

    更新: put メソッドに以下のスクリプトを追加する

    const id = Server.Context.QueryParameters["id"];
    const data = Server.Context.Body;
    return Server.Connector.Dataverse.UpdateRecord("accounts", id, data);
    

    削除: del メソッド内に追加する

    const id = Server.Context.QueryParameters["id"];
    const entitySetName = Server.Context.QueryParameters["entitySetName"];
    Server.Logger.Log("Entity Set name:" + entitySetName);
    return Server.Connector.Dataverse.DeleteRecord(entitySetName, id);
    
  10. ファイルを保存します。

  11. 貼り付けることができる完全なサーバー ロジック コードを次に示します。

    function get() {
     try {
         Server.Logger.Log("GET called"); // Logger reference
         const entitySetName = Server.Context.QueryParameters["entitySetName"];
         const additionParameters = Server.Context.QueryParameters['additionalParameters'];
         if (!Server.Context.QueryParameters["id"]) {
             const response = Server.Connector.Dataverse.RetrieveMultipleRecords(entitySetName,additionParameters);
             return response;
         }
         else{            
             const id = Server.Context.QueryParameters["id"]; // Context reference
             const response = Server.Connector.Dataverse.RetrieveRecord(entitySetName, id,additionParameters);
             return response;
         }        
     } catch (err) {
         Server.Logger.Error("GET failed: " + err.message);
         return JSON.stringify({ status: "error", method: "GET", message: err.message });
     }
     }
     function post() {
     try {
         Server.Logger.Log("POST called");
         const data = Server.Context.Body;
         const entitySetName = Server.Context.QueryParameters["entitySetName"];
          return Server.Connector.Dataverse.CreateRecord(entitySetName, data);
      } catch (err) {
         Server.Logger.Error("POST failed: " + err.message);
         return JSON.stringify({ status: "error", method: "POST", message: err.message });
     }
     } 
     function put() {
     try {
         Server.Logger.Log("PUT called");
         const id = Server.Context.QueryParameters["id"];
         const data = Server.Context.Body;
         const entitySetName = Server.Context.QueryParameters["entitySetName"];
         return Server.Connector.Dataverse.UpdateRecord(entitySetName, id, data);
      } catch (err) {
         Server.Logger.Error("PUT failed: " + err.message);
         return JSON.stringify({ status: "error", method: "PUT", message: err.message });
     }
     }   
     function del() {
     try {
         // "delete" keyword should not be used in script file.
         Server.Logger.Log("DEL called");
         const id = Server.Context.QueryParameters["id"];
           const entitySetName = Server.Context.QueryParameters["entitySetName"];
         return Server.Connector.Dataverse.DeleteRecord(entitySetName, id);
      } catch (err) {
         Server.Logger.Error("Deletion failed: " + err.message);
         return JSON.stringify({ status: "error", method: "DEL", message: err.message });
     }
     }
    

手順 2: Web ページを作成する

  1. Power Pages デザイン スタジオを起動します。

  2. [ページ] ワークスペースで[+ ページ]を選択します。

  3. [ページの追加] ダイアログで、[名前] ボックスに「サーバー ロジック」と入力し、[空白レイアウトから開始] を選択します。

  4. [] を選択し、[] を追加します。

  5. 右上隅にある [ コードの編集] オプションを選択します。

  6. [ Visual Studio Code を開く] を選択します。

  7. 次のサンプル コード スニペットをコピーし、ページ セクションの <div></div> タグの間に貼り付けます。

    <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; }
    </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() {
        // --- safeAjax wrapper ---
        (function(webapi, $) {
            function safeAjax(ajaxOptions) {
                var dfd = $.Deferred();
                shell.getTokenDeferred().done(function(token) {
                    ajaxOptions.headers = ajaxOptions.headers || {};
                    ajaxOptions.headers["__RequestVerificationToken"] = token;
                    $.ajax(ajaxOptions)
                        .done((data, ts, jq) => validateLoginSession(data, ts, jq, dfd.resolve))
                        .fail(dfd.reject);
                }).fail(() => dfd.rejectWith(this, arguments));
                return dfd.promise();
            }
            webapi.safeAjax = safeAjax;
        })(window.webapi = window.webapi || {}, jQuery);
    
        // --- notification banner ---
        const notify = (function() {
            const $m = $('#processingMsg'); let s = 0, t;
            return {
                show: (msg = 'Processing...') => { $m.text(msg); if (!s) clearTimeout(t), $m.show(); s++; },
                hide: () => { s = Math.max(0, s - 1); if (!s) clearTimeout(t), t = setTimeout(() => $m.hide(), 300); }
            };
        })();
    
        function ajaxCall(msg, opts) {
            notify.show(msg);
            return webapi.safeAjax(opts)
                .fail(r => alert(r.responseJSON?.error?.message || 'Server logic not available'))
                .always(notify.hide);
        }
    
        // --- Table config ---
        const cols = [
            { name: 'firstname', label: 'First Name' },
            { name: 'lastname', label: 'Last Name' },
            { name: 'emailaddress1', label: 'Email' },
            { name: 'telephone1', label: 'Telephone' }
        ];
        let data = [];
    
        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-id="${r.id}" data-name="${r.fullname}">
                        ${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);
        }
    
        function addRecord(r) { data.unshift(r); render(); }
        function removeRecord(id) { data = data.filter(r => r.id !== id); render(); }
        function updateRecord(id, attr, val) { const r = data.find(r => r.id === id); if (r) { r[attr] = val; render(); } }
    
        // --- Events ---
        $('#dataTable').on('dblclick', 'tr', function() {
            const $tr = $(this);
            if ($tr.hasClass('editing')) return; // prevent double edit
            $tr.addClass('editing');
            $tr.data('original', $tr.find('td[data-attribute]').map(function() { return $(this).text(); }).get());
            $tr.find('td[data-attribute]').each(function() {
                const $td = $(this);
                const oldVal = $td.text();
                $td.html(`<input type="text" value="${oldVal}" data-attr="${$td.data('attribute')}" />`);
            });
            const $actions = $tr.find('td.actions');
            $actions.append('<button class="save">✅</button><button class="cancel">❌</button>');
        });
    
        $('#dataTable').on('click', '.save', function() {
            const $tr = $(this).closest('tr');
            const id = $tr.data('id');
            const updates = {};
            $tr.find('input').each(function() {
                updates[$(this).data('attr')] = $(this).val();
            });
            ajaxCall('Updating...', {
                type: 'PUT',
                url: `/_api/serverlogics/dataverse-crud-operations?entitySetName=contacts&id=${id}`,
                contentType: 'application/json',
                data: JSON.stringify(updates),
                success: () => { Object.assign(data.find(r => r.id === id), updates); render(); }
            });
        });
    
        $('#dataTable').on('click', '.cancel', function() {
            const $tr = $(this).closest('tr');
            const original = $tr.data('original');
            $tr.find('td[data-attribute]').each(function(i) {
                $(this).text(original[i]);
            });
            $tr.removeClass('editing');
            $tr.find('button.save, button.cancel').remove();
        });
    
        $('#dataTable').on('click', '.delete', function() {
            const $tr = $(this).closest('tr');
            if (confirm('Delete "' + $tr.data('name') + '"?')) {
                ajaxCall('Deleting...', {
                    type: 'DELETE',
                    url: `/_api/serverlogics/dataverse-crud-operations?entitySetName=contacts&id=${$tr.data('id')}`,
                    contentType: 'application/json',
                    success: () => removeRecord($tr.data('id'))
                });
            }
        });
    
        $('#dataTable').on('click', '.add', function() {
            const r = { firstname: 'Alton', lastname: 'Stott' + Math.floor(Math.random() * 900 + 100), emailaddress1: 'Alton.Stott@contoso.com', telephone1: '555-123-4567' };
            ajaxCall('Adding...', {
                type: 'POST',
                url: '/_api/serverlogics/dataverse-crud-operations?entitySetName=contacts',
                contentType: 'application/json',
                data: JSON.stringify(r),
                success: (res, s, xhr) => { r.id = xhr.getResponseHeader('entityid'); r.fullname = r.firstname + ' ' + r.lastname; addRecord(r); }
            });
        });
    
        ajaxCall('Loading...', {
            type: 'GET',
            url: '/_api/serverlogics/dataverse-crud-operations?entitySetName=contacts&additionalParameters=$select=fullname,firstname,lastname,emailaddress1,telephone1',
            contentType: 'application/json'
        }).done(res => {
            try {
                const p = JSON.parse(res.data); const b = JSON.parse(p.Body);
                data = (b.value || []).map(r => ({ ...r, id: r.contactid, fullname: r.fullname }));
                render();
            } catch (e) { console.error(e); }
        });
    });
    </script>
    

手順 3: アクセス許可を構成する

Web ロールを作成する

現在、サーバー ロジックを使用してアクセスするテーブルに対するアクセス許可を持つ Web ロールがない場合、またはデータにアクセスするためのさまざまなコンテキストが必要な場合は、次の手順で新しい Web ロールを作成し、テーブルのアクセス許可を割り当てる方法を示します。

  1. ポータル管理アプリを起動します。
  2. 左側のウィンドウの [ セキュリティ ] セクションで、[ Web ロール] を選択します。
  3. 新規を選択します。
  4. [ 名前 ] ボックスに、「 サーバー ロジック ユーザー 」と入力します (または、この機能にアクセスするユーザーのロールを最もよく反映する任意の名前)。
  5. Web サイトの一覧で、あなたのウェブサイトレコードを選択してください。
  6. 保存 を選択します。

テーブルのアクセス許可の作成

  1. Power Pages デザイン スタジオを起動します。
  2. [セキュリティ] ワークスペースを選択します。
  3. [ 保護 ] セクションで、[ テーブルのアクセス許可] を選択します。
  4. [ 新しいアクセス許可] を選択します。
  5. [ 名前 ] ボックスに、「 連絡先テーブルの権限」と入力します。
  6. [テーブル名] ボックスの一覧で、[連絡先 (連絡先)] を選択します。
  7. [ アクセスの種類] ボックスの一覧で[ グローバル] を選択します。
  8. [ 読み取り]、[ 書き込み]、[ 作成]、[削除] の各権限を 選択 します。
  9. [ + ロールの追加] を選択し、先ほど選択または作成した Web ロール を選択します。
  10. 保存して閉じる を選択します。

Web ロールに連絡先を追加する

  1. ポータル管理アプリを起動します。
  2. 左側のウィンドウの [ セキュリティ ] セクションで、[連絡先] を選択 します
  3. この例でサーバー ロジックに使用する連絡先を選択します。

    この連絡先は、この例でサーバー ロジックのテストに使用されるユーザー アカウントです。 ポータルで正しい連絡先を選択してください。

  4. [関連Web ロール] を選択します。
  5. [ 既存の Web ロールの追加] を選択します。
  6. 前に作成した サーバー ロジック ユーザー ロールを選択します。
  7. [] を選択し、[] を追加します。
  8. 保存して閉じる を選択します。

手順 4: サーバー ロジックを使用して、読み取り、表示、編集、作成、削除を行う

Web API の機能をテストするには:

  1. [ プレビュー] を選択し、[デスクトップ] を選択 します
  2. 前に作成した サーバー ロジック ユーザー ロールが割り当てられているユーザー アカウントでサイトにサインインします。
  3. 前に作成した サーバー ロジック Web ページに移動します。

サーバー ロジックの概要
著者サーバーロジック
サーバー オブジェクト