Dynamics CRM 2011 SilverCrmSoap ライブラリの紹介

みなさん、こんにちは。

今回は CodePlex で公開されている SilverCrmSoap ライブラリを紹介します。

通常 Silverlight Web リソースの開発では、今まで紹介したように REST エンドポイントを
利用しますが、REST エンドポイントでは CRUD (Create、Read、Update、Delete) 操作しか
できないため、Execute メソッドを利用した複雑な処理は、直接 SOAP エンドポイントを
利用する必要があり、その手順は MSDN 上の こちらのページ で紹介されています。

しかしこの手順は多少面倒であることは事実です。

SOAP エンドポイント VS REST エンドポイント

Silverlight Web リソースを開発する場合、どのエンドポイントを利用するか選択する
必要があります。例えば以下のような操作が必要な場合には、Execute メソッドが
必要となるため、 SOAP エンドポイントを利用します。

・ 遅延バインドを利用する必要がある場合
・ レコードの割り当て処理が必要な場合
・ メタデータに関連する処理が必要な場合

一方で REST エンドポイントを利用するメリットも多くあります。

・ 事前バインドの利用
・ LINQ サポート
・ コンパイル時のエラーチェックおよび Intellisense

詳細は Web リソースでの Web サービス データの使用 (REST および SOAP エンドポイント)
参照してください。

SilverlightCrmSoap ライブラリ

まずはライブラリを CodePlex よりダウンロードします。

1. https://silvercrmsoap.codeplex.com/ にアクセスします。

2. 画面右端にある Download のボタンをクリックして、モジュールをダウンロードします。

3. ダウンロードした圧縮ファイルより、SilverCrmSoap.dll を任意の場所に保存します。

4. Visual Studio 2010 で Silverlight アプリケーションプロジェクトを作成します。

5. 参照設定より、SilverCrmSoap.dll を指定して追加します。

image

参照の追加が完了すると、以下の名前空間が利用可能になります。

・ SilverCrmSoap.CrmSdk
・ SilverCrmSoap.FetchXml
・ SilverCrmSoap.Helpers

clip_image001[2]SilverCrmSoap.CrmSdk

SDK 「Walkthrough: Use the SOAP Endpoint for Web Resources with Silverlight」 (英語)  に
そって開発されたクラスで、SOAP エンドポイントへのアクセスを提供します。また Entity クラスを
継承した UserOwnedEntity クラスが実装されており、フィールドが変更された際に適切に処理
するようになっています。またそれ以外にも、UserOwnedEntity を継承した Annocation クラスが
実装されています。

clip_image001[3]SilverCrmSoap.FetchXml

FetchXml 名前空間では、Fetch XML のシリアライズ/デシリアライズをサポートしており、オブジェクト
として、扱うことが可能になります。よって Fetch XML の構築や、パラメーターの変更等が容易です。
QueryExpression でも同様の処理が初めから可能ですが、関連したエンティティーの列の値を返さない等、
Fetch XML をより利用したいニーズがあるため、その場合に便利です。

Fetch myFetch = new Fetch();
myFetch.Entity.Name = "account";
SilverCrmSoap.FetchXml.Attribute myattAccountId = new SilverCrmSoap.FetchXml.Attribute();
myattAccountId.Name = "accountid";
SilverCrmSoap.FetchXml.Attribute myattName = new SilverCrmSoap.FetchXml.Attribute();
myattName.Name = "name";
myFetch.Entity.Attributes.Add(myattAccountId);
myFetch.Entity.Attributes.Add(myattName);
           
string generatedFetchXml = myFetch.Serialize();

結果は以下の Fetch XML 文字列が生成されます。
<fetch>
   <entity name="account">
      <attribute name="accountid" />
      <attribute name="name" />
   </entity>
</fetch>

また Fetch XML 文字列を所得できた場合には、以下のコードでデシリアライズできます。

Fetch myFetch = Fetch.Deserialize(FetchXmlString);

SilverCrmSoap.Helpers

SilverCrmSoap.Helper 名前空間は 3 種類のヘルパークラスを含んでいます。

clip_image004

XrmHelper

XrmHelper は Xrm.Page を利用するためのヘルパークラスです。また Web リソースが
フォームまたは HTML ページ上にロードされたか、それ以外にロードされたかを判別することも
可能です。このヘルパーを利用するには、Web リソースをフォーム上に配置するか、 HTML ページ
をホストにする必要があります。

例えば以下ように利用ができます。

// サーバーの URI を取得
string serverUrl = XrmHelper.ServerUri.ToString();
// フォームまたは HTML ページ上にロードされたか確認
// True なら Xrm.Page が利用可能。
bool isOnForm = XrmHelper.OnForm;

FormHelper

FormHelper は XrmHelper を元に動作し、以下のような機能を追加します。

・ GetUserPrivilege: 特定のフィールドに対して、読み取り、書き込み、作成の権限があるか確認
・ GetEntityValue: フィールドの値を取得。 Xrm.Page.data.entity.attributes の getValue と同じ機能
・ SetEntityValue: フィールドの値を設定。 Xrm.Page.data.entity.attributes の setValue と同じ機能

