Quantcast
Channel: Japan Microsoft Dynamics 365 Team Blog
Viewing all 589 articles
Browse latest View live

Dynamics CRM Online 2015 Update 1 SDK 新機能: プラグインおよびユーザー定義ワークフロー活動の追跡

$
0
0

みなさん、こんにちは。

今回は Dynamics CRM Online 2015 Update 1 で提供されるプラット
フォームと SDK の新機能より、プラグインおよびユーザー定義
ワークフロー活動の追跡を紹介します。

概要

同期のプラグインやユーザー定義ワークフロー活動の処理が失敗
した場合、これまではユーザーの画面にしかエラーが出力されず
開発者が後から詳細を確認するには、ユーザーがエラーを保存
しておく必要がありました。

今回のリリースではそれらのエラーをサーバー側に保存しておき、
開発者が後から簡単に確認できる機能が提供されます。

設定方法

プラグインおよびユーザー定義ワークフロー活動の追跡は既定で
無効となっており、以下の手順で有効にできます。尚、ログは
他エンティティのレコード同様にディスクを消費するため、必要
に応じて有効/無効を変更してください。

1. ブラウザで Dynamics CRM Online に接続します。

2. 設定 | 管理 | システムの設定よりカスタマイズタブを開きます。

3. 「プラグイントレースログへのログ記録を有効化」を「例外」
または「すべて」に変更して、「OK」をクリックします。

image

例外: エラーが発生した場合のみトレースを保存。
すべて: エラーおよび一般的なトレースを保存。

今回は検証のため「すべて」を選択します。

事前準備

まずはプラグインを開発して、登録します。

プラグインの開発

1. Visual Studio を開きます。

2. 新規プロジェクトよりクラスライブラリを選択し、プロジェクト
名を「TraceSample」と入力します。また .NET Framework 4.5.2 が
選択されている事を確認します。

※この記事では C# を利用しますが VB.NET でも基本は同じです。

image

3. プロジェクトを右クリックして「NuGet パッケージの管理」
を選択します。

image

4. 左ペインで「オンライン」を選択して、crmsdk を検索します。
「Microsoft Dynamics CRM 2015 SDK core assemblies を選択して
インストールします。

image

5. プロジェクトを右クリックして、プロパティをクリックします。
署名タブより「アセンブリに署名する」にチェックを入れます。
ドロップダウンより「新規作成」をクリックします。

image

6. 任意のキーファイル名とパスワードを指定して「OK」クリック
します。

7. Class1.cs の中身を以下のコードと差し替えます。

using Microsoft.Xrm.Sdk;
using System;

