Dynamics CRM 2011 サンプル紹介 REST エンドポイントを利用した jQuery

みなさん、こんにちは。

今日から四月ですが、相変わらず寒いです。体調はいかがでしょうか?

今回も引き続き REST エンドポイントのサンプルを紹介します。前回 は REST
エンドポイントを利用する JScript のサンプルで、一部 json2.js ライブラリを使っていました。
今回は jQuery ライブラリを併用したサンプルを紹介します。

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

サンプルの動作は前回同様、取引先企業の作成、読み取り、更新、削除です。
またコードをシンプルかつ再利用可能にするために、各操作用のスクリプトと
それらを呼出すメイン側のスクリプトに分けています。

では先に各操作用のスクリプトから解説します。

JScript サンプル - jqueryrestdataoperationfunctions.js

前回のサンプルでは、まず変数を定義して、そこにサーバーの URL 等の
情報を取り込んでいましたが、今回のサンプルでは変数定義時に、値も
代入しています。コンテキストは前回同様 ClientGlobalContext.js.aspx
から取り込んでいます。こちらの詳細は、今回は省略します。

変数の定義と値代入

まず変数を定義して、値を代入しています。内容は前回と同じです。
var context = GetGlobalContext();
var serverUrl = context.getServerUrl();
var ODATA_ENDPOINT = "/XRMServices/2011/OrganizationData.svc";

createRecord 関数

次にレコード作成用の関数を定義しています。4 つの引数を受け取ります。
entityObject - 作成するエンティティレコードのデータ ※必須
odataSetName - 使用するエンドポイント用の名前 ※必須
successCallback - 成功時のコールバック名
errorCallback - 失敗時のコールバック名

では中身を見ていきます。
function createRecord(entityObject, odataSetName, successCallback, errorCallback) {

// entityObject が存在するか確認
if (!entityObject) {
  alert("entityObject is required.");
  return;
}
// エンドポイント用の名前が存在するか確認
if (!odataSetName) {
  alert("odataSetName is required.");
  return;
}

// json2.js の stringify を利用して、オブジェクトを JSON 形式にシリアライズ
var jsonEntity = window.JSON.stringify(entityObject);

// jQuery の非同期 AJAX 関数を使用して、HTTP 通信を記述
// 戻り値は HTTP Response 
$.ajax({
  type: "POST", // 作成なので POST HTTP 動詞
  contentType: "application/json; charset=utf-8", // コンテントタイプを設定
  datatype: "json",
  url: serverUrl + ODATA_ENDPOINT + "/" + odataSetName, // エンドポイント組み立て
  data: jsonEntity, // シリアライズした値をデータとして設定
  // beforeSend を利用して、実際のリクエスト前に処理を実行
  beforeSend: function (XMLHttpRequest) {
   // HTTP リクエストのヘッダーをセット       
   XMLHttpRequest.setRequestHeader("Accept", "application/json");
  },
  // 処理が成功した場合
  success: function (data, textStatus, XmlHttpRequest) {
   // 成功時のコールバックがあれば、それを呼出す
   if (successCallback) {
    // data.d とは作成された CRM オブジェクト
    successCallback(data.d, textStatus, XmlHttpRequest);
   }
  },
  // 処理が失敗した場合
  error: function (XmlHttpRequest, textStatus, errorThrown) {
   // 失敗時のコールバックがあればそれを呼出す
   if (errorCallback)
    errorCallback(XmlHttpRequest, textStatus, errorThrown);
   else
    // なければ独自のエラーハンドラー関数を呼出す
    errorHandler(XmlHttpRequest, textStatus, errorThrown);
  }
});
}

前回は直接 HTTPRequest を作成して、値を代入していきました。
jQuery を利用してもその手間が省けるわけではありませんが、記述が
スッキリして、再利用性が高まったのではないでしょうか。では他の
関数も見ていきましょう。

retrieveRecord 関数

createRecord と同じく 4 つの引数を受け取ります。
id - 取得するレコードの ID  ※必須
odataSetName - 使用するエンドポイント用の名前 ※必須
successCallback - 成功時のコールバック名
errorCallback - 失敗時のコールバック名

