Практическое руководство. Взаимодействие с таблицами Dataverse с помощью логики сервера

В этом руководстве вы настроите веб-страницу и пользовательский веб-шаблон, который будет использовать логику сервера для чтения, записи, обновления и удаления записей из таблицы контактов.

Шаг 1. Создание логики сервера

  1. Войдите в Power Pages.

  2. Выберите сайт и изменить.

  3. Перейдите в рабочую область "Настройка ", а затем выберите логику сервера (предварительная версия).

  4. Нажмите кнопку +Создать логику сервера.

  5. Введите имя логики сервера. Это имя используется в API в качестве идентификатора ресурса при создании API логики сервера.

    Пример: dataverse-crud-operations

  6. Нажмите кнопку +Добавить роли , чтобы назначить соответствующую веб-роль.

  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. Создание веб-страницы

  1. Запустите студию разработки Power Pages.

  2. В рабочей области Pages выберите +Page.

  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. Настройка разрешений

Создание веб-роли

Если в настоящее время у вас нет веб-роли с разрешениями на таблицу, к которую вы обращаетесь через логику сервера или требуется другой контекст доступа к данным, в следующих шагах показано, как создать новую веб-роль и назначить разрешения таблицы.

  1. Запустите приложение "Управление порталом".
  2. На левой панели в разделе "Безопасность " выберите веб-роли.
  3. Выберите Создать.
  4. В поле "Имя" введите имя пользователя логики сервера (или любое имя, которое лучше всего отражает роль пользователя, обращаюющегося к этой функции).
  5. В списке Веб-сайт выберите запись о своем веб-сайте.
  6. Нажмите кнопку "Сохранить".

Создание разрешений для таблиц

  1. Запустите студию разработки Power Pages.
  2. Выберите рабочую область "Безопасность ".
  3. В разделе "Защита" выберите разрешения таблицы.
  4. Выберите новое разрешение.
  5. В поле "Имя" введите разрешение на таблицу контактов.
  6. В списке "Имя таблицы" выберите "Контакт" (контакт).
  7. В списке "Тип доступа" выберите "Глобальный".
  8. Выберите привилегии "Чтение", " Запись", "Создать" и "Удалить ".
  9. Выберите и добавьте роли и выберите выбранную или созданную ранее веб-роль .
  10. Выберите Сохранить и закрыть.

Добавление контактов в веб-роль

  1. Запустите приложение "Управление порталом".
  2. В левой области в разделе "Безопасность " выберите "Контакты".
  3. Выберите контакт, который вы хотите использовать в этом примере для логики сервера.

    Замечание

    Этот контакт — это учетная запись пользователя, используемая в этом примере для тестирования логики сервера. Не забудьте выбрать правильный контакт на портале.

  4. Выберите связанные>веб-роли.
  5. Выберите Добавить существующую веб-роль.
  6. Выберите роль пользователя логики сервера , созданную ранее.
  7. Нажмите кнопку "Добавить".
  8. Выберите Сохранить и закрыть.

Шаг 4. Использование логики сервера для чтения, просмотра, редактирования, создания и удаления

Чтобы проверить функциональные возможности веб-API, выполните следующие действия.

  1. Выберите "Предварительный просмотр" и выберите "Рабочий стол".
  2. Войдите на сайт с учетной записью пользователя, которая была назначена роли пользователя логики сервера , созданной ранее.
  3. Перейдите на веб-страницу логики сервера , созданную ранее.

Общие сведения о логике сервера
Разработка логики сервера
Объекты сервера