namespace TraceSample
{
    public class TraceSample : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {           
            ITracingService tracingService =
                (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            IPluginExecutionContext context = (IPluginExecutionContext)
                serviceProvider.GetService(typeof(IPluginExecutionContext));
           
            IOrganizationServiceFactory serviceFactory =
                (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
           
            IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
           
            if (context.InputParameters.Contains("Target") &&
                context.InputParameters["Target"] is Entity)
            {               
                Entity entity = (Entity)context.InputParameters["Target"];

                if (entity.LogicalName != "account")
                    return;

                // 名前に「失敗」が含まれていると例外を出す
                if(entity["name"].ToString().Contains("失敗"))
                {
                    tracingService.Trace("失敗をトレースに記述");
                    throw new InvalidPluginExecutionException("エラー発生");
                }
                else
                    tracingService.Trace("成功をトレースに記述");
            }

        }
    }
}

8. プロジェクトをビルドします。

プラグインの登録

1. 以下の URL より Dynamics CRM 2015 用の SDK を取得します。

http://www.microsoft.com/en-us/download/details.aspx?id=44567

2. ダウンロードしたファイルを任意のフォルダに解凍します。

3. SDK\Tools\PluginRegistration\PluginRegistration.exe を実行します。

4. 「CREATE NEW CONNECTION」をクリックして接続を設定します。
「Login」をクリックして組織に接続します。

image

5. 「Register」より「Register New Assembly」をクリックします。

image

6. 開発したプラグインを選択して登録します。

7. 登録したプラグインを展開後、右クリックより 「Register New
Step」をクリックします。

image

8. Create メッセージ、account エンティティの Pre-operation を
選択します。その他は既定のままです。

image

9. 「Register New Step」をクリックして登録を完了します。

動作確認

最後に動作を確認します。

1. 「トレーステスト」という名前で取引先企業を作成します。

2. 続いて「トレーステスト失敗」と名前でも作成します。
意図したとおり、画面にエラーが表示されます。「ファイル
のダウンロード」よりログを保存しておきます。

image

3. 設定 | プラグイン トレース を選択します。

image

4. ログが 2 件出ています。1 つ目のログを開きます。メッセージ
ブロックにトレースのメッセージが、例外の詳細に例外が出て
いることを確認します。

image

5. 2 つ目のログを開きます。メッセージブロックにトレースの
メッセージが出ていることを確認します。

image

まとめ

プラグインやユーザー定義ワークフロー活動で発生した問題の
トレースをサーバー側に保存できることは、開発者にとっては
非常に便利です。是非ご活用ください!

- 中村 憲一郎


Dynamics CRM Online 2015 Update 1 SDK 新機能: FetchXML の新しい検索条件

$
0
0

みなさん、こんにちは。

今回は Dynamics CRM Online 2015 Update 1 で提供されるプラット
フォームと SDK の新機能より、FetchXML に追加された新しい検索
条件を紹介します。

概要

今回のリリースで、以下の検索条件が追加されました。

X 分よりも古い
X 日よりも古い
X 週間よりも古い
X 年間よりも古い

尚、X か月よりも古いは以前からサポートされています。

高度な検索

高度な検索は FetchXML を利用してクエリを作成/実行しています。
今回追加された検索条件は高度な検索でも利用可能です。

image

カスタマイズ

レポート、システムビュー、ユーザービューなどビューの定義も
FetchXML を利用でるため、今回追加された検索条件が利用できます。

SDK

SDK としては FetchXML の検索条件追加に伴い、QueryExpression が
同様の検索条件をサポートしています。

FetchXML の条件

X 分よりも古い

<condition attribute="<AttributeName>" operator="olderthan-x-minutes" value="<VALUE>" />

※この条件は DateOnly と指定された DateTime 列ではサポートされません。

X 時間よりも古い

<condition attribute="<AttributeName>" operator="olderthan-x-hours" value="<VALUE>" />

※この条件は DateOnly と指定された DateTime 列ではサポートされません。

X 日よりも古い

<condition attribute="<AttributeName>" operator="olderthan-x-days" value="<VALUE>" />

X 週間よりも古い

<condition attribute="<AttributeName>" operator="olderthan-x-weeks" value="<VALUE>" />

X か月よりも古い

<condition attribute="<AttributeName>" operator="olderthan-x-months" value="<VALUE>" />

X 年間よりも古い

<condition attribute="<AttributeName>" operator="olderthan-x-years" value="<VALUE>" />

QueryExpression の条件

ConditionOperator に以下条件が追加されました。

image

まとめ

今回の検索条件追加により、より柔軟なクエリが可能になりました。
是非お試しください!

- 中村 憲一郎

LINQPad 4 用 Dynamics CRM REST/Web API ドライバーが公開されました!

$
0
0

みなさん、こんにちは。

今日は先日公開された、LINQPad 4 用 Dynamics CRM REST および Web API 向け
ドライバーを紹介します。

REST 用: https://crmlinqpadrest.codeplex.com/
Web API 用: https://crmlinqpadwebapi.codeplex.com/

SOAP 用については、以下をご覧ください。
LINQPad 4 用 Dynamics CRM ドライバーが公開されました!

LINQPad とは

LINQPad (http://www.linqpad.net/) は LINQ クエリを様々なデータソースに対して
実行できる、開発者向けのツールです。また、LINQ クエリだけでなく C#/F#/VB
ステートメントやコードブロックを実行する機能持っています。一部の機能は
無償で提供されていますが、IntelliSense やデバッグ機能は有償となっています。

Dynamics CRM ドライバーの利用

LINQPad 4 用 Dynamics CRM REST/Web API ドライバーを使うと LINQPad の
データソースとして Dynamics CRM が指定できます。早速試してみましょう。

ドライバーのインストール

1. LINQPad がインストールされていない場合、http://www.linqpad.net/よりダウン
ロードしてインストールしてください。

2. REST 用と Web API 用のページより CRMLinqPadDriverREST.lpx ファイルと
CRMLinqPadDriverWebAPI.lpx ファイルをダウンロードします。

3. LINQPad を開いて、画面左上の Add connection リンクをクリックします。

image

4. 開いた画面で View more drivers… ボタンをクリックします。

image

5. 次の画面で Browse ボタンをクリックします。

6. ダウンロードした lpx ファイルを選択して “Open” をクリックします。

7. 同じ作業をもう一方の lpx にも実行します。

REST 用ドライバーの利用

まず REST 用 ドライバーの利用方法から紹介します。

接続の作成

1. データコンテキストの選択画面で Dynamics CRM REST Linq Pad Driver を
選択して Next をクリックします。

image

2. 既に ClientId がある場合、“Register to Azure AD automatically” のチェックを
外すと、ClientId を入力できます。ClientId の詳細は後ほど紹介します。不明な
場合は “Login to CRM” をクリックします。

image

3. 任意の組織にログインします。

image

4. 組織にログイン後、メタデータの取得が始まります。終わるまでしばらく待ちます。

5. Loading Data… の表示が消えたら、Exit ボタンをクリックします。LINQPad が
スキーマを作成するので、またしばらく待ちます。完了すると以下の画面の様に
スキーマ一覧が表示されます。

image

LINQ クエリの実行

1. まずクエリウィンドウ右上にある Connection タブから、作成した接続を
選択します。複数の接続がある場合は適切なものを選択してください。

image

2. 以下のように LINQ クエリを入力します。

image

3. “Play” ボタンをクリックするか F5 キーを押下して実行します。

4. 結果の右側にある SQL タブを選択すると、実行した LINQ クエリに相当する
OData クエリが表示されます。

image

Web API ドライバーの利用

Web API は Dynamics CRM Online 2015 Update 1 でリリースされた機能で、
プレビューの扱いです。機能は既定で無効になっているため、以下手順で
有効にします。尚、Web API の詳細は今後の記事で紹介します。

Web API (プレビュー) の有効化

1. ブラウザで Dynamics CRM Online に接続ます。設定 | 管理 | システムの
設定を開きます。

2. プレビュータブをクリックして、機能を有効にします。
※「プレビューを有効にする」項目の「無効化する」と「無効化しない」
は誤訳であり、後日修正されます。以下の通りに設定してください。

image

接続の作成

1. データコンテキストの選択画面で Dynamics CRM Web API Linq Pad Driver を
選択して Next をクリックします。

image

2. 既に ClientId がある場合、“Register to Azure AD automatically” のチェックを
外すと、ClientId を入力できます。ClientId の詳細は後ほど紹介します。不明な
場合は “Login to CRM” をクリックします。

3. Web API を有効にした組織にログインします。ログイン完了後、自動的に
メタデータを取得するので、完了するまで待ちます。

4. Loading Data… の表示が消えたら、Exit ボタンをクリックします。

image

LINQ クエリの実行

1. まずクエリウィンドウ右上にある Connection タブから、作成した接続を
選択します。複数の接続がある場合は適切なものを選択してください。

image

2. 以下のように LINQ クエリを入力します。

image

3. “Play” ボタンをクリックするか F5 キーを押下して実行します。

4. 結果の右側にある SQL タブを選択すると、実行した LINQ クエリに相当する
OData クエリが表示されます。

image

C# ステートメントの実行

Web API はデータのクエリ以外に、関数の実行もサポートしています。
LINQ クエリに続いて、C# ステートメントも試してみましょう。

1. Language のドロップダウンより C# Statement(s) を選択します。
以下のステートメントを記述して実行します。結果が表示されます。

image

2. 結果の右側にある SQL タブを選択すると、実行した関数に相当する
OData クエリが表示されます。

image

3. より複雑なステートメントを実行することもできます。以下の例は
取引先企業の作成を行った後、作成したレコードを関連に設定した
営業案件を作成するコードです。

// 取引先企業の作成
DataServiceCollection<account> accounts = new DataServiceCollection<account>(this);
account myaccount = new account();
accounts.Add(myaccount);
// 列の値を設定
myaccount.name = "Test Account";
// 作成を実行
this.SaveChanges(SaveChangesOptions.PostOnlySetProperties);

// 営業案件の作成
DataServiceCollection<opportunity> opportunities = new DataServiceCollection<opportunity>(this);
opportunity myopportunity = new opportunity();
opportunities.Add(myopportunity);
// 列の値を設定
myopportunity.name = "Test Opps";
// 関連を設定
myopportunity.opportunity_customer_accounts = myaccount;

// 作成を実行
this.SaveChanges(SaveChangesOptions.PostOnlySetProperties);

Console.WriteLine("営業案件が作成されました。");

Azure AD アプリケーションの登録

Dynamics CRM Online の REST および Web API エンドポイントは OAuth 2.0
による認証/認可をサポートしています。ただし OAuth 2.0 を利用するには、
事前にアプリケーション(今回の場合 LINQPad のドライバー) を Azure AD に
登録する必要があり、通常手動での作業が必要となります。
※手順は Walkthrough: Register a CRM app with Active Directory を参照。

これらの手作業をなくすために、ドライバーは Azure AD にアプリケーションを
自動登録する仕組みを含んでいます。詳細が気になる方は是非ソースコードを
確認してください。

既定では、Dynamics CRM にログインしたユーザー権限でアプリケーションの
登録を試しますが、権限が不足している場合は Azure AD に権限があるユーザー
を求められます。もし Azure AD が他のユーザーに管理されている場合は、別途
アプリケーションを登録していただき、ClientId を取得してください。

ClientId 取得後、以下の画面にて “Register to Azure AD” のチェックを外すことで
手動で ClientId を設定できます。

image

ツールで自動登録された場合、以下のように登録されます。

image

REST 用ドライバーを設置型で利用している場合は、Windows 統合
認証を利用するため、 AD FS に対する登録は不要です。

まとめ

LINQPad を利用すると、ちょっとしたクエリ確認や動作確認をしたい
場合に非常に便利です。是非お試しください!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 SDK 新機能: フォームスクリプトのサブグリッドの制御 その 1

$
0
0

みなさん、こんにちは。

今回から Dynamics CRM Online 2015 Update 1 で提供される SDK の
新機能よりフォームスクリプトのサブグリッド制御を紹介します。

概要

Dynamics CRM Online 2015 Update 1 まで、フォームスクリプトを
利用したサブグリッドの操作は Refresh のみサポートしていました。
今回のリリースでは以下が追加されました。

追加されたオブジェクト
- GridControl : サブグリッド自体の操作用
- Grid : グリッドに含まれる行 (レコード) の操作用
- GridRow : 特定の行 (レコード) の操作用
- GridRowData : レコードの特定列の操作用
- GridEntity : グリッドのエンティティ情報の操作用
- ViewSelector : グリッドのビューの操作用

サポートされる操作
- サブグリッドの OnLoad イベントの管理、エンティティ名取得
- サブグリッド内の行の取得
- 選択されている行の取得
- サブグリッド内の行数
- サブグリッドのエンティティ情報の取得
- サブグリッドのビューの取得と操作

今回は検証用のフォームスクリプトの作成と GridControl の機能
について紹介します。

GridControl オブジェクト

フォームスクリプトより GridControl オブジェクトを取得するには
Xrm.Page.getControl(“<サブグリッド名”>) 関数を利用します。この
コントロールは通常のコントロールが持つ setFocus や Notificaiton
関数の他に、以下の関数を持ちます。

- addOnLoad/removeOnLoad : OnLoad イベントの管理
- getEntityName : エンティティ名の取得
- getGrid : Grid オブジェクトの取得
- getViewSelector : サブグリッドビューの取得

早速試してみましょう。

フォームスクリプトの開発と設定

1. ブラウザで Dynamics CRM Online に接続します。

2. 設定 | カスタマイズ | システムのカスタマイズより Web リソース
を選択して、新規ボタンをクリックします。

image

3. 名前と表示名に「formscriptsample.js」と入力し、「種類」より
「スクリプト (JScript)」 を選び、「テキストエディター」をクリック
します。

image

4. 以下のスクリプトを貼り付けて、OK をクリックします。

function subGridSample()
{
  // サブグリッドの取得
  var contactGridControl = Xrm.Page.getControl("Contacts");
  // OnLoad 用の関数を作成
  var myContactsGridOnloadFunction = function () { alert("サブグリッドの OnLoad イベント") };
  // OnLoad イベントの設定
  contactGridControl.addOnLoad(myContactsGridOnloadFunction);

  // サブグリッドのエンティティ名を表示
  alert("サブグリッドのエンティティ名: " + contactGridControl.getEntityName());

  // サブグリッドの更新
  contactGridControl.refresh();
}

5. 公開ボタンをクリックしてから、画面を閉じます。

6. エンティティ | 取引先企業 | フォームを選択します。「取引先企業」
フォームを開きます。

image

7. 「フォームのプロパティ」ボタンをクリックします。

8. フォームの OnLoad イベントに開発した Web リソースと
関数を設定します。

image

9. フォームを一旦保存してから、カスタマイズを公開します。

動作確認

1. 任意の取引先企業レコードを開きます。

2. サブグリッドのエンティティ名が表示されます。

image

3. 続いて OnLoad イベントが発生してメッセージが表示されます。

image

まとめ

今回はまずフォームスクリプトの作成と GridControl の取得および
関数の実行を紹介しました。次回はいよいよサブグリッドの中身
についての操作を紹介します。お楽しみに!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 SDK 新機能: フォームスクリプトのサブグリッドの制御 その 2

$
0
0

みなさん、こんにちは。

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
フォームスクリプトのサブグリッド制御を紹介します。

前回記事からの続きとなりますので、まだご覧になっていない場合
以下のリンクよりご確認ください。

フォームスクリプトのサブグリッドの制御 その 1

今回は Grid、GridRow、GridRowData、GridEntity  オブジェクトを
紹介します。

Grid オブジェクト

Grid オブジェクトは GridControl オブジェクトより getGrid 関数で
取得します。Grid オブジェクトは以下の関数を持ちます。

- getRows : サブグリッド内の行を取得します。
- getSelectedRows : サブグリッド内で選択している行を取得します。
- getTotalRecordCount : サブグリッドの行数を取得します。これは
表示されている件数ではなく、ビュー定義の対象となる件数です。
※上限 5000 件

早速試してみましょう。

フォームスクリプトの開発と設定

1. 前回作成した Web リソースを開きます。

image

2. 新しく以下の関数を追加します。

function gridSample()
{
  // グリッドの取得
  var contactGrid = Xrm.Page.getControl("Contacts").getGrid();
  // グリッドのレコード数取得
  alert("取引先担当者グリッドにはレコードが " + contactGrid.getTotalRecordCount() + " 件あります。");
}

3. Web リソースを保存して、公開します。

4. 取引先企業のフォームより、任意の列の OnChange に gridSample
関数を割り当てます。ここでは説明列にしました。

image

5. 変更を保存してカスタマイズを公開します。

6. 任意の取引先企業レコードを開き、説明の内容を変更します。
カーソルが外れたタイミングで以下のメッセージが出ます。

image

7. 次に getTotalRecordCount 関数がビュー定義に相当する
レコード数を取得しているか確認するために、取引先担当者
サブグリッドで、取引先担当者を 6 人以上追加します。

8. 再度説明の内容を変更して OnChange を発生させます。
ビュー定義の該当するすべてのレコード数がカウンタされる
ことを確認します。

image

※関連が 5000 件以上ある場合は、以下のように表示されます。

image

GridRow オブジェクトと GridRowData オブジェクト

これらのオブジェクトはグリッドの列データを取得するための
橋渡し役になるためまとめて紹介します。

GridRow オブジェクトは Grid オブジェクトより getRows 関数
または getSelectedRows 関数で取得します。GridRow は以下の
関数を持ちます。

- getData : GridRowData を取得します。

GridRowData オブジェクトは GridRow の getData 関数で取得
します。GridRowData は以下の関数を持ちます。

- getEntity: GridEntity を取得します。

GridEntity オブジェクト

GridEntity オブジェクトは GridRowData の getEntity 関数で
取得します。GridEntity は以下の関数を持ちます。

- getEntityName: エンティティ名を取得します。
- getEntityReference: レコード (参照) を取得します。
- getId: レコードの ID を取得します。
- getPrimaryAttributeValue: レコードの主列の値を取得します。

※ getEntityReference を利用すると getPrimaryAttributeValue の
結果と getId の結果および getEntityName の結果を一度に取得
出来ます。

早速試してみましょう。

フォームスクリプトの開発と設定

1. 先ほど利用した Web リソースを開きます。

2. 新しく以下の関数を追加します。

function gridEntitySample()
{
  var result = "";
  // サブグリッド内の列を取得
  var rows = Xrm.Page.getControl("Contacts").getGrid().getRows();
  // 1行ずつ処理
  rows.forEach(function (row, i) {
    // Grid Entity の取得
    var gridEntity = row.getData().getEntity();
    result = result + gridEntity.getEntityReference().id + "\n";
  });
  alert(result);
}

3. Web リソースを保存して、公開します。

4. 取引先企業のフォームより、上記同様に OnChange に追加した
gridEntitySample 関数を割り当てます。

image

5. 変更を保存してカスタマイズを公開します。

6. 任意の取引先企業レコードを開き、説明の内容を変更します。
初めの 6 件のレコードの GUID が取得できます。

image

まとめ

今回はサブグリッド内のレコードの取得について紹介しました。
次回はサブグリッドビューの操作について紹介します。
お楽しみに!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 SDK 新機能: フォームスクリプトのサブグリッドの制御 その 3

$
0
0

みなさん、こんにちは。

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
フォームスクリプトのサブグリッド制御を紹介します。

前回記事からの続きとなりますので、まだご覧になっていない場合
以下のリンクよりご確認ください。

フォームスクリプトのサブグリッドの制御 その 1
フォームスクリプトのサブグリッドの制御 その 2

今回は ViewSelector オブジェクトを紹介します。

ViewSelector オブジェクト

ViewSelector オブジェクトは Grid オブジェクトより getViewSelector
関数で取得します。ViewSelector オブジェクトは以下の関数を持ちます。

- getCurrentVIew: 現在のビューを取得します。
- setCurrentView: ビューを設定します。
- isVisible: ビューセレクターが表示されているか確認できます。

早速試してみましょう。

isVisible と getCurrentView の利用

1. 以前の記事で作成した Web リソースを開きます。

image

2. 新しく以下の関数を追加します。

function viewSelectorSample()
{
  // viewSelector の取得
  var selector = Xrm.Page.getControl("Contacts").getViewSelector();
  // ビューの表示状況を確認
  if(selector.isVisible())
  {
    alert("ビューは選択可能です。");
  }
  else
  {
    alert("ビューは選択不可能です。");
  }

  // 現在のビューを確認
  var current = selector.getCurrentView();
  alert("エンティティタイプ: " + current.entityType + "\nビューの id: " + current.id + "\nビューの名前: " + current.name);
}

3. 保存して、Web リソースを公開します。

4. 取引先企業のフォームの OnLoad に設定します。尚、以前設定した
ものは削除してください。

image

5. 保存してカスタマイズを公開します。

動作確認

1. 任意の取引先企業レコードを開きます。以下のメッセージが
表示されます。

image

image

2. ビューの選択ができない状態になっているので、フォームの
カスタマイズより、取引先担当者サブグリッドのビュー選択を
可能に変更します。

image

3. カスタマイズを公開後、再度取引先企業レコードを開くと以下の
メッセージが出ます。

image

setCurrentView の利用

最後に異なるビューをサブグリッドに設定してみます。

1. 設定 | カスタマイズ | システムのカスタマイズより、エンティティ |
取引先担当者 | ビューを選択します。

image

2. サブグリッドに設定したい任意のビューを開きます。この記事では
「あなたがフォローする」を利用してみます。アドレスバーの
URL より id を抜き出します。

image

3. 先ほどの Web リソースに新しい関数を追加します。

function changeViewSample()
{
  // 新しいビューの作成
  var ContactsIFollow = {
    entityType: 1039, // SavedQuery
    id:"{3A282DA1-5D90-E011-95AE-00155D9CFA02}",
    name: "あなたがフォローする 取引先担当者"
  };
  // ビューの設定
  Xrm.Page.getControl("Contacts").getViewSelector().setCurrentView(ContactsIFollow);
}

4. 保存して Web リソースを公開します。

5. 取引先企業フォームのカスタマイズより、任意のフィールドの
OnChange イベントに作成した関数を設定します。この記事では
説明フィールドを利用しました。

image

6. 変更を保存してカスタマイズを公開します。

動作確認

1. 任意の取引先企業レコードを開きます。取引先担当者のサブグリッド
のビューが既定であることを確認します。

image

2. 説明列を変更します。取引先担当者のサブグリッドビューが更新
されたことを確認します。

image

まとめ

今回のリリースではサブグリッドの操作が非常に柔軟になりました。
これによりあるサブグリッドビューの OnLoad イベントを利用して
他のサブグリッドのビューを変更するなど、今までできなかった
事が出来るようになっています。是非お試しください!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 SDK: クライアントサイドスクリプト その他の新機能

$
0
0

みなさん、こんにちは。

今回は Dynamics CRM Online 2015 Update 1 で提供される SDK の
新機能より、フォームスクリプトでのサブグリッド操作以外の
その他の新機能を紹介します。

サブグリッドの操作については、以下の記事をご覧ください。

フォームスクリプトのサブグリッドの制御 その 1
フォームスクリプトのサブグリッドの制御 その 2
フォームスクリプトのサブグリッドの制御 その 3

追加された機能

今回のリリースは、以下のクライアントサイドスクリプトの機能が
追加されています。

- 簡易作成フォームを開く
- レコードを別のウィンドウで開く
- 日付列で時刻が出ているかを確認する
- スクリプトを実行しているデバイスの種類を取得する

簡易作成フォームを開く

ユーザーに新規レコードを作成させたい場合、簡易作成フォームを
明示的に開くことができます。

Xrm.Utility.openQuickCreate 関数

openQuickCreate 関数を利用することで、簡易作成フォームを開く
事ができます。この関数は以下のパラメーターを取ります。

Xrm.Utility.openQuickCreate(entityLogicalName,createFromEntity,parameters).then(successCallback, errorCallback);

パラメーター名: entityLogicalName
型: String
必須項目か: はい
説明: 作成するエンティティの論理名

パラメーター名: createFromEntity
型: Lookup
必須項目か: いいえ
説明: 元となるエンティティ。関連のマッピングを利用したい場合は
指定してください。

パラメーター名: parameters
型: Object
必須項目か: いいえ
説明: 既定値の設定。フィールド名/値の配列

パラメーター名:successCallback
型: Function
必須項目か: いいえ
説明: 作成に成功した場合に実行される関数。引数として作成された
レコードが Lookup 型で返ります。

パラメーター名: errorCallback
型: Function
必須項目か: いいえ
説明: 作成に失敗した場合に実行される関数

フォームスクリプトの開発と設定

1. ブラウザで Dynamics CRM Online に接続します。

2. 設定 | カスタマイズ | システムのカスタマイズより Web リソース
を選択して、新規ボタンをクリックします。

image

3. 名前と表示名に「quickcreate.htm」と入力し、「種類」より
「Web ページ (HTML)」 を選び、「テキストエディター」をクリック
します。

image

4. ソースタブをクリックして、以下の HTML 貼り付けます。OK を
クリックして画面を閉じます。

<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
function quickcreate(){
  // 元の取引先企業レコードを指定
  var thisAccount = {
  entityType: "account",
  id: parent.Xrm.Page.data.entity.getId()
  };

  // 成功時のコールバック関数を作成
  var callback = function (lookup) {
    // 結果を「説明」に表示
    parent.Xrm.Page.getAttribute("description").setValue("新しい取引先担当者: " + lookup.savedEntityReference.name + "、id: " + lookup.savedEntityReference.id + " が作成されました!");
  }

  // 失敗時のコールバック関数を作成
  var failurecallback = function (lookup) {
    alert("操作に失敗しました。");
  }

  // 初期値をセット
  var setName = { lastname: "サンプル", firstname: "取引先担当者"};

  // 簡易作成フォームを開く
  parent.Xrm.Utility.openQuickCreate("contact", thisAccount, setName).then(callback, failurecallback);
}
</script>
<input onclick="quickcreate()" type="button" value="取引先担当者を作成">
</body>
</html>

5. 「上書き保存」をクリックしてから、「公開」をクリックします。
公開が終わったら画面を閉じます。

6. エンティティ | 取引先企業 | フォームを選択します。「取引先企業」
フォームを開きます。

image

7. 挿入タブより Web リソースをクリックします。

image

8. 作成した Web リソースを指定して、以下のように設定します。

image

image

9. 「OK」をクリックします。フォームを保存してから公開します。

動作確認

1. 任意の取引先企業レコードを開きます。

2. 配置した「取引先担当者を作成」ボタンをクリックします。

image

3. 簡易作成が表示され、既定値や関連のマッピングが正しく設定
されている事を確認します。

image

4. 必要に応じて名前を編集して、「上書き保存」をクリックします。
結果が説明欄に表示されていることを確認します。

image

レコードを別のウィンドウで開く

Dynamics CRM 2013 よりレコードはインラインで開きますが、UI
からは必要に応じて別画面にすることができました。今回の機能
拡張により、openEntityForm 関数に windowOptions パラメーター
がサポートされ、true を渡すことで別ウィンドウでレコードを
開くことができます。

Xrm.Utility.openEntityForm(name,id,parameters,windowOptions)

日付列で時刻が出ているかを確認する

日付型フィールドにおいて、時間コントロールの表示有無を
スクリプトで確認出来るようになりました。

var showsTime = Xrm.Page.getControl(arg).getShowTime();

スクリプトを実行しているデバイスの種類を取得する

デバイスの種類によって処理を変更したい場合、Xrm.Page.context
オブジェクトの getFormFactor 関数を利用出来ます。

返り値は以下の通りです。

0: 不明なデバイス
1: デスクトップ
2: タブレット
3: 携帯端末

まとめ

今回のリリースではクライアントサイドスクリプトも強化
されました。特に簡易フォームの利用など新機能の不随する
機能のサポートは便利だと思います。

是非おためしください!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 1

$
0
0

みなさん、こんにちは。

今回から Dynamics CRM Online 2015 Update 1 で提供される新機能より
Web API 開発者プレビューを紹介します。

概要

Microsoft Dynamics CRM は開発者向けに SOAP と REST エンドポイント
を提供してきましたが、今回新しく Web API エンドポイントが追加され
ました。現時点ではプレビューという位置づけです。

Web API エンドポイントは OData 4 をサポートしており、これまでの
REST エンドポイントがサポートしていた CRUD (Create/Read/Update/
Delete) に加え多くの Action と Function (組織サービスの実行等) が
提供されます。これは将来的に SOAP エンドポイントを置き換える事が
出来るもので、より Web 開発の標準に沿ったものです。

機能は既定で無効となっています。

機能の有効化

Web API 開発者プレビューは以下の手順で有効にできます。

1. ブラウザで Dynamics CRM Online に接続します。

2. 設定 | 管理 | システムの設定よりプレビュータブを開きます。

image

3. ライセンス状況を読んでいただき、「ライセンス状況を読んで同意する」
にチェックをします。プレビュー機能のため、開発およびテスト環境で
お試しいただくことを推奨します。

image

4. 「Dynamics CRM Web API のプレビューを有効にする」項目で左側の
チェックを入れます。※「無効化する」というラベルは「はい」の誤訳です。
次期パッチにて修正予定です。

image

5. 「OK」をクリックします。

データの取得

今回はまず簡単にデータの取得を試してみます。Web API エンドポイント
は以下の URL からアクセスできます。こちらの URL は開発者リソースには
出ていません。
※ 以下 URL の crm7 は環境によって変わります。

https://<組織名>.crm7.dynamics.com/api/data

1. 一旦 Dynamics CRM Online にブラウザで接続してから、以下の URL
にアクセスします。

https://<組織名>.crm7.dynamics.com/api/data/accounts

2. Internet Explorer の場合は結果をダウンロードできます。Chrome を
お使いの場合は、結果が画面に表示されます。

image

3. 特定のレコードを取得する場合は以下の URL を利用します。レコードの
Guid をそのまま渡すだけです。

https://<組織名>.crm7.dynamics.com/api/data/accounts(21e50903-900f-e511-80db-c4346bc42d18)

4. 多くの OData クエリをサポートしているため、以下のように Select や
Filter が利用できます。

https://<組織名>.crm7.dynamics.com/api/data/accounts?$select=name&$filter=statuscode -eq 0

認証

Web API は OAuth 2.0 認証をサポートします。開発するプログラムから
アクセスする場合は、Azure AD を利用した OAuth 2.0 認証が必須です。

まとめ

Web API は今後の開発の基本となる重要な機能です。まだプレビュー
ですが、是非お試しください。尚、設置型 の Dynamics CRM 2015 に
対するプレビュー機能提供の予定は現時点ではありません。

次回から具体的な利用方法を紹介していきます。お楽しみに!

参考URL
https://msdn.microsoft.com/en-us/dynamics/crm/webapipreview.aspx

- 中村 憲一郎


Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 2

$
0
0

みなさん、こんにちは。

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
Web API 開発者プレビューについて紹介します。連載記事になるため
第 1 回からご覧ください。

Web API 開発者プレビュー その 1

多くの開発者は、ただ説明されるよりハンズオンを希望されるため、
この連載でもハンズオン形式で機能を紹介していきます。

OData エンドポイントを利用する場合、T4 テンプレートなどを利用
したクライアントを作成する方法が一般的ですが、実際の通信で何が
起きているかを理解するため、まずは HttpClient を使います。

※T4 テンプレートを利用した機能の利用は、連載の後半で紹介します。

事前準備

Azure AD への登録

OAuth 2.0 を利用するには、Dynamics CRM Online の認証を行う Azure
AD 上で開発するアプリケーションを事前に登録する必要があります。
以下の手順で登録を行います。

1. ブラウザで http://manage.windowsazure.comへ接続します。

2. Azure サブスクリプションがあるアカウントでログインします。
利用する Dynamics CRM Online とは異なるアカウントでも結構です。

3. 左のメニュー一覧より Active Directory を選択します。

image

4. 利用する Dynamics CRM Online と異なるテナントにログインした場合で
ディレクトリの一覧に Dynamics CRM Online のディレクトリが表示されて
いない場合、以下手順で追加します。Dynamics CRM Online のディレクトリ
が表示されている場合はステップ 10 に進んでください。

5. 新規ボタンをクリックして、APP SERVICE | ACTIVE DIRECTORY より
ディレクトリを選択します。

image

6. カスタム作成をクリックして「既存ディレクトリの使用」を選択します。

image

7. 「サインアウトする準備ができました。」をチェックしてチェック
マークをクリックします。自動的にサインアウトされた後、サインインを
求められるので Dynamics CRM Online の管理者でログインします。

8. ユーザーをディレクトリの管理者にするか聞かれるので承認します。

9. 再度自動的にサインアウトされるので元のアカウントでログインします。

10. ディレクトリ一覧より Dynamics CRM Online のテナントを選択します。

11. アプリケーションタブをクリックして、画面下にある「追加」ボタンを
クリックします。

image

12. 「組織で開発中のアプリケーションを追加」を選択します。

image

13. 名前に「CRM Web API Test」と入力し、「ネイティブクライアント
アプリケーション」を選択して次へ進みます。

image

14. リダイレクト URI に 「http://localhost/webapipreview」と
入力して、完了します。

image

15. アプリケーション登録後、「構成」タブを選択します。

image

16. 表示されている「クライアント ID」を控えます。

17. 画面下部にある「アプリケーションの追加」をクリックします。

image

18. アプリケーションの一覧より Dynamics CRM Online を選択して
画面右下の完了マークをクリックします。

image

19. デリゲートされたアクセスより「Access CRM Online as organization
users」にチェックを入れます。

image

20. 画面下部の「保存」ボタンをクリックしたら登録完了です。

コンソールアプリケーションの作成

まず検証で利用するコンソールアプリケーションを準備します。

1. Visual Studio を起動します。新しいプロジェクトより Visual C# の
コンソールアプリケーションを作成します。ここでは名前を
CrmWebAPITest としました。

image

2. Web API は OAuth 2.0 での認証/認可が必要なため、NuGet より
ADAL (Active Directory Authentication Library) を追加します。
プロジェクトを右クリックして、「NuGet パッケージの管理」を
クリックします。

3. 左ペインで「オンライン」を選択して、画面右上の検索窓に
「ADAL」と入力して検索します。

4. 検索結果より 「Active Directory Authentication Library」を選択
してインストールします。

image

5. 同様に 「JSON.NET」もインストールしてください。

image

6. プロジェクト内の「参照設定」を右クリックして「参照の追加」を
クリックします。アセンブリより以下のアセンブリを追加します。

System.Net
System.Net.Http

また以下の using ステートメントを追加します。

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System.Net.Http;
using System.Net.Http.Headers;

7. クラスレベルのフィールドとして Main メソッドの前に以下を
追加します。 clientId は先ほど取得したものを入力してください。
※serverUrl をご利用の環境にアドレスに変更してください。

#region クラスレベルメンバー

static string serverUrl = "https://<CRM組織名>.crm7.dynamics.com";
static string authUrl = "https://login.windows.net/common";
static string clientId = "取得したIDを入力";
static string redirectUri = "http://localhost/webapipreview";

#endregion クラスレベルメンバー

8. Main メソッドに認証および実行部分とエ��ーハンドリングのコードを
追加します。

try
{
    AuthenticationContext authContext = new AuthenticationContext(authUrl);
    AuthenticationResult result = authContext.AcquireToken(serverUrl, clientId, new Uri(redirectUri));

    Program app = new Program();
    Task.WaitAll(Task.Run(async () => await app.Run(result.AccessToken)));
}          
catch (System.Exception ex)
{
    Console.WriteLine("エラーが発生しました。");
    Console.WriteLine(ex.Message);
}
finally
{
    Console.WriteLine("Press <Enter> to exit.");
    Console.ReadLine();
}       

9. プログラムを実行するメソッドを追加します。

public async Task Run(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    }
}

10. ソリューションをビルドします。参考までのプログラムの
全体を以下に示します。

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace CrmWebAPITest
{
    class Program
    {
        #region クラスレベルメンバー
       
        static string serverUrl = .crm7.dynamics.com">https://<CRM組織名>.crm7.dynamics.com;
        static string authUrl = "https://login.windows.net/common";
        static string clientId = "取得したIDを入力";
        static string redirectUri = "http://localhost/webapipreview";

        #endregion クラスレベルメンバー

        public async Task Run(string accessToken)
        {
            // HttpClient の作成
            using (HttpClient httpClient = new HttpClient())
            {
                // Web API アドレスの作成
                string serviceUrl = serverUrl + "/api/data/";
                // ヘッダーの設定
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            }
        }

        static void Main(string[] args)
        {
            try
            {
                AuthenticationContext authContext = new AuthenticationContext(authUrl);
                AuthenticationResult result = authContext.AcquireToken(serverUrl, clientId, new Uri(redirectUri));

                Program app = new Program();
                Task.WaitAll(Task.Run(async () => await app.Run(result.AccessToken)));
            }          
            catch (System.Exception ex)
            {
                Console.WriteLine("エラーが発生しました。");
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Console.WriteLine("Press <Enter> to exit.");
                Console.ReadLine();
            }       
        }
    }
}

動作確認

ここまで準備したものが期待通り動作するか確認します。

1. 上記ステップ 9 で追加したメソッド内にブレークポイントを
設定します。F5 キーを押下してプログラムを実行します。

image

2. サインイン画面が出るので、Dynamics CRM Online 組織に
アクセスできる権限でサインインします。

image

3. ブレークポイントがヒットしたら、AccessToken が取得できて
いるか確認します。

image

まとめ

少し手順が長かったですが、今回の作業で事前準備が整いました。
次回以降で実際に色々な機能を試していきますので、お楽しみに!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 3

$
0
0

みなさん、こんにちは。

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
Web API 開発者プレビューについて紹介します。連載記事になるため
第 1 回からご覧ください。

Web API 開発者プレビュー その 1
Web API 開発者プレビュー その 2

今回はレコード操作の基本となる作成、読み取り、更新、削除に
ついて説明します。

クラスの準備

この記事では、取引先企業レコードの操作を行いますので、まずは
取引先企業を表すクラスを追加します。

1. 前回作成した Visual Studio プロジェクトを開きます。

2. プロジェクトを右クリック | 追加 | 新しい項目よりクラスを
追加します。名前は Account.cs としました。

image

3. 追加した Account.cs ファイルを開き、以下コードに書き換えます。

using System;

namespace CrmWebAPITest
{
    public class Account
    {
        public Guid accountid{ get; set; }
        public string name { get; set; }
        public string telephone1 { get; set; }
    }
}

レコードの作成

まずレコードの作成部分を実装してみましょう。

プログラムの実装

1. Program.cs ファイルに以下の using ステートメントを追加します。

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

2. 次に取引先企業のオブジェクトを作成します。前回追加した Run
メソッドに以下のコードを追加します。

// 取引先企業オブジェクトの作成
Account account = new Account();
account.name = "Demo Account";
account.telephone1 = "555-5555";

3. 次に送信するリクエストを作成します。以下コードを追加します。
送信先アドレスは Web API エンドポイントに accounts を指定します。
また取引先企業オブジェクトは JSON にシリアライズします。

// 送信リクエストの作成
HttpRequestMessage createReq = new HttpRequestMessage(HttpMethod.Post, serviceUrl + "accounts");
createReq.Content = new StringContent(JsonConvert.SerializeObject(
    account, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));

createReq.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

4. 最後にリクエストを送信して、結果を画面に表示します。

// リクエストの送信と結果表示
HttpResponseMessage result = await httpClient.SendAsync(createReq);
Console.WriteLine(result.Headers.Location);

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

image

3. 作成したレコードのアドレスが表示されます。

image

レコードの読み取り

次に作成したレコードを読み取ります。

プログラムの実装

1. 上記で追加したコードに続いて、以下のコードを追加します。
今回は作成時に取得したアドレスではなく、名前の検索を使い
レコードを取得してみます。

HttpResponseMessage retrieveRes = await httpClient.GetAsync(serviceUrl + "accounts?$filter=name eq 'Demo Account'");

2. 取得した結果を Account オブジェクトにデシリアライズします。

// 取得結果をデシリアライズ
JToken jToken = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result)["value"];
Account forUpdate = JsonConvert.DeserializeObject<Account>(jToken[0].ToString());

