WCF Service Contract之MEPs
LazyBee
WCF支持的消息交换模式MEPs(Message Exchange Partten)为三种:请求-响应模式(Request-Replay), 单向模式(One Way),双向模式(Duplex).
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ICalculatorSession
{
[OperationContract(IsOneWay = true)]
void AddTo(double n);
[OperationContract]
double Equals();
}
以上AddTo方法就是单向模式,而Equals就是双向模式。(缺省的IsOneWay的值是false)
缺省的消息交换模式就是Request-Replay模式。
注意:如果指定的方法的消息交换模式是One Way,那么这个方法的返回值必须是void,并且不能有out和ref的参数。当WCF服务的客户端不应该等到对应的操作的完成并且也不需要处理SOAP错误时,采用这种单向模式。(这个方法的返回值是void并不代表该方法会返回消息给调用者。)
Duplex模式是客户端和服务之间可以相互独立的使用One Way和Request-Replay进行双向通讯的消息交换模式。
在使用Duplex进行消息交换的时候,并且客户端调用的是定义为Request-Reply的服务操作,而且在这个服务操作中又调用客户端的另外一个Request-Reply的一个回调方法,这时就会遇到如下错误,你可以根据提示进行修复操作。
错误:This operation would deadlock because the reply cannot be received until the current Message completes processing. If you want to allow out-of-order message processing, specify ConcurrencyMode of Reentrant(可重入的并发模式) or Multiple on ServiceBehaviorAttribute.
=================================================================
using System;
using System.ServiceModel;
namespace Microsoft.ServiceModel.Samples
{
// Define a duplex service contract.
// A duplex contract consists of two interfaces.
// The primary interface is used to send messages from the client to the service.
// The callback interface is used to send messages from the service back to the client.
// ICalculatorDuplex allows one to perform multiple operations on a running result.
// The result is sent back after each operation on the ICalculatorCallback interface.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required, CallbackContract=typeof(ICalculatorDuplexCallback))]
public interface ICalculatorDuplex
{
[OperationContract(IsOneWay = true)]
void Clear();
[OperationContract(IsOneWay = true)]
void AddTo(double n);
[OperationContract(IsOneWay = true)]
void SubtractFrom(double n);
[OperationContract(IsOneWay = true)]
void MultiplyBy(double n);
[OperationContract(IsOneWay = true)]
void DivideBy(double n);
[OperationContract]
String Request_ReplayMethodInDuplex(int i);
}
// The callback interface is used to send messages from service back to client.
// The Result operation will return the current result after each operation.
// The Equation opertion will return the complete equation after Clear() is called.
public interface ICalculatorDuplexCallback
{
[OperationContract(IsOneWay = true)]
void Result(double result);
[OperationContract(IsOneWay = true)]
void Equation(string eqn);
[OperationContract(IsOneWay=true)]
void ShowMessage(string s);
}
// Service class which implements a duplex service contract.
// Use an InstanceContextMode of PerSession to store the result
// An instance of the service will be bound to each duplex session
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class CalculatorService : ICalculatorDuplex
{
double result = 0.0D; string equation;
public CalculatorService()
{
equation = result.ToString();
}
public void Clear()
{
Callback.Equation(equation + " = " + result.ToString());
equation = result.ToString();
}
public void AddTo(double n)
{
result += n;
equation += " + " + n.ToString();
Callback.Result(result);
}
public void SubtractFrom(double n)
{
result -= n;
equation += " - " + n.ToString();
Callback.Result(result);
}
public void MultiplyBy(double n)
{
result *= n;
equation += " * " + n.ToString();
Callback.Result(result);
}
public void DivideBy(double n)
{
result /= n;
equation += " / " + n.ToString();
Callback.Result(result);
}
ICalculatorDuplexCallback Callback
{
get
{
return OperationContext.Current.GetCallbackChannel<ICalculatorDuplexCallback>();
}
}
public string Request_ReplayMethodInDuplex(int i)
{
Callback.ShowMessage("Hello World!" + i);
return "hello world " + i;
}
}
}
===============================================================================================================
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<!-- This endpoint is exposed at the base address provided by host: http://localhost/servicemodelsamples/service.svc -->
<endpoint address=""
binding="wsDualHttpBinding"
contract="Microsoft.ServiceModel.Samples.ICalculatorDuplex" />
<!-- the mex endpoint is exposed at http://localhost/servicemodelsamples/service.svc/mex -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
//Service.svc的内容
===================================================================================
<%@ServiceHost language=c# Debug="true" Service="Microsoft.ServiceModel.Samples.CalculatorService" %>
1 首先在IIS中创建一个http://localhost/servicemodelsamples的虚拟目录。
2 如果你是第一次运行WCF Service的话,需要将.svc扩展名和aspnet_isapi.dll关联,具体操作如下:
1. 打开IIS管理器.
2. 右单击 Web Sites 并且选择属性 Properties.
3. On the Home Directory tab, click 配置Configuration.
4. In the list of application mappings, verify that the .svc file is mapped to the aspnet_isapi.dll. If the file has not been mapped:
a. 单击增加按钮.
b. 在 Add/Edit Application Extension Mapping 对话框中, 单击浏览按钮
c. 找到aspnet_isapi.dll并单击Open.
d. 制定 .svc 扩展名
e.