中身は以下の通りです
function retrieveRecord(id, odataSetName, successCallback, errorCallback) {

// ID が存在するか確認
if (!id) {
  alert("record id is required.");
  return;
}
// エンドポイント用の名前が存在するか確認 
if (!odataSetName) {
  alert("odataSetName is required.");
  return;
}

// jQuery の非同期 AJAX 関数を使用して、HTTP 通信を記述
$.ajax({
  type: "GET",  // 取得なので GET HTTP 動詞
  contentType: "application/json; charset=utf-8",
  datatype: "json",
  // データ取得用の REST エンドポイント作成
  url: serverUrl + ODATA_ENDPOINT + "/" + odataSetName + "(guid'" + id + "')",
  beforeSend: function (XMLHttpRequest) {
   // HTTP リクエストのヘッダーをセット                     
   XMLHttpRequest.setRequestHeader("Accept", "application/json");
  },
  success: function (data, textStatus, XmlHttpRequest) {
   if (successCallback) {
    successCallback(data.d, textStatus, XmlHttpRequest);
   }
  },
  error: function (XmlHttpRequest, textStatus, errorThrown) {
   if (errorCallback)
    errorCallback(XmlHttpRequest, textStatus, errorThrown);
   else
    errorHandler(XmlHttpRequest, textStatus, errorThrown);
  }
});
}

基本的な構造は同じで、HTTP 動詞や REST の URI だけ変わっています。

retrieveMultiple 関数

複数のレコード取得用関数です。同じく 4 つの引数を受け取ります。
odataSetName - 使用するエンドポイント用の名前 ※必須
filter - 検索条件 
successCallback - 成功時のコールバック名
errorCallback - 失敗時のコールバック名

中身は以下の通りです。
function retrieveMultiple(odataSetName, filter, successCallback, errorCallback) {

// エンドポイント用の名前が存在するか確認
if (!odataSetName) {
  alert("odataSetName is required.");
  return;
}

// REST エンドポイント組み立て
var odataUri = serverUrl + ODATA_ENDPOINT + "/" + odataSetName + "()";

// 検索条件がある場合には、URI に付加
if (filter) {
  odataUri += filter;
}

// jQuery の非同期 AJAX 関数を使用して、HTTP 通信を記述
$.ajax({
  type: "GET", // 取得なので GET HTTP 動詞
  contentType: "application/json; charset=utf-8",
  datatype: "json",
  url: odataUri,
  beforeSend: function (XMLHttpRequest) {
   // HTTP リクエストのヘッダーをセット        
   XMLHttpRequest.setRequestHeader("Accept", "application/json");
  },
  success: function (data, textStatus, XmlHttpRequest) {
   // 成功時のコールバックがあれば、それを呼出す
   if (successCallback) {
    // 取得した結果データに CRM オブジェクトと results が含まれる場合
    if (data && data.d && data.d.results) {
     successCallback(data.d.results, textStatus, XmlHttpRequest);
    }
    // 取得した結果データに CRM オブジェクトしか含まれない場合
    else if (data && data.d) {
     successCallback(data.d, textStatus, XmlHttpRequest);
    }
    // それ以外
    else {
     successCallback(data, textStatus, XmlHttpRequest);
    }
   }
  },
  error: function (XmlHttpRequest, textStatus, errorThrown) {
   if (errorCallback)
    errorCallback(XmlHttpRequest, textStatus, errorThrown);
   else
    errorHandler(XmlHttpRequest, textStatus, errorThrown);
  }
});
}

この関数は、サンプル内で呼ばれることはありませんが、次回紹介する
サンプルで利用されています。

updateRecord 関数

レコード更新用関数です。5 つの引数を受け取ります。
id - 更新するレコードの ID ※必須
entityObject - 実際にアップデートする内容を持ったオブジェクト ※必須
odataSetName - 使用するエンドポイント用の名前 ※必須
successCallback - 成功時のコールバック名
errorCallback - 失敗時のコールバック名