Console.WriteLine("取引先企業 ID:{0} を取得しました。.", forUpdate.accountid);

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. 結果が表示されます。

image

レコードの更新

次に読み取ったレコードを更新します。

プログラムの実装

1. 上記で追加したコードに続いて、以下のコードを追加して
取得したオブジェクトの名前プロパティを更新します。

forUpdate.name = forUpdate.name + " 更新しました!";

2. 以下のコードでレコード更新用の要求を作成します。
HttpMethod は PATCH を利用します。アドレスは
レコードを特定するため /api/data/accounts(guid) となります。

// 更新要求の作成
HttpRequestMessage updateReq = new HttpRequestMessage(new HttpMethod("PATCH"), serviceUrl + "accounts(" + forUpdate.accountid + ")");
updateReq.Content = new StringContent(JsonConvert.SerializeObject(forUpdate, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));

updateReq.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

3. 作成した要求を送信します。

await httpClient.SendAsync(updateReq);

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. 処理が完了したら、実際のレコードをブラウザで確認します。

image

レコードの削除

最後にレコードを削除します。

1. 削除要求を作成します。以下のコードを追加します。
HttpMethod は DELETE を利用します。アドレスは
レコードを特定するため /api/data/accounts(guid) となります。

// 削除要求の作成
HttpRequestMessage deleteReq = new HttpRequestMessage(HttpMethod.Delete, serviceUrl + "accounts(" + forUpdate.accountid + ")");

2. 以下のコードを追加して、要求を送信します。

await httpClient.SendAsync(deleteReq);

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. 処理が完了したら、レコードが削除されたことをブラウザ
から確認します。

全てのコードを以下に示します。

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace CrmWebAPITest
{
    class Program
    {
        #region クラスレベルメンバー

        static string serverUrl = "https://<CRM組織名>.crm7.dynamics.com";
        static string authUrl = "https://login.windows.net/common";
        static string clientId = "取得したIDを入力";
        static string redirectUri = "http://localhost/webapipreview";

        #endregion クラスレベルメンバー

        public async Task Run(string accessToken)
        {
            // HttpClient の作成
            using (HttpClient httpClient = new HttpClient())
            {
                // Web API アドレスの作成
                string serviceUrl = serverUrl + "/api/data/";
                // ヘッダーの設定
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

                // 取引先企業オブジェクトの作成
                Account account = new Account();
                account.name = "Demo Account";
                account.telephone1 = "555-5555";

                // 送信リクエストの作成
                HttpRequestMessage createReq = new HttpRequestMessage(HttpMethod.Post, serviceUrl + "accounts");
                createReq.Content = new StringContent(JsonConvert.SerializeObject(
                    account, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));

                createReq.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

                // リクエストの送信と結果表示
                HttpResponseMessage result = await httpClient.SendAsync(createReq);
                Console.WriteLine(result.Headers.Location);
           
                // 作成したレコードの取得
                HttpResponseMessage retrieveRes = await httpClient.GetAsync(serviceUrl + "accounts?$filter=name eq 'Demo Account'");

                // 取得結果をデシリアライズ
                JToken jToken = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result)["value"];

                Account forUpdate = JsonConvert.DeserializeObject<Account>(jToken[0].ToString());

                Console.WriteLine("取引先企業 ID:{0} を取得しました。.", forUpdate.accountid);

                forUpdate.name = forUpdate.name + " 更新しました!";


                // 更新要求の作成
                HttpRequestMessage updateReq = new HttpRequestMessage(new HttpMethod("PATCH"), serviceUrl + "accounts(" + forUpdate.accountid + ")");

                updateReq.Content = new StringContent(JsonConvert.SerializeObject(forUpdate, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));

                updateReq.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

                await httpClient.SendAsync(updateReq);

                Console.WriteLine("取引先企業を更新しました!");

                // 削除要求の作成
                HttpRequestMessage deleteReq = new HttpRequestMessage(HttpMethod.Delete, serviceUrl + "accounts(" + forUpdate.accountid + ")");

                await httpClient.SendAsync(deleteReq);

                Console.WriteLine("取引先企業を削除しました!");

             }
        }

        static void Main(string[] args)
        {
            try
            {
                AuthenticationContext authContext = new AuthenticationContext(authUrl);
                AuthenticationResult result = authContext.AcquireToken(serverUrl, clientId, new Uri(redirectUri));

                Program app = new Program();
                Task.WaitAll(Task.Run(async () => await app.Run(result.AccessToken)));
            }          
            catch (System.Exception ex)
            {
                Console.WriteLine("エラーが発生しました。");
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Console.WriteLine("Press <Enter> to exit.");
                Console.ReadLine();
            }       
        }
    }
}

まとめ

まずは基本となるレコードの作成、読み取り、更新、削除を
紹介しました。利用するアドレスや HttpMethod、および
JSON のシリアライズ/デシリアライズを再度ご確認ください。

次回は Upsert 機能の利用を紹介します。お楽しみに!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 4

$
0
0

みなさん、こんにちは。

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
Web API 開発者プレビューについて紹介します。連載記事になるため
第 1 回からご覧ください。

Web API 開発者プレビュー その 1
Web API 開発者プレビュー その 2
Web API 開発者プレビュー その 3

Web API では Upsert もサポートしています。Upsert の SDK サポート
は以下の記事をご覧ください。
Dynamics CRM Online 2015 Update 1 SDK 新機能: Upsert

Upsert で新規レコードの作成

まず Upsert を利用したレコードの作成を検証します。

