[Dynamics CRM 2011]Azure対応(Azure Aware) カスタムプラグインを作成する その1 の続きです。カスタムプラグインの作成と、サービスエンドポイントの準備を行いました。今回は、Azure AppFabric サービスバスリスナーアプリケーションを作成します。

  • Visual Studio 2010 Professional
  • Windows Azure AppFabric SDK V 1.5

今回作成する例は次のサンプルを参考にしています。ってかその簡易実装みたいな感じです。

サンプル: 二方向リスナー
http://msdn.microsoft.com/ja-jp/library/gg334438.aspx

1. リスナーコンソールアプリケーションの作成

Visual Studio を起動し、コンソールアプリケーションプロジェクトを作成します。下図では、 AppFabricServiceBusIntegrationSample01という名前で作成しています。

ソリューションエクスプローラ上のプロジェクトを右クリック→プロパティをクリックします。プロジェクトのプロパティ画面が表示されます。下図のよう対象のフレームワークを .NET Framework 4 します。

次に、必要なアセンブリの参照を設定します。ファイルの参照として、下図のように microsoft.crm.sdk.proxy.dll と microsoft.xrm.sdk.dll を追加します。dllはCRM SDK の bin フォルダに格納されています。

同様に、 Microsoft.ServiceBus.dll の参照も追加します。既定のインストールでは、 C:\Program Files\Windows Azure AppFabric SDK\V1.5\Assemblies\NET4.0配下にdllが格納されています。Windows Azure AppFabric SDK がインストールされていないとアセンブリがないので注意してください。

上記に加えて、 System.ServiceModel, System.Runtime.Serialization への参照を追加します。

既定で作成される Program.cs を次のように編集します。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xrm.Sdk; using System.ServiceModel; using Microsoft.ServiceBus; using System.ServiceModel.Description;  namespace AppFabricServiceBusIntegrationSample01 {     class Program     {         /// <summary>         /// Azure サービスバスからメッセージがポストされたときにExecuteメソッドが実行される         /// </summary>         [ServiceBehavior]         private class TwoWaySampleService : ITwoWayServiceEndpointPlugin         {             /// <summary>             /// ITwoWayServiceEndpointPluginのオペレーションコントラクタ Execute は文字列を             /// プラグインに返すことができる。             /// </summary>             /// <param name="executionContext"></param>             /// <returns></returns>             public string Execute(RemoteExecutionContext executionContext)             {                 if (executionContext.MessageName.Equals("Create", StringComparison.InvariantCultureIgnoreCase))                 {                     Console.WriteLine("レコードが作成されました");                     Console.WriteLine("Entity:{0}", executionContext.PrimaryEntityName);                     Console.WriteLine("ID:{0}", executionContext.OutputParameters["id"].ToString());                      return "True";                 }                 return "False";             }          }         public static void Run()         {             ServiceBusEnvironment.SystemConnectivity.Mode = ConnectivityMode.Http;              string servicebusNamespace = "Netplanetes-Crm-Sample";             string servicePath = "Custom/Sample01";             string issuerName = "xxxxx";             string issuerSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";              // Address の作成             Uri address = ServiceBusEnvironment.CreateServiceUri(Uri.UriSchemeHttps, servicebusNamespace, servicePath);             Console.WriteLine("サービスのアドレス: " + address);              // Azureアクセスコントロールサービスでエンドポイントとのマッチングに使用される共有シークレット資格情報オブジェクトの作成             TransportClientEndpointBehavior sharedSecretServiceBusCredential = new TransportClientEndpointBehavior();             sharedSecretServiceBusCredential.TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerSecret);              // Bindingの作成             WS2007HttpRelayBinding binding = new WS2007HttpRelayBinding();             binding.Security.Mode = EndToEndSecurityMode.Transport;             // ServiceHostの作成             ServiceHost serviceHost = new ServiceHost(typeof(TwoWaySampleService));             // エンドポイントの追加             serviceHost.AddServiceEndpoint(typeof(ITwoWayServiceEndpointPlugin), binding, address);              // エンドポイント用に ServiceRegistrySettings Behaviorを作成する             IEndpointBehavior serviceRegistrySettings = new ServiceRegistrySettings(DiscoveryType.Public);             // サービスバスの資格情報をすべてのエンドポイントに追加する             foreach (ServiceEndpoint endpoint in serviceHost.Description.Endpoints)             {                 endpoint.Behaviors.Add(serviceRegistrySettings);                 endpoint.Behaviors.Add(sharedSecretServiceBusCredential);             }              // サービスホストを開く             serviceHost.Open();              Console.WriteLine("Azure からメッセージをリッスンしています");             Console.WriteLine("終了するには Enter を入力してください。");             Console.ReadLine();              // Close the service.             Console.WriteLine("サービスホストをクローズします");             serviceHost.Close();          }         static void Main(string[] args)         {             try             {                 Run();             }             catch (FaultException<ServiceEndpointFault> ex)             {                 Console.WriteLine("The application terminated with an error.");                 Console.WriteLine("Message: {0}", ex.Detail.Message);                 Console.WriteLine("Inner Fault: {0}",                     null == ex.InnerException.Message ? "Has Inner Fault" : "No Inner Fault");             }             catch (System.TimeoutException ex)             {                 Console.WriteLine("The application terminated with an error.");                 Console.WriteLine("Message: {0}", ex.Message);                 Console.WriteLine("Stack Trace: {0}", ex.StackTrace);                 Console.WriteLine("Inner Fault: {0}",                     null == ex.InnerException.Message ? "Has Inner Fault" : "No Inner Fault");             }             catch (System.Exception ex)             {                 Console.WriteLine("The application terminated with an error.");                 Console.WriteLine(ex.Message);                  // Display the details of the inner exception.                 if (ex.InnerException != null)                 {                     Console.WriteLine(ex.InnerException.Message);                      FaultException<ServiceEndpointFault> fe = ex.InnerException                         as FaultException<ServiceEndpointFault>;                     if (fe != null)                     {                         Console.WriteLine("Message: {0}", fe.Detail.Message);                         Console.WriteLine("Inner Fault: {0}",                             null == ex.InnerException.Message ? "Has Inner Fault" : "No Inner Fault");                     }                 }             }              finally             {                 Console.WriteLine("プログラムを終了します。Enterを入力してください.");                 Console.ReadLine();             }          }      } }

プロジェクトをビルドしてエラーが発生しないことを確認します。

以上で準備が完了です。

リスナーアプリケーションをデバッグ実行した後、取引先企業の作成をすると、コンソールにレコードのGUIDが表示されるようになります。

2.まとめ

説明は以上です。指摘点などがあればご連絡ください。

Azure対応のカスタムプラグイン(およびカスタムワークフローアクティビティー)を独自実装すると、Two-Way や REST 用のコントラクト(ITwoWayServiceEndpointPlugin, IWebHttpServiceEndpointPlugin) のExecute メソッドの返り値(文字列型)を受け取って何らかのカスタム処理を行うことが可能になります。