Partager via


Dynamics CRM 2011 サンプル紹介 REST エンドポイントとページング

みなさん、こんにちは。

東京では先週末に桜が満開だったようです。桜を見ると気分が和らぎますね。

さて今回は、REST エンドポイントサンプルの締めくくりとして、ページングの
サンプルに触れたいと思います。

REST エンドポイントの制限とページング

REST エンドポイントでは、一度に付き最大 50 件のデータを返します。これは
パフォーマンスを考慮しての制限です。逆に、50 件以上のデータを取得して
画面に表示させたい場合には、続きのレコードから再度取得し、結果を
結合していく必要があります。

REST エンドポイントは、データを返す際に、まだデータがある場合には
そうと分かるように追加で情報を渡しています。その情報を利用して
続きのレコードから再度 50 件まで結果を取得できます。

事前準備

検証を行うためには、50 件以上の取引先企業データが必要となります。
サンプルデータは 50 件もありませんので、手元で 50 件以上のデータを
作成してください。

- UI から手動での作成
- サンプルデータ用の CSV を作成し、インポート
- SDK 利用

もっとも簡単にできるのは、2 番目かとおもいますが、REST サンプルを
紹介してきましたので、是非 3 番目も試してください。私の手元では、
Sample Account 01 ~ 99 と、既存のサンプルデータが存在する環境を
利用します。

付加情報の確認

では早速ページングの情報がどのように返るか見ていきましょう。

1. Internet Explorer を起動して、 REST エンドポイントを利用して
取引先企業を取得する。表示を簡潔にするため、名前のみ表示
…組織URL…./XRMServices/2011/OrganizationData.svc/AccountSet?$select=Name

2. 画面で結果を確認。私の環境では、サンプルデータから始まり、
Account Sample 36 までの合計 50件が表示。
image

3. 画面最下部に <link ref=”next” href=”<url>” /> があることを確認。これが
ページング情報です。URL 部のみをコピーして、Internet Explorer のアドレスに
貼り付け。実行してください。
image

結果は Sample Account 37 以降の 50 件を取得できました。これを繰り返し、取得できる
レコードが 50 件以下になった時点で、<link ref> はなくなります。

URL には何ページ目かを示す $skiptoken も付属しています。さて、これらの知識を
前提に、サンプルを紹介します。

サンプルは、sdk\samplecode\js\restendpoint\restendpointpaging に
あるものを利用します。動作を試すために、事前にこのフォルダにある
restendpointpagingjscript_1_0_0_0_managed.zip ファイルを、ソリューションとして
インポートしておいてください

このサンプルは、指定した数の取引先企業を取得できるもので、指定できる数が
50 より大きい、100、300、600、900 となっています。

image

このサンプルは以下のファイルで構成されています。
restendpointpaging.htm - 上記スクリーンショットの画面を提供
sdk.restendpointpaging.js - ページングを利用したデータの取得用
json2.js - JSON ライブラリ
restendpointpaging.css - スタイルシート

HTML ファイル

HTML ファイルでは画面の作成とスクリプトを保持しています。

スクリプトの読み込み restendpointpaging.htm ファイルでは、まずスクリプト類の読み込みが指定されます。
またスタイルシートファイルもここで指定します。

<script src="../ClientGlobalContext.js.aspx"></script>
<script src="Scripts/SDK.RestEndpointPaging.js" type="text/javascript"></script>
<script src="Scripts/json2.js" type="text/javascript"></script>
<link href="Styles/RestEndpointPaging.css" rel="stylesheet" type="text/css" />

独自スクリプト
各種ファイル読み込み後、独自のスクリプトが定義されています。

