다음을 통해 공유


자습서: 포털 웹 API 사용

참고

2022년 10월 12일부터 Power Apps 포털이 Power Pages가 됩니다. 추가 정보: Microsoft Power Pages는 이제 일반적으로 사용할 수 있습니다(블로그)
곧 Power Apps 포털 설명서를 마이그레이션하고 Power Pages 설명서와 병합할 예정입니다.

이 자습서에서는 웹 API를 사용하여 연락처 테이블에서 레코드를 읽고, 쓰고, 업데이트하고, 삭제할 웹 페이지 및 사용자 지정 웹 템플릿을 설정합니다.

참고

이 예의 단계를 수행하는 동안 열 이름을 변경하거나 다른 테이블을 사용할 수 있습니다.

1단계 사이트 설정 만들기

포털 웹 API를 사용하기 전에 포털 관리 앱에서 필요한 사이트 설정을 활성화해야 합니다. 사이트 설정은 웹 API와 상호 작용할 때 사용하려는 테이블에 따라 다릅니다.

  1.  Power Apps(으)로 이동합니다.

  2. 왼쪽 창에서 을 선택합니다.

  3.  포털 관리  앱을 선택합니다.

    포털 관리 앱 시작

  4.  포털 관리 앱의 왼쪽 창에서 사이트 설정을 선택합니다.

    포털 관리 앱에서 사이트 설정을 엽니다.

  5.  새로 만들기를 선택합니다.

  6.  이름 상자에 Webapi/contact/enabled를 입력합니다.

  7.  웹 사이트 목록에서 웹 사이트 레코드를 선택합니다.

  8.   상자에 true를 입력합니다.

    웹 API 사이트 설정을 위한 연락처 테이블을 활성화합니다.

  9.  저장하고 닫기를 선택합니다.

  10.  새로 만들기를 선택합니다.

  11.  이름 상자에 Webapi/contact/fields를 입력합니다.

  12.  웹 사이트 목록에서 웹 사이트 레코드를 선택합니다.

  13.   상자에
    firstname,lastname,fullname,emailaddress1,telephone1을 입력합니다.

    웹 API 연락처 테이블 필드 활성화

  14.  저장하고 닫기를 선택합니다.

  15.  새로 만들기를 선택합니다.

  16.  이름 상자에 Webapi/error/innererror를 입력합니다.

    웹 API 내부 오류 사이트 설정을 활성화합니다.

  17.  웹 사이트 목록에서 웹 사이트 레코드를 선택합니다.

  18.   상자에 true를 입력합니다.

  19.  저장하고 닫기를 선택합니다.

  20.  웹 API의 사이트 설정을 확인합니다.

2단계. 권한 구성

사용자가 웹 API 기능을 사용할 수 있도록 권한을 구성해야 합니다. 이 예에서는 테이블 권한의 연락처를 활성화하고, 웹 API를 사용하여 웹 역할을 생성하고, 연락처 테이블의 테이블 권한을 이 웹 역할에 추가한 다음 사용자에게 웹 역할을 추가하여 사용자가 웹 API를 사용할 수 있도록 합니다.

  1.  포털 관리 앱의 왼쪽 창에서 테이블 권한을 선택합니다.

  2.  새로 만들기를 선택합니다.

  3.  이름 상자에서 연락처 테이블 권한을 입력합니다.

  4.  테이블 이름 목록에서 연락처(연락처) 를 선택합니다.

  5.  웹 사이트 목록에서 웹 사이트 레코드를 선택합니다.

  6.  액세스 형식 목록에서 전역을 선택합니다.

  7. 읽기, 쓰기, 만들기삭제 권한을 선택합니다.

  8.  저장하고 닫기를 선택합니다.

    연락처 테이블 권한

웹 역할 만들기

웹 사이트에서 기존 웹 역할을 사용하거나 새 웹 역할을 생성할 수 있습니다.

  1. 왼쪽 창에서 웹 역할 을 선택합니다.

  2.  새로 만들기를 선택합니다.

  3.  이름 상자에 웹 API 사용자(또는 이 기능에 액세스하는 사용자의 역할을 가장 잘 반영하는 이름)를 입력합니다.

  4.  웹 사이트 목록에서 웹 사이트 레코드를 선택합니다.

    웹 API 사용자 웹 역할을 추가합니다.

  5.  저장을 선택합니다.

관련 테이블 권한 추가

  1. 신규 또는 기존 웹 역할을 사용하여 관련 > 테이블 권한을 선택합니다.

    웹 역할에 관련 테이블 권한 추가

  2.  기존 테이블 권한 추가를 선택합니다.

  3. 이전에 만든 연락처 테이블 권한을 선택합니다.

    연락처 테이블 권한 선택

  4.  추가를 선택합니다.

  5.  저장하고 닫기를 선택합니다.

    테이블 권한 보기