プログラムの実装

1 前回利用した Visual Studio ソリューションを開き、Program.cs
ファイルを開きます。新しく以下のメソッドを追加します。

public async Task RunUpsert(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    }
}

2. Main メソッドの以下のコードを書き換えて、新しい
メソッドを呼ぶように変更します。

元)  
Task.WaitAll(Task.Run(async () => await app.Run(result.AccessToken)));

変更後)
Task.WaitAll(Task.Run(async () => await app.RunUpsert(result.AccessToken)));

3. Upsert を利用するにはレコードの GUID を指定する必要があります。
まずはまだ存在しないレコードを指定して、レコードが作成されるか
確認しましょう。以下のコードを新しく追加メソッド内に追加します。

// レコードの GUID
Guid newGuid = Guid.NewGuid();

// 取引先企業オブジェクトの作成
Account account = new Account();
account.name = "Upsert デモ";
account.telephone1 = "555-5555";

4. 送信するリクエストを作成します。以下コードを追加します。
HttpMethod には PATCH を利用します。

// 送信リクエストの作成
HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), serviceUrl+ "accounts(" + newGuid + ")");
request.Content = new StringContent(JsonConvert.SerializeObject(account, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));
               
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

5. 最後にリクエストを送信します。

// リクエストの送信
await httpClient.SendAsync(request);

6. 以下のコードを追加して、一旦画面を止めるようにします。

Console.WriteLine("レコードを作成しました。");
Console.Read();

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

image

3. レコード作成のメッセージが表示されたら、レコードを作成されたか
ブラウザで確認します。

image

image

Upsert で既存レコードの更新

次に Upsert を利用したレコードの更新を検証します。

プログラムの実装

1 上記に続いて以下のコードを追加します。まずは取引先企業の
オブジェクトを作ります。Guid は作成で利用したものと同じ
ID を指定します。

// 取引先企業オブジェクトの作成
Account account2 = new Account();
account2.name = "Upsert デモ 更新しました";
account2.telephone1 = "555-5555";
account2.accountid = newGuid;

2. 次に送信リクエストを作成します。基本的には上記で作成
したものと同じです。

// 送信リクエストの作成
HttpRequestMessage request2 = new HttpRequestMessage(new HttpMethod("PATCH"), serviceUrl + "accounts(" + newGuid + ")");
request2.Content = new StringContent(JsonConvert.SerializeObject(account2, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));

request2.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

3. 最後にリクエストを送信します。

// リクエストの送信
await httpClient.SendAsync(request2);

4. レコードを更新したメッセージを表示します。

Console.WriteLine("レコードを更新しました。");

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. レコードが作成された時点で一旦プログラムが停止します。ブラウザで
レコードをが追加されたことを確認します。

※ 1 行目は先ほど作成したレコードです。

image

4. プログラムに戻って、画面で Enter キーを押下します。

5. 以下のメッセージが出たタイミングでブラウザでレコードを更新された
ことを確認します。

image

image

最後に今回追加したメソッドを以下に示します。

public async Task RunUpsert(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        // レコードの GUID
        Guid newGuid = Guid.NewGuid();

        // 取引先企業オブジェクトの作成
        Account account = new Account();
        account.name = "Upsert デモ";
        account.telephone1 = "555-5555";

        // 送信リクエストの作成
        HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("PATCH"), serviceUrl + "accounts(" + newGuid + ")");
        request.Content = new StringContent(JsonConvert.SerializeObject(account, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));

        request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

        // リクエストの送信
        await httpClient.SendAsync(request);

        Console.WriteLine("レコードを作成しました。");
        Console.Read();

        // 取引先企業オブジェクトの作成
        Account account2 = new Account();
        account2.name = "Upsert デモ 更新";
        account2.telephone1 = "555-5555";
        account2.accountid = newGuid;

        // 送信リクエストの作成
        HttpRequestMessage request2 = new HttpRequestMessage(new HttpMethod("PATCH"), serviceUrl + "accounts(" + newGuid + ")");
        request2.Content = new StringContent(JsonConvert.SerializeObject(account2, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));

        request2.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

        // リクエストの送信
        await httpClient.SendAsync(request2);

        Console.WriteLine("レコードを更新しました。");
    }
}

まとめ

Web API でも SDK 同様 Upsert が利用できるのは便利です。
是非お試しください!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 5

$
0
0

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
Web API 開発者プレビューについて紹介します。連載記事になるため
第 1 回からご覧ください。

Web API 開発者プレビュー その 1
Web API 開発者プレビュー その 2
Web API 開発者プレビュー その 3
Web API 開発者プレビュー その 4

Web API ではオプティミスティック同時実行制御もサポートしています。
オプティミスティック同時実行制御の SDK サポートは以下の記事を
ご覧ください。
Dynamics CRM Online 2015 Update 1 SDK 新機能: オプティミスティック同時実行制御

レコード Version の取得

まず取引先企業を 1 件作成してから、レコードの Version 情報を取得します。

プログラムの実装

1 前回利用した Visual Studio ソリューションを開き、Program.cs
ファイルを開きます。新しく以下のメソッドを追加します。

public async Task RunOptimisticConcurrency(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    }
}

2. Main メソッドの以下のコードを書き換えて、新しい
メソッドを呼ぶように変更します。

元)  
Task.WaitAll(Task.Run(async () => await app.RunUpsert(result.AccessToken)));

変更後)
Task.WaitAll(Task.Run(async () => await app.RunOptimisticConcurrency(result.AccessToken)));

3. 新しく追加した RunOptimisticConcurrency メソッド内に
以下のコードを追加して、取引先企業を 1 件作成します。

// 取引先企業オブジェクトの作成
Account account = new Account();
account.name = "同時実行制御デモ";
account.telephone1 = "555-5555";

// 送信リクエストの作成
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, serviceUrl + "accounts");
request.Content = new StringContent(JsonConvert.SerializeObject(account, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));

request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

// リクエストの送信
var result =await httpClient.SendAsync(request); 

4. 次に作成したレコードを取得して、バージョン番号を
表示します。以下のコードを追加します。

// 作成したレコードの取得
var retrieveRes = await httpClient.GetAsync(result.Headers.Location);

JToken jToken = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result);
account = JsonConvert.DeserializeObject<Account>(jToken.ToString());

string version = jToken["@odata.etag"].ToString();

// バージョンの表示
Console.WriteLine("レコードのバージョンは {0} です。", version );
Console.Read();

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

image

3. レコードのバージョン情報が表示されることを確認します。

image

バージョンを指定したレコードの取得

一度レコードを取得した後、他のユーザーがそのレコードを更新
していないか確認する場面があると思います。その方法として、
バージョン番号が異なる場合のみレコードを取得できます。

プログラムの実装

1 先ほど取得したバージョン番号を指定したレコード取得を
行います。以下のコードを追加します。ポイントは Header
に If-None-Match とバージョン番号を追加することです。

// レコードのバージョンが異なる場合のみレコードを取得
HttpRequestMessage retrieveReq = new HttpRequestMessage(HttpMethod.Get, result.Headers.Location);
retrieveReq.Headers.Add("If-None-Match", version);

2. リクエストの送信と結果を表示します。

// レコードの取得
try
{
    retrieveRes = await httpClient.SendAsync(retrieveReq);

    jToken = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result);
    account = JsonConvert.DeserializeObject<Account>(jToken.ToString());
                   
    string newVersion = jToken["@odata.etag"].ToString();

    // バージョンの表示
    Console.WriteLine("レコードのバージョンは {0} です。", newVersion);
}
catch(Exception ex)
{
    Console.WriteLine("レコードはまだ更新されていません");
}

Console.Read();

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. レコードのバージョン情報が表示されることを確認します。

image

4. Enter キーを押下してプログラムを進めます。以下の画面
が出ることを確認します。

image

5. Enter キーを押下してプログラムを終了した後、再度 F5
キーを押下してプログラムを実行します。

6. 認証ダイアログが表示されたらログインします。

7. レコードのバージョン情報が表示されることを確認します。

image 

8. 再度レコードを取得する前に、ブラウザからレコードを更新します。
ブラウザで Dynamics CRM Online に接続してレコードの一部を変更
します。その後プログラムに戻り、Enter キーを押下します。
レコードのバージョンが変わるため、以下のように表示されます。

image

バージョンを指定したレコードの更新

最後にレコードの更新を同じようにやってみます。ここまで既に
いくつかレコードを作成しているため、このタイミングで一度
ブラウザで「同時実行制御デモ」と名前がついているものは削除
することをお勧めします。

1. 更新要求を作成します。今回はバージョンが変わっていない場合に
更新を行いたいので、If-Match ヘッダーを設定します。

// レコードの更新
account.name = "同時実行制御デモ 更新";

// バージョンが一致する場合にのみ更新
HttpRequestMessage updateReq = new HttpRequestMessage(new HttpMethod("PATCH"), result.Headers.Location);
updateReq.Content = new StringContent(JsonConvert.SerializeObject(account, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));
updateReq.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
updateReq.Headers.Add("If-Match", version);

2. リクエストを送信して、結果を表示します。

try
{
    HttpResponseMessage updateRes = await httpClient.SendAsync(updateReq);

    if (updateRes.IsSuccessStatusCode)
        Console.WriteLine("レコードを更新しました。", version);
    else
        Console.WriteLine("レコードが更新できませんでした。");
}
catch (Exception ex)
{

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. レコードのバージョン情報が表示されることを確認します。

image

4. Enter キーを押下します。ブラウザでレコードを更新していない
ため、以下のメッセージが表示されます。

image

5. Enter キーを押下します。レコードをが更新されたかブラウザで
確認します。

image

image

6. Enter キーを押下してプログラムを終了した後、再度 F5 キーを
押下してプログラムを実行します。

7. 認証ダイアログが表示されたらログインします。

8. レコードのバージョン情報が表示されることを確認します。

image

9. 今回はブラウザより手動でレコードを変更します。レコードを
変更した後、プログラムに戻り Enter キーを押下します。手動で
レコードを編集したため、意図したとおり更新に失敗しました。

image

最後に今回追加したメソッドを示します。

public async Task RunOptimisticConcurrency(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        // 取引先企業オブジェクトの作成
        Account account = new Account();
        account.name = "同時実行制御デモ";
        account.telephone1 = "555-5555";

        // 送信リクエストの作成
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, serviceUrl + "accounts");
        request.Content = new StringContent(JsonConvert.SerializeObject(account, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));

        request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");

        // リクエストの送信
        var result = await httpClient.SendAsync(request);

        // 作成したレコードの取得
        var retrieveRes = await httpClient.GetAsync(result.Headers.Location);

        JToken jToken = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result);
        account = JsonConvert.DeserializeObject<Account>(jToken.ToString());

        string version = jToken["@odata.etag"].ToString();

        // バージョンの表示
        Console.WriteLine("レコードのバージョンは {0} です。", version);
        Console.Read();

        // レコードのバージョンが異なる場合のみレコードを取得
        HttpRequestMessage retrieveReq = new HttpRequestMessage(HttpMethod.Get, result.Headers.Location);
        retrieveReq.Headers.Add("If-None-Match", version);

        // レコードの取得
        try
        {
            retrieveRes = await httpClient.SendAsync(retrieveReq);

            jToken = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result);
            account = JsonConvert.DeserializeObject<Account>(jToken.ToString());
                   
            string newVersion = jToken["@odata.etag"].ToString();

            // バージョンの表示
            Console.WriteLine("レコードのバージョンは {0} です。", newVersion);
        }
        catch(Exception ex)
        {
            Console.WriteLine("レコードはまだ更新されていません");
        }

        Console.Read();

        // レコードの更新
        account.name = "同時実行制御デモ 更新";

        // バージョンが一致する場合にのみ更新
        HttpRequestMessage updateReq = new HttpRequestMessage(new HttpMethod("PATCH"), result.Headers.Location);
        updateReq.Content = new StringContent(JsonConvert.SerializeObject(account, new JsonSerializerSettings() { DefaultValueHandling = DefaultValueHandling.Ignore }));
        updateReq.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
        updateReq.Headers.Add("If-Match", version);

        try
        {
            HttpResponseMessage updateRes = await httpClient.SendAsync(updateReq);

            if (updateRes.IsSuccessStatusCode)
                Console.WriteLine("レコードを更新しました。", version);
            else
                Console.WriteLine("レコードが更新できませんでした。");
        }
        catch (Exception ex)
        {
        }
    }
}

