【Dynamics CRM 2011】RESTを使ってデータを作成/更新/削除する
前回の続きです。
RESTを使用することでデータの操作を行うことが出来ます。基本的にただのPOSTメソッドです。リファレンスを読むだけでも普通に作れるとは思いますが、翻訳が壊れているので一応やり方をメモしておきます。
使用できるメソッドとx-http-method
データの取得はGETメソッド、データの作成はPOSTメソッドです。更新と削除はどうするのかと言うと、完全に忘れ去られた技術であるPUT/DELETEメソッドを使う…わけではなく、POSTメソッドでx-http-methodと言うヘッダにコマンドを指定してあげます。(※「x-http-method-override」ではないので注意)
リファレンスにHTTPリクエストの例が載っているのでそれを見れば大体わかりますが、以下の三つを指定することが出来ます。
- PUT
- MERGE
- DELETE
PUTとDELETEは読んで字の如くですが、MERGEは何なのでしょう。
これも(読みにくいけど)リファレンスに書いてあります。PUTでは指定された項目だけが更新され、指定されなかった項目は規定値が適用されます。(規定値がなければNULL)
MERGEでは指定された項目だけを更新し、指定されなかった項目に対しては何も変更しません。変更しないだけで全項目を更新しているようです。当然全メソッドでプラグインetcも動きます。
「速度を気にするならPUTを使ってください」みたいなことが書いてありますが、この説明だけだと「結局全項目を指定するから意味がないんじゃ?」と思うかもしれません。これはURIに多少書き加えることで個別のフィールドを更新できるから、それを使えと言うことなのでしょう。方法に関しては後述します。
ATOMとJSON
POSTするデータはATOM(XML)形式とJSON形式があります。リファレンスの例を読めばわかりますが、ATOMを使う理由はまずありません。(面倒くさすぎる)
この記事の例もすべてJSONで記述します。
URI
前回のGETメソッドと同じです。Contactであれば、以下の通りです。
[Your Organization Root URL]/XRMServices/2011/OrganizationData.svc/ContactSet
今回はGETではないので?は必要ありません。
また、PUT/MERGE/DELETEのような、あるレコードを特定する場合は末尾にGUIDを付与する必要があります。
[Your Organization Root URL]/XRMServices/2011/OrganizationData.svc/ContactSet(guid'xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx')
ちなみに、GUIDを指定した状態のURIもGETメソッドで投げることが出来ます。対象のレコードが1件返って来ます。デバッグなどにどうぞ。
POSTメソッド
x-http-methodを指定しない普通のPOSTメソッドです。要はCreateです。
エンティティ名はURIに組み込まれているので、後は普通に渡したいJSONを作ってあげるだけです。
{"FirstName":"ほげ","LastName":"ぴよ"}
前回確認したJSONの形式であればOKです。当然OptionSetやLookup、Money型の場合は、そう言った形に直してやる必要があります。
ただ、__metadataはなくても問題ありません。例えばStateCodeであれば
{"StateCode": {"Value":1}}
と言う形にしておけばOKです。Lookupの場合は
{"FugaLookup": {"Id":"xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx"}}
となります。指定できるエンティティが複数ある場合はLogicalNameも指定してあげないとダメだと思います。(面倒なので未検証)
このルールはPUT/MERGEメソッドでも同様に守る必要があります。
ちなみに、POSTするデータを配列にしたからと言って複数レコードを同時に作ることはできません。何でできないんでしょうね?
MERGEメソッド
URIの末尾にGUIDを付与し、x-http-methodをMERGEにし、Createの時と同じようにPOSTデータを指定すればOKです。
PUTメソッド
MERGEメソッドのx-http-methodをPUTに変えただけにすると、先述した通り、JSONで指定しなかったフィールドは初期化されます。
ある特定のフィールドのみを変更する場合はURIを変更する必要があります。例えばLastNameのみ変更したい場合は
[Your Organization Root URL]/XRMServices/2011/OrganizationData.svc/ContactSet(guid'xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx')/LastName
とすればOKです。(当然これもGETメソッドで確認できる)
この状態でもちゃんとJSONを作ってあげる必要があります。
{"LastName":"ぴよぴよ"}
これをPOSTすればLastNameのみを変更することができます。性能の差がどれぐらい出るのかは知りません。
DELETメソッド
基本的にはMERGEと同じです。x-http-methodをDELETEに変え、POSTするデータを空にすればOKです。
ただし、ヘッダのContentLengthは指定する必要があります。0にでもしておきましょう。
まとめ
そこまでややこしくはないと思います。
ただ、データの型によってパース/POSTする方法が微妙に変わるにも関わらず、RESTではメタデータを取得する方法がありません。
汎用的なライブラリを作るとなると相当骨が折れると思います。GETは力技でどうにかなると思いますが、POSTになると、型がわかっていることが前提です。
どうしてもその辺を解決したいのであればメタデータを何らかの形で静的に保持するぐらいしかないでしょう。その環境から他の方法で動的にメタデータを取得できるのであれば、そもそもRESTを使う必要はないと思います。
使えるものはHTTPのみ、ハードコーディングも已む無し、そんなケース以外では、基本的にやめておいた方がいいです。