웹 역할에 연락처 추가

  1. 왼쪽 창에서 연락처를 선택합니다.

  2. 웹 API 예제에서 사용할 연락처를 선택합니다.

    참고

    이 연락처는 웹 API를 테스트하기 위해 이 예제에서 사용되는 사용자 계정입니다. 포털에서 올바른 연락처를 선택해야 합니다.

  3.  관련 항목 > 웹 역할을 선택합니다.

    관련 웹 역할을 선택합니다.

  4.  기존 웹 역할 추가를 선택합니다.

  5. 앞에서 만든 웹 API 사용자 역할을 선택합니다.

  6.  추가를 선택합니다.

    웹 역할 관련 보기

  7.  저장하고 닫기를 선택합니다.

3단계. 웹 페이지 만들기

이제 웹 API를 활성화하고 사용자 권한을 구성했으므로 레코드를 보고 편집하고 만들고 삭제할 수 있는 샘플 코드가 포함된 웹 페이지를 만듭니다.

  1.  포털 관리 앱의 왼쪽 창에서 웹 페이지를 선택합니다.

  2. 새로 만들기를 선택합니다.

  3. 이름 상자에 webapi를 입력합니다.

  4. 웹 사이트 목록에서 웹 사이트 레코드를 선택합니다.

  5. 상위 페이지에 대해 을 선택합니다.

  6. 부분 URLwebapi를 입력합니다.

  7. 페이지 템플릿에 대해 을 선택합니다.

  8. 게시 상태에 대해 게시됨을 선택합니다.

  9. 저장을 선택합니다.

    웹 페이지.

  10. 관련 항목 > 웹 페이지를 선택합니다.

    관련 웹 페이지

  11. 웹 페이지 관련 보기에서 webapi를 선택합니다.

    웹 페이지 관련 보기.

  12. 콘텐츠 섹션으로 아래로 스크롤한 다음, 복사(HTML)(HTML 디자이너)로 이동합니다.

    HTML 콘텐츠 복사

  13. HTML 탭을 선택합니다.

    HTML 탭 선택

  14. 다음 샘플 코드 조각을 복사하여 HTML 디자이너에 붙여넣습니다.

        <!-- Sample code for Web API demonstration -->
    <style>
        #processingMsg {
            width: 150px;
            text-align: center;
            padding: 6px 10px;
            z-index: 9999;
            top: 0;
            left: 40%;
            position: fixed;
            -webkit-border-radius: 0 0 2px 2px;
            border-radius: 0 0 2px 2px;
            -webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
            display: none;
        }
    
        table td[data-attribute] .glyphicon-pencil {
            margin-left: 5px;
            opacity: 0;
        }
    
        table td[data-attribute]:hover .glyphicon-pencil {
            opacity: 0.7;
        }
    </style>
    
    <script>
      $(function() {
        //Web API ajax wrapper
        (function(webapi, $) {
          function safeAjax(ajaxOptions) {
            var deferredAjax = $.Deferred();
            shell.getTokenDeferred().done(function(token) {
              // Add headers for ajax
              if (!ajaxOptions.headers) {
                $.extend(ajaxOptions, {
                  headers: {
                    "__RequestVerificationToken": token
                  }
                });
              } else {
                ajaxOptions.headers["__RequestVerificationToken"] = token;
              }
              $.ajax(ajaxOptions)
                .done(function(data, textStatus, jqXHR) {
                  validateLoginSession(data, textStatus, jqXHR, deferredAjax.resolve);
                }).fail(deferredAjax.reject); //ajax
            }).fail(function() {
              deferredAjax.rejectWith(this, arguments); // On token failure pass the token ajax and args
            });
            return deferredAjax.promise();
          }
          webapi.safeAjax = safeAjax;
        })(window.webapi = window.webapi || {}, jQuery)
        // Notification component
        var notificationMsg = (function() {
          var $processingMsgEl = $('#processingMsg'),
            _msg = 'Processing...',
            _stack = 0,
            _endTimeout;
          return {
            show: function(msg) {
              $processingMsgEl.text(msg || _msg);
              if (_stack === 0) {
                clearTimeout(_endTimeout);
                $processingMsgEl.show();
              }
              _stack++;
            },
            hide: function() {
              _stack--;
              if (_stack <= 0) {
                _stack = 0;
                clearTimeout(_endTimeout);
                _endTimeout = setTimeout(function() {
                  $processingMsgEl.hide();
                }, 500);
              }
            }
          }
        })();
        // Inline editable table component
        var webAPIExampleTable = (function() {
          var trTpl = '<% _.forEach(data, function(data){ %>' +
            '<tr data-id="<%=data.id%>" data-name="<%=data.fullname%>">' +
            '<% _.forEach(columns, function(col){ %>' +
            '<td data-attribute="<%=col.name%>" data-label="<%=col.label%>" data-value="<%=data[col.name]%>">' +
            '<%-data[col.name]%><i class="glyphicon glyphicon-pencil"></i>' +
            '</td>' +
            '<% }) %>' +
            '<td>' +
            '<button class="btn btn-default delete" type="submit"><i class="glyphicon glyphicon-trash" aria-hidden="true"></i></button>' +
            '</td>' +
            '</tr>' +
            '<% }) %>';
          var tableTpl = '<table class="table table-hover">' +
            '<thead>' +
            '<tr>' +
            '<% _.forEach(columns, function(col){ %>' +
            '<th><%=col.label%></th>' +
            '<% }) %>' +
            '<th>' +
            '<button class="btn btn-default add" type="submit">' +
            '<i class="glyphicon glyphicon-plus" aria-hidden="true"></i> Add Sample Record' +
            '</button>' +
            '</th>' +
            '</tr>' +
            '</thead>' +
            '<tbody>' + trTpl + '</tbody>' +
            '</table>';
          function getDataObject(rowEl) {
            var $rowEl = $(rowEl),
              attrObj = {
                id: $rowEl.attr('data-id'),
                name: $rowEl.attr('data-name')
              };
            $rowEl.find('td').each(function(i, el) {
              var $el = $(el),
                key = $el.attr('data-attribute');
              if (key) {
                attrObj[key] = $el.attr('data-value');
              }
            })
            return attrObj;
          }
          function bindRowEvents(tr, config) {
            var $row = $(tr),
              $deleteButton = $row.find('button.delete'),
              dataObj = getDataObject($row);
            $.each(config.columns, function(i, col) {
              var $el = $row.find('td[data-attribute="' + col.name + '"]');
              $el.on('click', $.proxy(col.handler, $el, col, dataObj));
            });
            //User can delete record using this button
            $deleteButton.on('click', $.proxy(config.deleteHandler, $row, dataObj));
          }
          function bindTableEvents($table, config) {
            $table.find('tbody tr').each(function(i, tr) {
              bindRowEvents(tr, config);
            });
            $table.find('thead button.add').on('click', $.proxy(config.addHandler, $table));
          }
          return function(config) {
            var me = this,
              columns = config.columns,
              addHandler = config.addHandler,
              deleteHandler = config.deleteHandler,
              $table;
            me.render = function(el) {
              $table = $(el).html(_.template(tableTpl)({
                columns: columns,
                data: me.data
              })).find('table');
              bindTableEvents($table, {
                columns: columns,
                addHandler: addHandler,
                deleteHandler: deleteHandler
              });
            }
            me.addRecord = function(record) {
              $table.find('tbody tr:first').before(_.template(trTpl)({
                columns: columns,
                data: [record]
              }));
              bindRowEvents($table.find('tbody tr:first'), config);
            }
            me.updateRecord = function(attributeName, newValue, record) {
              $table.find('tr[data-id="' + record.id + '"] td[data-attribute="' + attributeName + '"]').text(newValue);
            }
            me.removeRecord = function(record) {
              $table.find('tr[data-id="' + record.id + '"]').fadeTo("slow", 0.7, function() {
                $(this).remove();
              });
            }
          };
        })();
        //Applicaton ajax wrapper 
        function appAjax(processingMsg, ajaxOptions) {
          notificationMsg.show(processingMsg);
          return webapi.safeAjax(ajaxOptions)
            .fail(function(response) {
              if (response.responseJSON) {
                alert("Error: " + response.responseJSON.error.message)
              } else {
                alert("Error: Web API is not available... ")
              }
            }).always(notificationMsg.hide);
        }
        function loadRecords() {
          return appAjax('Loading...', {
            type: "GET",
            url: "/_api/contacts?$select=fullname,firstname,lastname,emailaddress1,telephone1",
            contentType: "application/json"
          });
        }
        function addSampleRecord() {
          //Sample data to create a record - change as appropriate
          var recordObj = {
            firstname: "Willie",
            lastname: "Huff" + _.random(100, 999),
            emailaddress1: "Willie.Huff@contoso.com",
            telephone1: "555-123-4567"
          };
          appAjax('Adding...', {
            type: "POST",
            url: "/_api/contacts",
            contentType: "application/json",
            data: JSON.stringify(recordObj),
            success: function(res, status, xhr) {
              recordObj.id = xhr.getResponseHeader("entityid");
              recordObj.fullname = recordObj.firstname + " " + recordObj.lastname;
              table.addRecord(recordObj);
            }
          });
          return false;
        }
        function deleteRecord(recordObj) {
          var response = confirm("Are you sure, you want to delete \"" + recordObj.name + "\" ?");
          if (response == true) {
            appAjax('Deleting...', {
              type: "DELETE",
              url: "/_api/contacts(" + recordObj.id + ")",
              contentType: "application/json",
              success: function(res) {
                table.removeRecord(recordObj);
              }
            });
          }
          return false;
        }
        function updateRecordAttribute(col, recordObj) {
          var attributeName = col.name,
            value = recordObj[attributeName],
            newValue = prompt("Please enter \"" + col.label + "\"", value);
          if (newValue != null && newValue !== value) {
            appAjax('Updating...', {
              type: "PUT",
              url: "/_api/contacts(" + recordObj.id + ")/" + attributeName,
              contentType: "application/json",
              data: JSON.stringify({
                "value": newValue
              }),
              success: function(res) {
                table.updateRecord(attributeName, newValue, recordObj);
              }
            });
          }
          return false;
        }
        var table = new webAPIExampleTable({
          columns: [{
            name: 'firstname',
            label: 'First Name',
            handler: updateRecordAttribute
          }, {
            name: 'lastname',
            label: 'Last Name',
            handler: updateRecordAttribute
          }, {
            name: 'emailaddress1',
            label: 'Email',
            handler: updateRecordAttribute
          }, {
            name: 'telephone1',
            label: 'Telephone',
            handler: updateRecordAttribute
          }],
          data: [],
          addHandler: addSampleRecord,
          deleteHandler: deleteRecord
        });
        loadRecords().done(function(data) {
          table.data = _.map(data.value, function(record){
            record.id = record.contactid;
            return record;
          });
          table.render($('#dataTable'));
        });
      });
    </script>
    <div id="processingMsg" class="alert alert-warning" role="alert"></div>
    <div id="dataTable"></div>
    

    코드를 붙여넣습니다.

  15. 저장 및 닫기를 선택합니다.

