在过去的几天里,我花了很多时间寻找如何将简单消息从工作流(WF4)服务器发送到客户端(在我的情况下为 WPF)的解决方案。
存在一些如何回复请求(通过回调)的示例,但我找不到任何如何异步联系客户端的示例。
我希望能够进行这样的交流:
- [上午 8:00] 客户:“您好服务器,这是我的请求。请使用此配方开始您的工作流程 'MakeCoffee'。”。
- [上午 8 点 01 分] WF-Server:“您好,客户端,我在上面。”
- [8:05 am] WF-Server:“我找不到咖啡。我会买一些。”
- [8:10 am] WF-Server:“我在烧水。”
- [上午 8 点 15 分] WF-Server:“你想要糖吗?”
- (上午 8 点 17 分)客户:“是的。”
- [上午 8 点 18 分] WF-Server:“我完成了。”
到目前为止,我找到了以下解决方案:
1. WCF - 带有回调通道的服务
这个例子看起来很酷,但我不知道如何将它与我的 Workflow-Service 一起使用——因为没有“实现服务”类。一切都是可视的,所以我不能应用“SubscribeClient”方法(或者至少我不知道在哪里放置服务实现)。
2. 带有通知事件的工作流
这个例子是一个很好的解决方案——但是(据我的理解)这不适用于单独的工作流服务器——它似乎要求工作流服务器和客户端是相同的。
3. 访问 OperationContext
此示例在客户端创建了一个 WorkflowServiceHost,但它不是很容易处理,我无法根据我的要求对其进行调整。
有谁知道如何将消息从(单独的)工作流服务器发送到客户端的方便解决方案/模式?客户端不知道服务器何时可以向他发送消息以及消息数量。
我是 WF4 的新手,非常感谢每一个提示/建议/想法。
提前致谢,
蒂莫
更新
根据莫里斯的评论,我尝试在我的客户中使用一个简单的服务,但不幸的是,我的客户没有收到并显示任何消息。
这是我的客户代码:
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 接口:
[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);
}
}
这是静态应用程序接口:
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);
}
}
}
这是 ListBoxTextWriter 类,它应该将消息添加到给定的 ListBox:
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-Server 使用这个发送活动:
<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>
我没有收到任何消息、错误或警告 - 有人可以快速检查给定的代码吗?
再次感
谢蒂莫