现在的位置: 首页 > 综合 > 正文

WCF Service Contract之MEPs

2013年08月02日 ⁄ 综合 ⁄ 共 6529字 ⁄ 字号 评论关闭

 

 

WCF Service ContractMEPs

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,并且不能有outref的参数。当WCF服务的客户端不应该等到对应的操作的完成并且也不需要处理SOAP错误时,采用这种单向模式。(这个方法的返回值是void并不代表该方法会返回消息给调用者。)

 

Duplex模式是客户端和服务之间可以相互独立的使用One WayRequest-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.

 

以下是来自微软的例子中的一个Duplex方式的程序,经过稍加改动(红色的方法是增加的代码):

//服务器端代码
=================================================================
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;
        }

    }

}

 

//Web.Config的内容
===============================================================================================================
<?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.                 

抱歉!评论已关闭.