例えば以下のように利用ができます。

// name フィールドの作成権限を確認
bool checkPriv = FormHelper.GetUserPrivilege("name", FormHelper.UserPrivilege.Create);
// 権限があれば初期値設定
if(checkPriv)
   FormHelper.SetEntityValue("name", "test");

SoapHelper

SoapHelper は Soap エンドポイントに対するメッセージ実行機能を提供します。またその際に
サーバーの URL を指定する必要がないため、処理を簡潔に記述できます。以下のメソッドが
利用可能です。

・ BeginAssociate
・ BeginCreate
・ BeginUpdate
・ BeginDelete
・ BeginDisassociate
・ BeginExecute
・ BeginExecuteFetch
・ BeginExecuteRetrieveAllEntities
・ BeginExecuteRetrieveEntity

例えば、既に紹介した Fetch と組み合わせて、以下のような記述が可能です。

// サービスを SoapHelper から取得
private OrganizationServiceClient _service = SoapHelper.SoapClient;

public MainPage()
{
    InitializeComponent();

    // Form または HTML 上で実行されているか確認
    bool isOnForm = XrmHelper.OnForm;

    if (isOnForm)
    {
        // アクティブな取引先企業を取得する Fetch XML
        // 今回は使用しない。
        string originalFetch = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
            <entity name='account'>
            <attribute name='name' />
            <attribute name='address1_city' />
            <attribute name='primarycontactid' />
            <attribute name='telephone1' />
            <attribute name='accountid' />
            <order attribute='name' descending='false' />
            <filter type='and'>
                <condition attribute='statecode' operator='eq' value='0' />
            </filter>
            <link-entity name='contact' from='contactid' to='primarycontactid' visible='false' link-type='outer' alias='accountprimarycontactidcontactcontactid'>
                <attribute name='emailaddress1' />
            </link-entity>
            </entity>
        </fetch>";

        // 上記の Fetch XML を Fetch.Deserialize でシリアライズ可能。
        // シリアライズ後、必要に応じて編集。
        //Fetch myFetch = Fetch.Deserialize(originalFetch);

        // 今回は新規に Fetch を作成
        Fetch myFetch = new Fetch();
        // エンティティ名を付与
        myFetch.Entity.Name = "account";
        // 取得したい列を作成
        SilverCrmSoap.FetchXml.Attribute myattAccountId = new SilverCrmSoap.FetchXml.Attribute();
        myattAccountId.Name = "accountid";
        SilverCrmSoap.FetchXml.Attribute myattName = new SilverCrmSoap.FetchXml.Attribute();
        myattName.Name = "name";
        // 列を Fetch に付与
        myFetch.Entity.Attributes.Add(myattAccountId);
        myFetch.Entity.Attributes.Add(myattName);

        // Fetch から Fetch XML 文字列を生成
        string generatedFetchXml = myFetch.Serialize();
               
        // Soap Helper を利用した BeginExecuteFetch の実行
        // BeginExecuteFetch では、最終的に BeginExecute が呼ばれる
        SoapHelper.BeginExecuteFetch(generatedFetchXml, callbackOnCompleteFetch, _service);

        // なお、BeginExecuteFetch は Fetch を引数にもできるため、Fetch XML への変換は任意
        // SoapHelper.BeginExecuteFetch(myFetch, callbackOnCompleteFetch, _service);
    }
    else
        label1.Content = "Silverlight Web リソースは HTML ページ上またはフォームにホストしてください。";      
}

private void callbackOnCompleteFetch(IAsyncResult result)
{            
    try
    {
        // BeginExecute が呼ばれているので、EndExecute で処理を完了
        OrganizationResponse response = ((IOrganizationService)result.AsyncState).EndExecute(result);
        EntityCollection results = (EntityCollection)response["EntityCollection"];

        // 結果を文字列に変換して、テキストボックスに入力
        StringBuilder sb = new StringBuilder();
        if (results.Entities.Count == 0)
        { sb.AppendLine("There are no Account records in the system."); }

        foreach (SilverCrmSoap.CrmSdk.Entity entity in results.Entities)
        {
            sb.AppendLine("Account Name = " + entity.GetAttributeValue<string>("name"));
        }
        if (results.MoreRecords)
        {
            sb.AppendLine("Only the first 10 records were returned.");
        }
        this.ReportMessage(sb.ToString());
    }
    catch
    { }
}

// 結果を表示
private void ReportMessage(string message)
{
    this.Dispatcher.BeginInvoke(() => ResultsBox.Text = message);
}

まとめ

SilverCrmSoap ライブラリを利用すれば、コードがより単純になり読みやすくなります。
またこちらのライブラリのソースを参考にして、独自のヘルパークラスを作成することも
可能ですので、Silverlight 開発を行う際には、是非参考にしてください。

情報元: SilverCrmSoap: A CRM Soap Library for CRM 2011
https://blogs.msdn.com/b/crm/archive/2011/04/26/silvercrmsoap-a-crm-soap-library-for-crm-2011.aspx

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