Dynamics CRM 2016 SDK 新機能: メタデータ Web API その 1: エンティティ

あけましておめでとうございます。

年末年始はいかがお過ごしだったでしょうか。私は主に Windows
Universal Application を作って遊んでおりました。

今年も Microsoft Dynamics CRM に関連する記事を公開して参り
ますので、ご愛読いただきますようお願いいたします。

さて、前回に引き続き、Dynamics CRM 2016 SDK の新機能として
正式版となった Web API について紹介します。

今回から Web API の機能よりメタデータサービスの詳細を紹介しますが
初回はまずエンティティメタデータの操作を紹介します。

概要

既存の組織サービス同様、Web API を利用してメタデータを操作する
ことが可能です。サポートされる操作は多岐に渡りますが、今回は
エンティティの操作を紹介します。

エンティティの作成

まずカスタムエンティティを作成します。

プログラムの実装

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

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

    }
}

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

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

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

3. 新しく追加した RunEntityMetadata メソッド内に以下のコードを追加して、
カスタムエンティティの情報を作成します。

// カスタムエンティティの情報を作成
string customEntityMeta = @"
{
    'SchemaName':'new_SampleEntity',
    'HasActivities':'false',
    'HasNotes':'false',
    'IsActivity':'false',
    'OwnershipType':'UserOwned',
    'DisplayCollectionName': {
        'LocalizedLabels': [{
            'Label': 'サンプルエンティティ',
            'LanguageCode': 1041
        }],
        'UserLocalizedLabel': {
            'Label': 'サンプルエンティティ',
            'LanguageCode': 1041
        }
    },
    'DisplayName': {
        'LocalizedLabels': [{
            'Label': 'サンプルエンティティ',
            'LanguageCode': 1041
        }],
        'UserLocalizedLabel': {
            'Label': 'サンプルエンティティ',
            'LanguageCode': 1041
        }    
    },    
    'PrimaryNameAttribute':'new_name',
    'Attributes':[{
        '@odata.type': '#Microsoft.Dynamics.CRM.StringAttributeMetadata',
        'AttributeType':'String',
        'IsPrimaryName':'true',
        'SchemaName':'new_name',
        'MaxLength':'100',
        'FormatName': {
            'Value': 'Text'
        },
        'RequiredLevel': {
            'Value': 'ApplicationRequired',
            'CanBeChanged': true,
            'ManagedPropertyLogicalName': 'canmodifyrequirementlevelsettings'
        },
        'DisplayName': {
            'LocalizedLabels': [{
                'Label': 'サンプルエンティティ名',
                'LanguageCode': 1041
            }],
            'UserLocalizedLabel': {
                'Label': 'サンプルエンティティ名',
                'LanguageCode': 1041
            }
        }
    }]
}";

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

// カスタムエンティティの作成
HttpResponseMessage createRes = await httpClient.PostAsync(serviceUrl + "EntityDefinitions",
    new StringContent(customEntityMeta, Encoding.UTF8, "application/json"));

動作確認

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

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

image

3. プログラム完了後、カスタムエンティティが作成されて
いることを確認します。

image

image

エンティティの取得

メタデータサービスも OData を利用したクエリが可能です。次の作業に
あたり上記で追加したカスタムエンティティの作成要求はコメントアウト
しておきます。

プログラムの実装

1. 上記のコードに続いて以下のコードを追加します。エンティティの
論理名を利用してフィルターします。

// 作成したエンティティの取得
HttpResponseMessage entityRes = await httpClient.GetAsync(serviceUrl + "EntityDefinitions?$filter=LogicalName eq 'new_sampleentity'");
JToken entity = JObject.Parse(entityRes.Content.ReadAsStringAsync().Result)["value"][0];

2. 以下のコードを追加して結果を表示します。エンティティのメタ
データは内容が多いため、今回はそのまますべて表示しました。

// 詳細を表示
Console.WriteLine(entity);

動作確認

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

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

3. エンティティの詳細が表示されます。

image

エンティティの削除

更新および削除も通常のレコード同様に行えます。ここでは削除の
方法を紹介します。

プログラムの実装

上記のコードに続いて以下のコードを追加します。レコードの ID に
相当するものとして、MetadataId があります。これを取得した内容から
取り出して、指定しています。

// 作成したエンティティの削除
HttpResponseMessage deleteRes = await httpClient.DeleteAsync(serviceUrl + "EntityDefinitions(" + entity["MetadataId"] + ")");

動作確認

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

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

3. 作成したエンティティが削除されることを確認します。

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

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

        // カスタムエンティティの情報を作成
        string customEntityMeta = @"
        {
            'SchemaName':'new_SampleEntity',
            'HasActivities':'false',
            'HasNotes':'false',
            'IsActivity':'false',
            'OwnershipType':'UserOwned',
            'DisplayCollectionName': {
                'LocalizedLabels': [{
                    'Label': 'サンプルエンティティ',
                    'LanguageCode': 1041
                }],
                'UserLocalizedLabel': {
                    'Label': 'サンプルエンティティ',
                    'LanguageCode': 1041
                }
            },
            'DisplayName': {
                'LocalizedLabels': [{
                    'Label': 'サンプルエンティティ',
                    'LanguageCode': 1041
                }],
                'UserLocalizedLabel': {
                    'Label': 'サンプルエンティティ',
                    'LanguageCode': 1041
                }    
            },    
            'PrimaryNameAttribute':'new_name',
            'Attributes':[{
                '@odata.type': '#Microsoft.Dynamics.CRM.StringAttributeMetadata',
                'AttributeType':'String',
                'IsPrimaryName':'true',
                'SchemaName':'new_name',
                'MaxLength':'100',
                'FormatName': {
                    'Value': 'Text'
                },
                'RequiredLevel': {
                    'Value': 'ApplicationRequired',
                    'CanBeChanged': true,
                    'ManagedPropertyLogicalName': 'canmodifyrequirementlevelsettings'
                },
                'DisplayName': {
                    'LocalizedLabels': [{
                        'Label': 'サンプルエンティティ名',
                        'LanguageCode': 1041
                    }],
                    'UserLocalizedLabel': {
                        'Label': 'サンプルエンティティ名',
                        'LanguageCode': 1041
                    }
                }
            }]
        }";

        // カスタムエンティティの作成
        HttpResponseMessage createRes = await httpClient.PostAsync(serviceUrl + "EntityDefinitions",
          new StringContent(customEntityMeta, Encoding.UTF8, "application/json"));

        Console.WriteLine("Press Enter to continue");
        Console.ReadLine();

        // 作成したエンティティの取得
        HttpResponseMessage entityRes = await httpClient.GetAsync(serviceUrl + "EntityDefinitions?$filter=LogicalName eq 'new_sampleentity'");
        JToken entity = JObject.Parse(entityRes.Content.ReadAsStringAsync().Result)["value"][0];

        // 詳細を表示
        Console.WriteLine(entity);

        Console.WriteLine("Press Enter to continue");
        Console.ReadLine();

        // 作成したエンティティの削除
        HttpResponseMessage deleteRes = await httpClient.DeleteAsync(serviceUrl + "EntityDefinitions(" + entity["MetadataId"] + ")");
               
    }
}

まとめ

メタデータブラウザや初期構成時のエンティティ操作などを
プログラムから行いたい場合利用できます。是非お試しください!

- 中村 憲一郎

※本情報の内容(添付文書、リンク先などを含む)は、作成日時点でのものであり、予告なく変更される場合があります