まとめ

楽観的同時実行制御は、今回紹介した読み取りと更新以外に、
削除処理も制御できますので、是非お試しください!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 6

$
0
0

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
Web API 開発者プレビューについて紹介します。連載記事になるため
第 1 回からご覧ください。

Web API 開発者プレビュー その 1
Web API 開発者プレビュー その 2
Web API 開発者プレビュー その 3
Web API 開発者プレビュー その 4
Web API 開発者プレビュー その 5

今回は Web API 固有の機能である、ビューを利用したレコードをの
取得を紹介します。

概要

ビューを利用したレコードの取得は以下の流れでレコードを取得します。

1. 特定エンティティのビュー一覧を取得します。
2. 取得したビューの情報を利用してレコードの一覧を取得します。

では早速実装していきましょう。

特定エンティティのビュー一覧取得

まず取引先企業エンティティ用のビュー一覧を取得します。

プログラムの実装

1 前回利用した Visual Studio ソリューションを開き、Program.cs
ファイルを開きます。新しく以下のメソッドを追加します。

public async Task RunViewQueries(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    }
}

2. Main メソッドの以下のコードを書き換えて、新しいメソッドを
呼ぶように変更します。

元)  
Task.WaitAll(Task.Run(async () => await app.RunOptimisticConcurrency(result.AccessToken)));

変更後)
Task.WaitAll(Task.Run(async () => await app.RunViewQueries(result.AccessToken)));

3. 新しく追加した RunViewQueries メソッド内に以下のコードを追加
して、取引先企業用のビュー一覧を取得します。

// 取引先企業ビューの一覧取得
HttpResponseMessage retrieveRes = await httpClient.GetAsync(serviceUrl + "accounts/mscrm.GetSavedQueries");
JToken results = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result)["value"];

// ビュー名の漂位j
foreach (JToken result in results)
{
    Console.WriteLine("ビュー名: {0}", result["name"]);

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

image

3. ビューの一覧が表示されることを確認します。

image

4. Enter キーを押下してプログラムを終了します。

ビューを利用したレコードを一覧の取得

次に取得したビューを利用してレコードの一覧を取得します。

プログラムの実装

1. 上記に続いて、以下のコードを追加します。api/data/accounts
アドレスに savedQuery=<savedQueryId> を渡すことで、該当の
ビュー定義を利用したレコードを取得出来ます。

// 取引先企業レコードの取得
retrieveRes = await httpClient.GetAsync(serviceUrl + "accounts?savedQuery=" + results[0]["savedqueryid"]);
JToken accounts = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result)["value"];

2. 取得した結果を表示します。以下のコードを追加します。

// 取引先企業名の表示
foreach (JToken account in accounts)
{
    Console.WriteLine("取引先企業名: {0}", account["name"]);
}

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. ビューの一覧と 1 つめのビュー定義を利用して取得された
取引先企業一覧が表示されることを確認します。

image

個人ビューの利用

上記の例ではシステムビューを取得して利用しましたが、個人ビューを
利用したい場合は GetSavedQueries を GetUserQueries に、savedQuery を
userQuery に書き換えることで対応できます。

今回追加したメソッドを以下に示します。

public async Task RunViewQueries(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        // 取引先企業ビューの一覧取得
        HttpResponseMessage retrieveRes = await httpClient.GetAsync(serviceUrl + "accounts/mscrm.GetSavedQueries");
        JToken results = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result)["value"];

        // ビュー名の漂位j
        foreach (JToken result in results)
        {
            Console.WriteLine("ビュー名: {0}", result["name"]);
        }

        // 取引先企業レコードの取得
        retrieveRes = await httpClient.GetAsync(serviceUrl + "accounts?savedQuery=" + results[0]["savedqueryid"]);
        JToken accounts = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result)["value"];

        // 取引先企業名の表示
        foreach (JToken account in accounts)
        {
            Console.WriteLine("取引先企業名: {0}", account["name"]);
        }   
    }
}

まとめ

今回は Web API 固有の機能としてエンティティビューを利用したレコード
取得を紹介しました。クエリを別途作らなくても、保存されているビューを
使用してクエリ出来る点が便利だと思います。

是非お試しください!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 7

$
0
0

みなさん、こんにちは。

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
Web API 開発者プレビューについて紹介します。連載記事になるため
第 1 回からご覧ください。

Web API 開発者プレビュー その 1
Web API 開発者プレビュー その 2
Web API 開発者プレビュー その 3
Web API 開発者プレビュー その 4
Web API 開発者プレビュー その 5
Web API 開発者プレビュー その 6

今回は Web API を利用した Action と Function の機能を紹介します。

概要

Web API と REST エンドポイントの最大の違いは Action と Function
をサポートしていることです。これによりレコードの単純な作成、
読み取り、更新、削除だけでなく各種組織サービスも実行できます。

今回のバージョンではまだ全て組織サービスがサポートされては
いませんが、以下にいくつか紹介します。

Action の利用

普段よく使われる組織メッセージとして WhoAmI 要求を試します。

プログラムの実装

1 前回利用した Visual Studio ソリューションを開き、Program.cs
ファイルを開きます。新しく以下のメソッドを追加します。

public async Task RunActions(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    }
}

2. Main メソッドの以下のコードを書き換えて、新しいメソッドを
呼ぶように変更します。

元)  
Task.WaitAll(Task.Run(async () => await app.RunViewQueries(result.AccessToken)));

変更後)
Task.WaitAll(Task.Run(async () => await app.RunActions(result.AccessToken)));

3. 新しく追加した RunActions メソッド内に以下のコードを追加
して、WhoAmI を実行します。

// WhoAmI Action アドレスの作成と実行
HttpResponseMessage whoAmIRes = await httpClient.GetAsync(serviceUrl + "WhoAmI");

4. 以下のコードを追加して結果を表示します。

// 結果の表示
JToken jToken = JObject.Parse(whoAmIRes.Content.ReadAsStringAsync().Result);

Console.WriteLine("UserId: {0}", jToken["UserId"]);
Console.WriteLine("BusinessUnitId: {0}", jToken["BusinessUnitId"]);
Console.WriteLine("OrganizationId: {0}", jToken["OrganizationId"]);

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

image

3. WhoAmI の結果が表示されることを確認します。

image

Function の利用

次に Function として、上記で取得した UserId をそのまま利用できる
RetrieveUserPrivileges を試します。

プログラムの実装

1. 上記に続いて、以下のコードを追加します。まず UserId を変数に
取得します。

// ユーザーID の取得
string userId = jToken["UserId"].ToString();

2. 次に Function を実行する要求を実行します。

// Function の実行
HttpResponseMessage retrieveUserPrivilegesRes = await httpClient.GetAsync(serviceUrl + "RetrieveUserPrivileges(UserId=" + userId + ")");


3. 最後の結果を表示するコードを追加します。

// 結果の表示
JToken privileges = JObject.Parse(retrieveUserPrivilegesRes.Content.ReadAsStringAsync().Result)["value"];

foreach (JToken privilege in privileges)
{
    Console.WriteLine("レベル: {0}, PrivilegeId: {1}", privilege["Depth"], privilege["PrivilegeId"]);
}

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. RetrieveUserPrivileges の結果が表示されることを確認します。

image

以下に今回追加したメソッドを示します。

public async Task RunActions(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        // WhoAmI Action アドレスの作成と実行
        HttpResponseMessage whoAmIRes = await httpClient.GetAsync(serviceUrl + "WhoAmI");

        // 結果の表示
        JToken jToken = JObject.Parse(whoAmIRes.Content.ReadAsStringAsync().Result);

        Console.WriteLine("UserId: {0}", jToken["UserId"]);
        Console.WriteLine("BusinessUnitId: {0}", jToken["BusinessUnitId"]);
        Console.WriteLine("OrganizationId: {0}", jToken["OrganizationId"]);

        // ユーザーID の取得
        string userId = jToken["UserId"].ToString();

        // Function の実行
        HttpResponseMessage retrieveUserPrivilegesRes = await httpClient.GetAsync(serviceUrl + "RetrieveUserPrivileges(UserId=" + userId + ")");

        // 結果の表示
        JToken privileges = JObject.Parse(retrieveUserPrivilegesRes.Content.ReadAsStringAsync().Result)["value"];

        foreach (JToken privilege in privileges)
        {
            Console.WriteLine("レベル: {0}, PrivilegeId: {1}", privilege["Depth"], privilege["PrivilegeId"]);
        } 
    }
}

まとめ

Web API が Action と Function をサポートすることで、開発に
必要なすべての操作を行うことが出来るようになります。まだ
プレビューですが、基本的なコンセプトは変わりませんので、
是非お試しください!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 8

$
0
0

みなさん、こんにちは。

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
Web API 開発者プレビューについて紹介します。連載記事になるため
第 1 回からご覧ください。

Web API 開発者プレビュー その 1
Web API 開発者プレビュー その 2
Web API 開発者プレビュー その 3
Web API 開発者プレビュー その 4
Web API 開発者プレビュー その 5
Web API 開発者プレビュー その 6
Web API 開発者プレビュー その 7

今回は Web API を利用した FormattedValue の取得を紹介します。

概要

Dynamics CRM はユーザーにレコードを返す際、FormattedValue と
いうユーザーの設定によってフォーマットされた値が一部の型で
返ります。Web API を利用した場合もこの FormattedValue を取得
出来るようになっています。

事前準備

今回はステータス型、金額型と日付型で検証を行います。事前に複数の
取引先企業レコードの利用限度額列に値を入れておいてください。

プログラムの実装

1 前回利用した Visual Studio ソリューションを開き、Program.cs
ファイルを開きます。新しく以下のメソッドを追加します。

public async Task RunFormattedValue(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    }
}

2. Main メソッドの以下のコードを書き換えて、新しいメソッドを
呼ぶように変更します。

元)  
Task.WaitAll(Task.Run(async () => await app.RunActions(result.AccessToken)));

変更後)
Task.WaitAll(Task.Run(async () => await app.RunFormattedValue(result.AccessToken)));

3. 新しく追加した RunFormattedValue メソッド内に以下のコードを追加
して、取引先企業の取得を実行します。ヘッダーとして include-anntation
を指定する点がポイントです。

// 取引先企業の取得
HttpRequestMessage retrieveReq = new HttpRequestMessage(HttpMethod.Get, serviceUrl + "accounts?$select=name,statecode,statuscode,creditlimit,createdon");
retrieveReq.Headers.Add("Prefer", "odata.include-annotations=\"*\"");

4. 要求を実行して結果を表示します。以下のコードを追加します。

// 要求の送信
HttpResponseMessage retrieveRes = await httpClient.SendAsync(retrieveReq);

// 結果の表示
JToken records = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result)["value"];

foreach (JToken record in records)
{
    JObject fields = JsonConvert.DeserializeObject(record.ToString()) as JObject;

    foreach(var field in fields)
    {
        Console.WriteLine(field);
    }
}

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

image

3. FormattedValue が表示されることを確認します。
列名に @mscrm.formattedvalue とついているものが
該当します。

image

以下に今回追加したメソッドを示します。

public async Task RunFormattedValue(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
               
        // 取引先企業の取得
        HttpRequestMessage retrieveReq = new HttpRequestMessage(HttpMethod.Get, serviceUrl + "accounts?$select=name,statecode,statuscode,creditlimit,createdon");
        retrieveReq.Headers.Add("Prefer", "odata.include-annotations=\"*\"");
               
        // 要求の送信
        HttpResponseMessage retrieveRes = await httpClient.SendAsync(retrieveReq);

        // 結果の表示
        JToken records = JObject.Parse(retrieveRes.Content.ReadAsStringAsync().Result)["value"];

        foreach (JToken record in records)
        {
            JObject fields = JsonConvert.DeserializeObject(record.ToString()) as JObject;

            foreach(var field in fields)
            {
                Console.WriteLine(field);
            }
        } 
    }
}

まとめ