function updateRecord(id, entityObject, odataSetName, successCallback, errorCallback) {

// ID が存在するか確認
if (!id) {
  alert("record id is required.");
  return;
}
// エンドポイント用の名前が存在するか確認
if (!odataSetName) {
  alert("odataSetName is required.");
  return;
}

// json2.js の stringify を利用して、オブジェクトを JSON 形式にシリアライズ 
var jsonEntity = window.JSON.stringify(entityObject);

// jQuery の非同期 AJAX 関数を使用して、HTTP 通信を記述
$.ajax({
  type: "POST", // 更新処理なので POST HTTP 動詞をまず定義
  contentType: "application/json; charset=utf-8",
  datatype: "json",
  data: jsonEntity,
  url: serverUrl + ODATA_ENDPOINT + "/" + odataSetName + "(guid'" + id + "')",
  beforeSend: function (XMLHttpRequest) {
   // HTTP リクエストのヘッダーをセット        
   XMLHttpRequest.setRequestHeader("Accept", "application/json");

   // 更新処理なので、MERGE メソッドを定義      
   XMLHttpRequest.setRequestHeader("X-HTTP-Method", "MERGE");
  },
  success: function (data, textStatus, XmlHttpRequest) {
   // 更新処理では、結果のデータは返ってこないため、新規に作成
   data = new Object();
   // ID を設定
   data.id = id;
   if (successCallback) {
    successCallback(data, textStatus, XmlHttpRequest);
   }
  },
  error: function (XmlHttpRequest, textStatus, errorThrown) {
   if (errorCallback)
    errorCallback(XmlHttpRequest, textStatus, errorThrown);
   else
    errorHandler(XmlHttpRequest, textStatus, errorThrown);
  }
});
}

deleteRecord 関数

メソッドで DELETE を使っている以外新しいことはないので省略します。

JScript サンプル - jqueryrestdataoperationactions.js

jqueryrestdataoperationactions.js は、上記で解説した関数を
順次呼出すためのスクリプトです。目新しいものはありませんが、初めの
$() 内に一番初めに実行する関数が入っているところがポイントです。

jQuery では、$() 内に記述した内容は、OnLoad 時に自動実行されます。
このサンプルでは関数名を渡すのではなく、関数の中身をまるまる
渡して処理をしています。

ホストする HTML ファイル

前回のサンプル同様、Web リソース作成時に、接頭辞を階層に見立て
相対パスで各種スクリプトを読み込んでいます。

<script src="../ClientGlobalContext.js.aspx"></script>     
<script src="Scripts/jquery1.4.1.min.js" type="text/javascript"></script> 
<script src="Scripts/json2.js" type="text/javascript"></script>
<script src="Scripts/JQueryRESTDataOperationFunctions.js" type="text/javascript"></script>
<script src="Scripts/JQueryRESTDataOperationActions.js" type="text/javascript"></script>

ここで読み込んでいる jquery1.4.1.min.js は、縮小版と呼ばれるもので、内容は同じですが
コメントやスペースなどを省き、ファイルサイズを最適化したものになります。

また残り部分は以下のように、初めに呼出す関数の指定がありません。これは
jQuery の機能を利用して、 $() ではじめに実行する内容をすでに指定している
ためです。

</head>
<body>    
    <div id="status" />    
</body>
</html>

動作の確認

では最後に動作の確認をしたいと思います。サンプルのソリューションをインポートした後、
設定 | カスタマイズ | システムのカスタマイズを開きます。 Web リソースをクリックして、
sample_/JQueryRESTDataOperations.htm を開き、下部リンクをクリックします。

image

まとめ

jQuery は多機能な JScript ライブラリです。また Visual Studio 2010 用のスニペットなども
提供されております。(詳細はリンクのブログ参照)

今回は HTTP Request を作成する jQuery.ajax を使用するサンプルを紹介しました。他にも
取引先担当者を UI から操作するサンプルとして REST Endpoint jQuery Contact Editor が
提供されています。次回はこちらを紹介したいと思います。

このように、すでに公開されているライブラリをうまく使って開発をすることで、開発効率
だけでなく、保守性もあがり、また再利用性も高まります。すでに何かしらのライブラリを
使われている場合には、是非そちらのライブラリを利用して Dynamics CRM のクライアント
拡張に活かすことができるか試してみてください。

参考リンク
Visual Studio 2010 で jQuery のコード スニペットを使おう
https://blogs.msdn.com/b/chack/archive/2009/12/22/jquery-code-snippets-for-visual-studio-2010.aspx

jQuery 公式サイト
https://jquery.com/
jQuery.ajax 関数詳細
https://api.jquery.com/jQuery.ajax/

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