[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 メソッドの返り値(文字列型)を受け取って何らかのカスタム処理を行うことが可能になります。
さんのコメント: さんのコメント: