読者です 読者をやめる 読者になる 読者になる

【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に多少書き加えることで個別のフィールドを更新できるから、それを使えと言うことなのでしょう。方法に関しては後述します。

ATOMJSON

POSTするデータはATOMXML)形式と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のみ、ハードコーディングも已む無し、そんなケース以外では、基本的にやめておいた方がいいです。