<script type="text/javascript">
  var accountsGrid; // 画面に出力する際の、 tbody 要素を保持
  var numberOfAccountsToRetrieve; // 取得する取引先企業数 (100、300、600、900)
  var btnRetrieveAccounts; // 取得実行ボタン
  onload = function () {

   // 画面から btnRetrieveAccounts ボタンを取得
   btnRetrieveAccounts = document.getElementById("btnRetrieveAccounts");
   // 画面から、accountsGrid を取得
   accountsGrid = document.getElementById("accountsGrid");
   // 画面から、 numberOfAccountsToRetrieve を取得
   numberOfAccountsToRetrieve = document.getElementById("numberOfAccountsToRetrieve");
   // ボタンのクリックイベントに retrieveAccounts 関数をセット
   btnRetrieveAccounts.onclick = retrieveAccounts;
   btnRetrieveAccounts.click();
  }

  function retrieveAccounts() {
   clearaccountsGrid(); // accountsGrid のデータをクリア

   // numberOfAccountsToRetrieve から検索数を取得して数値に変換
   var number = parseInt(numberOfAccountsToRetrieve.options[numberOfAccountsToRetrieve.selectedIndex].value, 10);
   // 取得列として名前と電話番号、また検索数を設定
   var filter = "/AccountSet?$select=Name,Telephone1&$top=" + number;
   // 別 JScript ファイルの RetrieveRecords 関数を、フィルターおよびコールバックを指定して実行
   SDK.RestEndpointPaging.RetrieveRecords(filter, retrieveAccountsCallBack);
  }

  function retrieveAccountsCallBack(retrievedAccounts) {
   // 取得した取引先企業の数だけループ
   for (var i = 0; i < retrievedAccounts.length; i++) {
    // 取引先企業を取得
    var account = retrievedAccounts[i];
    // 結果表示テーブル用の行を作成
    var row = document.createElement("tr");
    // 行にセットする名前用の列を作成
    var nameCell = document.createElement("td");
    // 名前の列に取引先企業名をセット
    nameCell.innerText = account.Name;
    // 行に作成した名前用の列を追加
    row.appendChild(nameCell);
    // 同じように電話番号列も作成して追加
    var mainPhoneCell = document.createElement("td");
    mainPhoneCell.innerText = (account.Telephone1 == null) ? "" : account.Telephone1;
    mainPhoneCell.className = "rightColumn";
    row.appendChild(mainPhoneCell);
    // グリッドに作成した行を追加
    accountsGrid.appendChild(row);
   }
  }

  function clearaccountsGrid() {
   // グリッドの全部の列を削除
   for (var i = accountsGrid.rows.length - 1; i >= 0; i--) {
    accountsGrid.deleteRow(i);
   }
  }
</script>

UI 部分
UI 部分として、グリッド、ボタン、ドロップダウンを作成しています。ドロップダウンには
取得件数を指定できるよう、100、300、600、900 の数値がハードコードされています。

sdk.restendpointpaging.js ファイル

ではスクリプトファイルを確認しましょう。今までのサンプル同様、REST エンドポイントを
利用して、データの取得を行っているだけですが、コールバック部分でページングの
処理を追加してあります。

RetrieveRecordsCallBack: function (retrieveRecordsReq, callback) {
  // HTTP リクエストのステータスから、処理結果を確認
  if (retrieveRecordsReq.readyState == 4 /* complete */) {
   if (retrieveRecordsReq.status == 200) {
    // 成功の場合、JSON 形式からオブジェクトへ変換
    var retrievedRecords = JSON.parse(retrieveRecordsReq.responseText).d;
    /// HTML 側にあるコールバック関数が呼ばれる
    callback(retrievedRecords.results);

    // 結果として取得したオブジェクトに __next の値がある場合はページング処理
    if (null != retrievedRecords.__next) {
     // 次のページ用に OData パス以降の部分のみ切り出して、フィルターに指定
     var filter = retrievedRecords.__next.replace(SDK.RestEndpointPaging.GetODataPath(), "");
     // 再度 RetrieveRecords 関数呼び出して、このコールバックに戻ってくる
     SDK.RestEndpointPaging.RetrieveRecords(filter, callback);
    }
   }

以上のように、結果からページングの情報の有無を確認し、存在する場合には
新しい URL (上記の場合はフィルタ部分のみ活用) を利用して続きのデータを
取得しています。

まとめ

ページング処理は通常、開発者側がパフォーマンスを考慮して設定するものですが、
Dynamics CRM 2011 では既定でページング処理が存在するため、そこをハンドリングして
ページングの境界を越えたデータの取得を処理する必要があります。

これは Silverlight アプリケーションのも言えますが、同様のサンプルが Silverlight
バージョンも存在しますので、是非試してください。

- Dynamics CRM サポート 中村 憲一郎