4단계. 포털 캐시 지우기

웹 API 기능을 테스트하기 위해 webapi 샘플 페이지를 작성했습니다. 시작하기 전에 포털 관리 앱의 변경 내용이 포털에 반영되도록 Power Apps 포털 캐시가 지워졌는지 확인합니다.

중요: 포털 서버 측 캐시를 지우면 Microsoft Dataverse에서 데이터를 다시 로드하는 동안에 포털 성능이 일시적으로 저하될 수 있습니다.

캐시를 지우려면

  1. 관리자 웹 역할의 구성원으로 포털에 로그인합니다.

  2. 끝에 /_‑/_services/about 을 추가하여 URL을 변경합니다. 예를 들어 포털 URL이  https://contoso.powerappsportals.com인 경우  https://contoso.powerappsportals.com/_services/about으로 변경합니다.

    캐시 지우기.

    참고: 캐시를 지우려면 관리자 웹 역할의 구성원이어야 합니다. 빈 화면이 표시되는 경우 웹 역할 할당을 확인합니다.

  3.  캐시 지우기를 선택합니다.

추가 정보:  포털에 대한 서버측 캐시 지우기

5단계 웹 API를 사용하여 읽기, 보기, 편집, 생성 및 삭제

이전에 생성한 URL webapi가 포함된 샘플 웹페이지를 이제 테스트할 준비가 되었습니다.

