ここ数日、私はワークフロー (WF4) サーバーからクライアント (私の場合は WPF) に単純なメッセージを送信する方法に関する解決策を見つけるために多くの時間を費やしました。
(コールバック経由で) リクエストに応答する方法の例がいくつかありますが、クライアントに非同期的に連絡する方法の例は見つかりません。
次のようなコミュニケーションができるようになりたいです。
- [8:00 am] クライアント: 「こんにちはサーバー、これは私のリクエストです。このレシピを使用してワークフロー 'MakeCoffee' を開始してください。」.
- [午前 8 時 1 分] WF-Server: 「こんにちは、クライアントです。準備中です。」
- [8:05 am] WF-Server: 「コーヒーが見つかりません。買います。」
- [午前8時10分] WF-Server: 「お湯を沸かしています。」
- [午前 8 時 15 分] WF サーバー: 「砂糖はいかがですか?」
- [午前8時17分] クライアント: 「はい。」
- [午前 8 時 18 分] WF-Server: 「完了しました。」
今まで、私はこれらの解決策を見つけました:
1. WCF - CallBack-Channel を使用したサービス
この例はかなりクールに思えますが、これを Workflow-Service で使用する方法がわかりません。「サービスを実装する」クラスがないためです。すべてが視覚的であるため、「SubscribeClient」メソッドを適用できません (または、少なくともサービス実装を配置する場所がわかりません)。
2. 通知イベントを伴うワークフロー
この例は素晴らしい解決策ですが、(私の理解では) これは別のワークフロー サーバーでは機能しません。ワークフロー サーバーとクライアントが同じである必要があるようです。
3.OperationContextへのアクセス
この例では、クライアント側で WorkflowServiceHost を作成しますが、処理が簡単ではなく、要件に合わせて調整することもできません。
(別の)ワークフローサーバーからクライアントにメッセージを送信する方法に関する便利なソリューション/パターンを知っている人はいますか? クライアントは、サーバーがいつメッセージを送信し、それが何通になるかを知りません。
私は WF4 を初めて使用するので、あらゆるヒント/アドバイス/アイデアに非常に感謝しています。
前もって感謝します、
ティモ
アップデート
Maurice からのコメントによると、クライアントで簡単なサービスを使用しようとしましたが、残念ながら、クライアントはメッセージを受信して表示しません。
これは私のクライアントコードです:
public partial class MainWindow : Window
{
private ServiceHost _serviceHost;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ApplicationInterface._app = this;
//prepare the serviceHost
string clientAddress = "http://localhost:8000/ClientService";
System.ServiceModel.Channels.Binding bBinding = new BasicHttpBinding();
_serviceHost.AddServiceEndpoint(typeof(IClientService), bBinding, clientAddress);
_serviceHost.Open();
}
public ListBox GetEventListBox()
{
return this.lstEvents;
}
}
これは私の IClientService-Interface です:
[ServiceContract]
public interface IClientService
{
[OperationContract(IsOneWay=true)]
void MeldeStatus(String statusText);
}
これは、IClientService-Interface の実装です。
public class ClientService : IClientService
{
public void MeldeStatus(string statusText)
{
ApplicationInterface.AddEvent(statusText);
}
}
これは静的 ApplicationInterface です。
public static class ApplicationInterface
{
public static MainWindow _app { get; set; }
public static void AddEvent(String eventText)
{
if (_app != null)
{
new ListBoxTextWriter(_app.GetEventListBox()).WriteLine(eventText);
}
}
}
これは、指定された ListBox にメッセージを追加する ListBoxTextWriter クラスです。
public class ListBoxTextWriter : TextWriter
{
const string textClosed = "This TextWriter must be opened before use";
private Encoding _encoding;
private bool _isOpen = false;
private ListBox _listBox;
public ListBoxTextWriter()
{
// Get the static list box
_listBox = ApplicationInterface._app.GetEventListBox();
if (_listBox != null)
_isOpen = true;
}
public ListBoxTextWriter(ListBox listBox)
{
this._listBox = listBox;
this._isOpen = true;
}
public override Encoding Encoding
{
get
{
if (_encoding == null)
{
_encoding = new UnicodeEncoding(false, false);
}
return _encoding;
}
}
public override void Close()
{
this.Dispose(true);
}
protected override void Dispose(bool disposing)
{
this._isOpen = false;
base.Dispose(disposing);
}
public override string ToString()
{
return "";
}
public override void Write(char value)
{
if (!this._isOpen)
throw new ApplicationException(textClosed); ;
this._listBox.Dispatcher.BeginInvoke
(new Action(() => this._listBox.Items.Add(value.ToString())));
}
public override void Write(string value)
{
if (!this._isOpen)
throw new ApplicationException(textClosed); ;
if (value != null)
this._listBox.Dispatcher.BeginInvoke
(new Action(() => this._listBox.Items.Add(value)));
}
public override void Write(char[] buffer, int index, int count)
{
String toAdd = "";
if (!this._isOpen)
throw new ApplicationException(textClosed); ;
if (buffer == null || index < 0 || count < 0)
throw new ArgumentOutOfRangeException("buffer");
if ((buffer.Length - index) < count)
throw new ArgumentException("The buffer is too small");
for (int i = 0; i < count; i++)
toAdd += buffer[i];
this._listBox.Dispatcher.BeginInvoke
(new Action(() => this._listBox.Items.Add(toAdd)));
}
}
私の WF サーバーは、次の Send-Activity を使用します。
<Send Action="MeldeStatus" EndpointConfigurationName="BasicHttpBinding_Client" sap:VirtualizedContainerService.HintSize="255,90" OperationName="MeldeStatus" ProtectionLevel="None" ServiceContractName="p:IClientService">
<SendParametersContent>
<p1:InArgument x:TypeArguments="x:String" x:Key="statusText">Yes, it works.</p1:InArgument>
</SendParametersContent>
</Send>
これは、WF サーバーでのエンドポイントの構成です。
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="DefaultHTTPBinding" allowCookies="true" />
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="WFServer.ReklamationErfassen">
<endpoint address="http://localhost:7812/ReklamationErfassen.xamlx"
binding="basicHttpBinding"
bindingConfiguration="DefaultHTTPBinding"
contract="IReklamationService" />
</service>
</services>
<client>
<endpoint address="http://localhost:8000/ClientService" binding="basicHttpBinding"
bindingConfiguration="DefaultHTTPBinding" contract="IClientService"
name="BasicHttpBinding_Client" />
</client>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
メッセージ、エラー、または警告が表示されません - 誰かが指定されたコードを簡単に確認できますか?
ありがとう、
ティモ