FormattedValue はアプリケーションなどでユーザーに値を
表示する際に必要です。Web API はこのようにユーザーが
利用するアプリケーションも想定していますので、是非
開発に取り入れてみてください!

次回で HttpClient を利用した Web API の利用シリーズは
最終回です。最後はサポートするクエリを紹介します。

- 中村 憲一郎


Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 9

$
0
0

みなさん、こんにちは。

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
Web API 開発者プレビューについて紹介します。連載記事になるため
第 1 回からご覧ください。

Web API 開発者プレビュー その 1
Web API 開発者プレビュー その 2
Web API 開発者プレビュー その 3
Web API 開発者プレビュー その 4
Web API 開発者プレビュー その 5
Web API 開発者プレビュー その 6
Web API 開発者プレビュー その 7
Web API 開発者プレビュー その 8

今回は Web API でサポートするクエリを紹介します。

概要

Web API 開発者プレビューはこれまでに REST でサポートしたクエリ
以外に、以下のクエリをサポートします。

- $ref
- $count
- Not
- $value

早速順番に見ていきましょう。

$ref クエリ

$ref クエリを使うと、レコードの値ではなくレコードが取得できる
URI を取得できます。今回は取引先企業に紐づく取引先担当者の
レコード URI を取得してみます。

事前準備

事前に「Microsoft」という取引先企業レコードと、そのレコードに
関連する取引先担当者レコードを数件作成してください。

image

プログラムの実装

1. 前回利用した Visual Studio ソリューションを開き、Program.cs
ファイルを開きます。新しく以下のメソッドを追加します。

public async Task RunQueries(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    }
}

2. Main メソッドの以下のコードを書き換えて、新しいメソッドを
呼ぶように変更します。

元)  
Task.WaitAll(Task.Run(async () => await app.RunFormattedValue(result.AccessToken)));

変更後)
Task.WaitAll(Task.Run(async () => await app.RunQueries(result.AccessToken)));

3. 新しく追加した RunQueries メソッド内に以下のコードを追加して、
取引先企業の取得を実行します。

// 取引先企業の取得
HttpResponseMessage accountRes = await httpClient.GetAsync(serviceUrl + "accounts?$filter=startswith(name,'microsoft')");
JToken record = JObject.Parse(accountRes.Content.ReadAsStringAsync().Result)["value"][0];

4. 取得した取引先企業に紐づく取引先担当者レコードの URI を取得
して、表示します。以下のコードを追加します。

// $ref を利用した関連する取引先担当者の取得
HttpResponseMessage contactsRes = await httpClient.GetAsync(serviceUrl + "accounts(" + record["accountid"] + ")/contact_customer_accounts/$ref");

// 結果の表示
JToken contacts = JObject.Parse(contactsRes.Content.ReadAsStringAsync().Result)["value"];

foreach (JToken contact in contacts)
{
    Console.WriteLine("取引先担当者の URI: {0}", contact["@odata.id"]);
}

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

image

3. 以下のように取引先担当者の URI が表示されることを
確認します。

image

$count クエリ

$countクエリを使うと、レコードの件数を確認できます。

プログラムの実装

上記で追加したメソッドに以下のコードを追加して、取引先企業の
件数を取得します。※取得できる数は 5,000 件が上限です。

// $count を利用したデータの取得
HttpResponseMessage countRes = await httpClient.GetAsync(serviceUrl + "accounts?$count=true");
// 結果の表示
Console.WriteLine("取引先企業の数: {0}", JObject.Parse(countRes.Content.ReadAsStringAsync().Result)["@odata.count"]);

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. 結果を確認します。

image

Not オペレーター

Not オペレーターを使うと、指定した条件と逆の結果を得られます。

プログラムの実装

上記で追加したメソッドに以下コードを追加して、名前が Microsoft
で始まらない取引先企業の件数を取得します。

// Not オペレーターを利用した取引先企業の検索
HttpResponseMessage notRes = await httpClient.GetAsync(serviceUrl + "accounts?$count=true&$filter=not(startswith(name, 'microsoft'))");
// 結果の表示
Console.WriteLine("Microsoft で始まらない取引先企業の件数: {0}", JObject.Parse(notRes.Content.ReadAsStringAsync().Result)["@odata.count"]);

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. 結果を確認します。

image

$value クエリ

$value クエリを使うと、JSON データではなく値を直接取得できます。

プログラムの実装

上記で追加したメソッドに以下のコードを追加して、取引先企業の
名前を値で取得します。ポイントは OData のバージョンを明記する
ことです。尚、取引先企業の ID は上記で取得したものを再利用します。

結果の表示で JSON を処理していない点を確認してください。

// OData バージョンの指定
httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
// $value を利用した取引先企業名前の取得
HttpResponseMessage varRes = await httpClient.GetAsync(serviceUrl + "accounts(" + record["accountid"] + ")/name/$value");
// 結果の表示
Console.WriteLine("取引先企業の名前: {0}", varRes.Content.ReadAsStringAsync().Result);

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. 結果を確認します。

image

今回追加したメソッドを以下に示します。

public async Task RunQueries(string accessToken)
{
    // HttpClient の作成
    using (HttpClient httpClient = new HttpClient())
    {
        // Web API アドレスの作成
        string serviceUrl = serverUrl + "/api/data/";
        // ヘッダーの設定
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        // 取引先企業の取得
        HttpResponseMessage accountRes = await httpClient.GetAsync(serviceUrl + "accounts?$filter=startswith(name,'microsoft')");
        JToken record = JObject.Parse(accountRes.Content.ReadAsStringAsync().Result)["value"][0];

        // $ref を利用した関連する取引先担当者の取得
        HttpResponseMessage contactsRes = await httpClient.GetAsync(serviceUrl + "accounts(" + record["accountid"] + ")/contact_customer_accounts/$ref");

        // 結果の表示
        JToken contacts = JObject.Parse(contactsRes.Content.ReadAsStringAsync().Result)["value"];

        foreach (JToken contact in contacts)
        {
            Console.WriteLine("取引先担当者の URI: {0}", contact["@odata.id"]);
        }

        // $count を利用したデータの取得
        HttpResponseMessage countRes = await httpClient.GetAsync(serviceUrl + "accounts?$count=true");
        // 結果の表示
        Console.WriteLine("取引先企業の数: {0}", JObject.Parse(countRes.Content.ReadAsStringAsync().Result)["@odata.count"]);

        // Not オペレーターを利用した取引先企業の検索
        HttpResponseMessage notRes = await httpClient.GetAsync(serviceUrl + "accounts?$count=true&$filter=not(startswith(name, 'microsoft'))");
        // 結果の表示
        Console.WriteLine("Microsoft で始まらない取引先企業の件数: {0}", JObject.Parse(notRes.Content.ReadAsStringAsync().Result)["@odata.count"]);

        // OData バージョンの指定
        httpClient.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
        // $value を利用した取引先企業名前の取得
        HttpResponseMessage varRes = await httpClient.GetAsync(serviceUrl + "accounts(" + record["accountid"] + ")/name/$value");
        // 結果の表示
        Console.WriteLine("取引先企業の名前: {0}", varRes.Content.ReadAsStringAsync().Result);
    }
}

まとめ

今回まで Web API プレビューの機能を HttpClient を利用して
紹介してきました。より生の HTTP リクエストに近い内容を
確認できるため参考になったのではないでしょうか。

次回は T4 テンプレートを利用した Web API の利用を紹介します。
お楽しみに!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 10

$
0
0

みなさん、こんにちは。

今回から Dynamics CRM Online 2015 Update 1 で提供される Web
API 開発者プレビューを T4 テンプレートで作成したクライアント
から利用する方法を紹介します。

Web API 開発者プレビューについての関連記事として、以下記事を
事前にご覧ください。

Web API 開発者プレビュー その 1
Web API 開発者プレビュー その 2

T4 テンプレートとは

T4 テンプレートとは Text Template Transformation Toolkit の略で
テンプレートベースでコードを自動生成できる仕組みのことです。

詳細は以下の記事をご覧ください。
https://msdn.microsoft.com/ja-jp/library/bb126445.aspx

T4 テンプレートでのクライアント作成

メタデータの取得

まずは Web API エンドポイントのメタデータを取得します。

1. ブラウザで Dynamics CRM Online に接続します。

2. 認証を行ってログインした後、以下のアドレスを入れます。

https://<CRM Online のアドレス>/api/data/$metadata

3. エンドポイントの情報が表示されたら、内容を任意の場所に
保存します。

image

Visual Studio 拡張のインストール

次に Visual Studio に拡張ツールをインストールします。

1. Visual Studio を開きます。

2. ツールメニューより拡張機能と更新プログラムをクリックします。

3. 左ペインよりオンラインを選択し、”odata v4” で検索します。
検索結果より OData v4 Client Code Generator をインストールします。

image

4. インストール後 Visual Studio を一旦再起動します。

プロジェクトの作成

最後に Visual Studio プロジェクトを作成します。

1. Visual Studio を起動して、新しいプロジェクトを作成します。

2. Visual C# | Windows デスクトップ | コンソールアプリケーション
を選択して、任意の名前を付けます。ここでは WebApiT4Client と
しました。

image

3. プロジェクトを右クリックして、追加 | 新しい項目を選択します。

4. 検索に odata と入力して、OData Client を探します。任意の名前
を付けて追加します。ここでは CrmODataClient としました。
※一部環境ではスクリプトの警告が出る事がありますが、その場合
一旦キャンセルを行ってください。

image

5. CrmOdataClient.tt ファイルが開きます。9行目にメタデータを
指定する場所があるので、ダウンロードしたメタデータファイルの
パスを指定します。

例)
public const string MetadataDocumentUri = @"C:\$metadata.xml";

6. 変更を保存すると自動的にクライアントが生成されます。

image

まとめ

今回は T4 テンプレートを使ったクライアントの作成を紹介しました。
これは OData サービスを利用する場合に共通したものです。次回は
作成したクライアントを使ってプログラムを作成していきます。

お楽しみに!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 11

$
0
0

みなさん、こんにちは。

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
Web API 開発者プレビューを T4 テンプレートで作成したクライアント
で利用する方法について紹介します。連載記事になるため以下の記事を
事前にご覧ください。

Web API 開発者プレビュー その 1
Web API 開発者プレビュー その 2
Web API 開発者プレビュー その 10

今回は前回作成した OData クライアントを利用したプログラムを
作成していきます。

OData クライアントの利用

プロジェクトの作成と準備

まずプロジェクトを準備します。

1. Visual Studio を起動して、新しいプロジェクトを作成します。

2. Visual C# | Windows デスクトップ | コンソールアプリケーション
を選択して、任意の名前を付けます。ここでは WebApiCrmClient と
しました。

image

3. プロジェクトを右クリック | NuGet パッケージの管理を選択します。

4. 左ペインでオンラインを選択して、”odata” で検索します。

5. 検索結果より ”OData Client for .NET” を選択してインストールします。

image

6. 同様に JSON.Net と Active Directory Authentication Library を追加します。

7. Program.cs ファイルを開き、以下の using ステートメントを追加します。

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using WebApiT4Client;

8.  クラスレベルのフィールドとして Main メソッドの前に以下を追加します。
clientId はこちらの記事で取得したものを入力してください。
※serverUrl をご利用の環境にアドレスに変更してください。

#region クラスレベルメンバー

static string serverUrl = "https://<CRM組織名>.crm7.dynamics.com";
static string authUrl = "https://login.windows.net/common";
static string clientId = "取得したIDを入力";
static string redirectUri = "http://localhost/webapipreview";

#endregion クラスレベルメンバー

9. Main メソッドに認証および実行部分とエラーハンドリングのコードを
追加します。

try
{
    AuthenticationContext authContext = new AuthenticationContext(authUrl);
    AuthenticationResult result = authContext.AcquireToken(serverUrl, clientId, new Uri(redirectUri));

    Program app = new Program();
    app.Run(result.AccessToken);
}          
catch (System.Exception ex)
{
    Console.WriteLine("エラーが発生しました。");
    Console.WriteLine(ex.Message);
}
finally
{
    Console.WriteLine("Press <Enter> to exit.");
    Console.ReadLine();

10. 最後に Run メソッドを追加します。

public void Run(string accessToken)
{
    // クライアントの作成
    CrmODataClient client = new CrmODataClient(new Uri(serverUrl + "/api/data/"));
    client.SendingRequest2 += (s, e) => { e.RequestMessage.SetHeader("Authorization", "Bearer " + accessToken); };

}

T4 テンプレートで作成したクライアントの追加

1. プロジェクトを右クリックして、追加 | 既存の項目を選択します。

2. 前回作成した CrmODataClient.cs ファイルを追加します。

image

3. 追加した CrmODataClient.cs を開きます。

4.  18 行目と 24 行目の System を CrmODataClient に変更します。

image

5. ソリューションを一旦ビルドします。

プログラムの実装

まず今回は取引先企業の取得を試します。

1. 上記追加した Run メソッドに以下のコードを追加します。
名前に「サンプル」を含むレコードを取得します。

// 取引先企業の取得
foreach (Account account in client.Accounts.Where(x => x.Name.Contains("サンプル")))
{
    Console.WriteLine("取引先企業名: {0}", account.Name);
}

2. 次に以下のコードを追加します。クエリを外だしにした
形です。

// クエリの作成
var query = from a in client.Accounts
            where a.Name.Contains("サンプル")
            select a;

// クエリの実行
foreach(var account in query)
{
    Console.WriteLine("取引先企業名: {0}", account.Name);
}

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

image

3. 取引先企業の一覧が表示されることを確認します。

image

以下に Program.cs のコードを示します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using WebApiT4Client;

namespace WebApiCrmClient
{
    class Program
    {
        #region クラスレベルメンバー

         static string serverUrl = "https://<CRM組織名>.crm7.dynamics.com";
        static string authUrl = "https://login.windows.net/common";
        static string clientId = "取得したIDを入力";
        static string redirectUri = "http://localhost/webapipreview";

         #endregion クラスレベルメンバー

        public void Run(string accessToken)
        {
            // クライアントの作成
            CrmODataClient client = new CrmODataClient(new Uri(serverUrl + "/api/data/"));
            client.SendingRequest2 += (s, e) => { e.RequestMessage.SetHeader("Authorization", "Bearer " + accessToken); };


            // 取引先企業の取得
            foreach (Account account in client.Accounts.Where(x => x.Name.Contains("サンプル")))
            {
                Console.WriteLine("取引先企業名: {0}", account.Name);
            }
           
            // クエリの作成
            var query = from a in client.Accounts
                        where a.Name.Contains("サンプル")
                        select a;

            // クエリの実行
            foreach(var account in query)
            {
                Console.WriteLine("取引先企業名: {0}", account.Name);
            }
        }

        static void Main(string[] args)
        {
            try
            {
                AuthenticationContext authContext = new AuthenticationContext(authUrl);
                AuthenticationResult result = authContext.AcquireToken(serverUrl, clientId, new Uri(redirectUri));

                Program app = new Program();
                //Task.WaitAll(Task.Run(async () => await app.Run(result.AccessToken)));
                app.Run(result.AccessToken);
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("エラーが発生しました。");
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Console.WriteLine("Press <Enter> to exit.");
                Console.ReadLine();
            }    
        }
    }
}

まとめ

HttpClient を利用した場合とは随分違う事が分かると思います。
次回はレコードの作成、読み取り、変更、削除を紹介します。
お楽しみに!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 新機能: Web API 開発者プレビュー その 12

$
0
0

みなさん、こんにちは。

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
Web API 開発者プレビューを T4 テンプレートで作成したクライアント
で利用する方法について紹介します。連載記事になるため以下の記事を
事前にご覧ください。

Web API 開発者プレビュー その 1
Web API 開発者プレビュー その 2
Web API 開発者プレビュー その 10
Web API 開発者プレビュー その 11

今回は T4 テンプレートで作成したクライアントを利用したレコードの
作成、更新、削除を紹介します。

レコードの作成

1. 前回作成した Visual Studio ソリューションを開き、Program.cs
ファイルを開きます。新しく以下のメソッドを追加します。

public void CRUDRun(string accessToken)
{
    // クライアントの作成
    CrmODataClient client = new CrmODataClient(new Uri(serverUrl + "/api/data/"));
    client.SendingRequest2 += (s, e) => { e.RequestMessage.SetHeader("Authorization", "Bearer " + accessToken); };
}

2. 以下の using ステートメントを追加します。

using Microsoft.OData.Client;

3. Main メソッドの以下のコードを書き換えて、新しいメソッドを
呼ぶように変更します。

元)  
app.Run(result.AccessToken);

変更後)
app.CRUDRun(result.AccessToken);

4. 新しく追加した CRUDRunメソッド内に以下のコードを追加します。

// 取引先企業のコレクションを作成
DataServiceCollection<Account> accounts = new DataServiceCollection<Account>(client);
// 取引先企業レコードをインスタンス化
Account account = new Account();
// コレクションに追加
accounts.Add(account);
// 値を指定
account.Accountid =  Guid.NewGuid();
account.Name = "サンプル取引先企業";
account.Accountnumber = "SampleAccountNumber";

5. 最後に変更を保存してレコードを作成します。この際、指定した
値以外は送信しないよう、SaveChangesOption を指定します。

client.SaveChanges(SaveChangesOptions.PostOnlySetProperties);
Console.WriteLine("レコードを作成しました。");

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

image

3. 処理が完了したらブラウザでレコードが作成されたか確認します。

image

image

4. 作成したレコードは一旦削除しておきます。

レコードの更新

次に追加したレコードを更新します。

1. CRUDRun メソッドの最後に以下のコードを追加します。

// 取引先企業の更新
account.Name = account.Name + " 更新";

2. 変更を保存してレコードを作成します。この際、指定した
値以外は送信しないよう、SaveChangesOption を指定します。

client.SaveChanges(SaveChangesOptions.PostOnlySetProperties);
Console.WriteLine("レコードを更新しました。");

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. 結果を確認します。

image

image

4. 作成したレコードは一旦削除しておきます。

レコードの削除

最後にレコードを削除します。CRUDRun メソッドの最後に以下の
コードを追加します。

// レコードをクライアントから削除
client.DeleteObject(account);
// 変更の保存
client.SaveChanges();
Console.WriteLine("レコードを削除しました。");

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. 結果を確認します。

image

以下に今回追加したメソッドを示します。

using Microsoft.OData.Client;

public void CRUDRun(string accessToken)
{
    // クライアントの作成
    CrmODataClient client = new CrmODataClient(new Uri(serverUrl + "/api/data/"));
    client.SendingRequest2 += (s, e) => { e.RequestMessage.SetHeader("Authorization", "Bearer " + accessToken); };

    // 取引先企業のコレクションを作成
    DataServiceCollection<Account> accounts = new DataServiceCollection<Account>(client);
    // 取引先企業レコードをインスタンス化
    Account account = new Account();
    // コレクションに追加
    accounts.Add(account);
    // 値を指定
    account.Accountid = Guid.NewGuid();
    account.Name = "サンプル取引先企業";
    account.Accountnumber = "SampleAccountNumber";

    client.SaveChanges(SaveChangesOptions.PostOnlySetProperties);
    Console.WriteLine("レコードを作成しました。");
           
    // 取引先企業の更新
    account.Name = account.Name + " 更新";
    client.SaveChanges(SaveChangesOptions.PostOnlySetProperties);
    Console.WriteLine("レコードを更新しました。");

    // レコードをクライアントから削除
    client.DeleteObject(account);
    // 変更の保存
    client.SaveChanges();
    Console.WriteLine("レコードを削除しました。");
}

まとめ

レコードの作成、更新、削除は Dynamics CRM に依存した形ではなく
通常の OData Client をまったく同じ方法で使用できます。次回は
Action の実行を紹介します。お楽しみに!

- 中村 憲一郎

Dynamics CRM Online 2015 Update 1 新���能: Web API 開発者プレビュー その 13

$
0
0

みなさん、こんにちは。

前回に引き続き Dynamics CRM Online 2015 Update 1 で提供される
Web API 開発者プレビューを T4 テンプレートで作成したクライアント
で利用する方法について紹介します。連載記事になるため以下の記事を
事前にご覧ください。

Web API 開発者プレビュー その 1
Web API 開発者プレビュー その 2
Web API 開発者プレビュー その 10
Web API 開発者プレビュー その 11
Web API 開発者プレビュー その 12

今回は T4 テンプレートで作成したクライアントを利用した Action の
実行を紹介します。Action の詳細は以下記事をご覧ください。

Web API 開発者プレビュー その 7

Action の利用

普段よく使われる組織メッセージとして WhoAmI 要求を試します。

プログラムの実装

1. 前回作成した Visual Studio ソリューションを開き、Program.cs
ファイルを開きます。新しく以下のメソッドを追加します。

public void RunActions(string accessToken)
{
    // クライアントの作成
    CrmODataClient client = new CrmODataClient(new Uri(serverUrl + "/api/data/"));
    client.SendingRequest2 += (s, e) => { e.RequestMessage.SetHeader("Authorization", "Bearer " + accessToken); };
}

2. 以下の using ステートメントが追加されていることを確認します。

using Microsoft.OData.Client;

3. Main メソッドの以下のコードを書き換えて、新しいメソッドを
呼ぶように変更します。

元)  
app.CRUDRun(result.AccessToken);

変更後)
app.RunActions(result.AccessToken);

4. 追加した RunActions メソッドに以下のコードを追加します。
WhoAmI Action を実行します。

// WhoAmI の実行
WhoAmIResponse whoAmIRes = client.WhoAmI().GetValue();

5. 最後に結果を表示します。以下のコードを追加します。上記で
作成したリクエストに対して GetVaue() を実行しています。

// 結果の表示
Console.WriteLine("UserId: {0}", whoAmIRes.UserId);
Console.WriteLine("OrganizationId: {0}", whoAmIRes.OrganizationId);
Console.WriteLine("BusinessUnitId: {0}", whoAmIRes.BusinessUnitId);

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

image

3. WhoAmI の結果が表示されることを確認します。

image

Function の利用

次に Function として、上記で取得した UserId をそのまま利用できる
RetrieveUserPrivileges を試します。

プログラムの実装

1. 上記に続いて、以下のコードを RunActions メソッドに追加します。
上記で取得した UserId を使って RetrieveUserPrivilege を実行します。

// ユーザー権限の取得
var rolePrivileges = client.RetrieveUserPrivileges(whoAmIRes.UserId).Execute();

2. 結果を表示するコードを追加します。

// 結果の表示
foreach (var rolePrivilege in rolePrivileges)
{               
    Console.WriteLine("レベル: {0}, PrivilegeId: {1}", rolePrivilege.Depth, rolePrivilege.PrivilegeId);
}

動作確認

1. F5 キーを押下してプログラムを実行します。

2. 認証ダイアログが表示されたらログインします。

3. RetrieveUserPrivileges の結果が表示されることを確認します。

image

以下に今回追加したメソッドを示します。

public void RunActions(string accessToken)
{
    // クライアントの作成
    CrmODataClient client = new CrmODataClient(new Uri(serverUrl + "/api/data/"));
    client.SendingRequest2 += (s, e) => { e.RequestMessage.SetHeader("Authorization", "Bearer " + accessToken); };

    // WhoAmI の実行
    WhoAmIResponse whoAmIRes = client.WhoAmI().GetValue();

    // 結果の表示
    Console.WriteLine("UserId: {0}", whoAmIRes.UserId);
    Console.WriteLine("OrganizationId: {0}", whoAmIRes.OrganizationId);
    Console.WriteLine("BusinessUnitId: {0}", whoAmIRes.BusinessUnitId);

    // ユーザー権限の取得
    var rolePrivileges = client.RetrieveUserPrivileges(whoAmIRes.UserId).Execute();
           
    // 結果の表示
    foreach (var rolePrivilege in rolePrivileges)
    {               
        Console.WriteLine("レベル: {0}, PrivilegeId: {1}", rolePrivilege.Depth, rolePrivilege.PrivilegeId);
    }
}

まとめ

組織サービスを利用できるのは Web API のメリット
ですが、クライアントを利用することでより容易に
コーディングが行えます。次回はトランザクション処理
を紹介します。お楽しみに!

- 中村 憲一郎

Viewing all 589 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>