웹 API 기능을 테스트하려면 다음을 수행하십시오.

  1. 앞에서 만든 웹 API 사용자 역할이 할당된 사용자 계정으로 포털에 로그인합니다.

  2. 앞에서 만든 webapi 웹 페이지로 이동합니다. *https://contoso.powerappsportals.com/webapi*을 예로 들 수 있습니다. 웹 API는 Microsoft Dataverse에서 레코드를 검색합니다.

    샘플 webapi 웹 페이지.

  3. 샘플 레코드 추가를 선택하고 스크립트에서 샘플 레코드를 추가합니다.

  4. 필드를 선택합니다. 이 예에서는 이메일을 선택하여 연락처의 이메일 주소를 변경합니다.

    메일 편집

  5. 삭제 단추 을 선택하여 레코드를 삭제합니다.

레코드를 읽고, 편집하고, 만들고, 삭제할 수 있는 샘플이 포함된 웹 페이지를 만들었으므로 이제 양식과 레이아웃을 사용자 지정할 수 있습니다.

다음 단계

HTTP 요청 작성 및 오류 처리

참고 항목:

포털 웹 API 개요
포털은 웹 API를 사용하여 작업을 쓰고 업데이트하고 삭제합니다
포털은 웹 API를 사용하여 작업을 읽습니다
열 권한 구성

참고

귀사의 설명서 언어 기본 설정에 대해 말씀해 주시겠습니까? 간단한 설문 조사에 응해주세요. (이 설문 조사는 영어로 되어 있습니다.)

이 설문 조사는 약 7분 정도 걸립니다. 개인 데이터는 수집되지 않습니다(개인정보처리방침).