你能模仿WCF中的现有服务吗?

时间:2014-03-10 17:13:02

标签: c# .net web-services wcf wsdl

我们有第三方供应商服务和内部服务与之沟通。一切都与我们的内部服务完美配合,但我被要求写下我们供应商服务的后备克隆。目的是能够运行我们的克隆,换出客户端,并允许我们的内部服务继续测试克隆。

是否可以重新创建/模仿服务,以便现有客户端可以与之通信(无需修改),就好像它是原始服务一样?

到目前为止,我已经尝试了3件事,但没有一件工作。

第一种方法

创建一个简单的服务,引用第三方服务以获取对自定义类型的访问权限并模仿[operation Contract]

当我尝试与此服务通信时,我收到以下错误。

'System.ServiceModel.ActionNotSupportedException'中出现System.ServiceModel.dll类型的第一次机会异常 附加信息:由于EndpointDispatcher上的ContractFilter不匹配,无法在接收方处理带有Action''的消息。这可能是由于合同不匹配(发送方与接收方之间的操作不匹配)或发送方与接收方之间的绑定/安全性不匹配。检查发件人和收件人是否具有相同的合同和相同的约束(包括安全要求,例如邮件,传输,无)。

由于我们使用的是基本的http(无ssl),因此没有安全要求。配置文件的服务模型部分和服务行为类属性如下:

<system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="SimpleBinding" />
      </basicHttpBinding>
    </bindings>
    <services>
      <service behaviorConfiguration="cloneBehavior" name="MyClone">
        <endpoint address="" binding="basicHttpBinding" bindingConfiguration="SimpleBinding"
          contract="MyService.IMyService" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/clone/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="cloneBehavior">
          <serviceMetadata httpGetEnabled="True" httpGetUrl="http://localhost/clone/mex" />
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
</system.serviceModel>

和服务行为

[ServiceBehavior(Name = "CloneService", 
    ConfigurationName = "MyClone", 
    InstanceContextMode = InstanceContextMode.PerCall, 
    AddressFilterMode = AddressFilterMode.Any)]
public class MyService : IMyService
{

一切看起来都很好,我已经到了第一个死胡同。

第二种方法

删除我的接口/服务合约,并直接从reference.cs文件中生成的接口继承。

当我运行此服务时,我收到以下错误

System.InvalidOperationException:操作myMethodA和myMethodB具有相同的操作()。每个操作都必须具有唯一的操作值。

在System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ActionDemuxer.Add(String action,DispatchOperationRuntime operation)     在System.ServiceModel.Dispatcher.ImmutableDispatchRuntime..ctor(DispatchRuntime dispatch)     在System.ServiceModel.Dispatcher.DispatchRuntime.GetRuntimeCore()     在System.ServiceModel.Dispatcher.ChannelDispatcher.OnOpened()     在System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan超时)     在System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan超时)     在System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan超时)     在Microsoft.Tools.SvcHost.ServiceHostHelper.OpenService(ServiceInfo info)

看一下这个方法的生成界面,它们都用以下属性修饰:

[System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="*")]

我对msdn的理解是,WCF默认添加模式<namespace>/<service>/<operation>[Response]的唯一操作。

如果我尝试将操作设置为*,那么我可以点击服务(正如预期的那样使用catch all / unmatched message handler),但我无法点击特定的方法。

尽管如此,手动使所有操作都是唯一的(并符合上述模式),会出现此错误:

客户端配置中的合同“IMyService”与服务合同中的名称不匹配,或者此合同中没有有效的方法。 ...

我已经在服务合同中明确定义了方法,并且已经到了第二个死胡同。

第3种方法

使用wsdl.exe工具从wsdl生成服务。我按照this SO post中的说明生成了一个接口并从中继承。

我还尝试使用clientWsdl.wsdl /l:CS /server命令并按照this帖子中的说明生成服务本身。

在整理生成的代码并运行它之后,我又回到了原来的错误:

System.ServiceModel.dll中出现'System.ServiceModel.ActionNotSupportedException'类型的第一次机会异常 附加信息:由于EndpointDispatcher上的ContractFilter不匹配,无法在接收方处理带有Action''的消息。这可能是由于合同不匹配(发送方与接收方之间的操作不匹配)或发送方与接收方之间的绑定/安全性不匹配。检查发件人和收件人是否具有相同的合同和相同的约束(包括安全要求,例如邮件,传输,无)。

在每次尝试时,我都仔细检查了所有配置设置,并在每个阶段更新了合同。

在这个阶段,我想知道它是否可能。

2 个答案:

答案 0 :(得分:1)

您是否能够使用WCF模仿服务?我发现自己处于类似的情况,我的任务是编写一些集成测试,我们的方法调用供应商的Web服务。我宁愿利用Moq编写适当的单元测试,但我受到以下约束:1)不允许更改我正在测试的方法的签名,2)除了Web服务本身之外什么都不知道,除了我们发送给服务的内容及其预期的响应。

@ jparram的建议是我的下一个方法。

注意:我本来希望将此作为评论发布,因为我没有回答你的问题。

答案 1 :(得分:0)

如果我理解你的场景,我会创建包装服务来决定要调用哪个服务。这听起来就像你想要用Scenario 1做的那样。所以,你的客户端总是会调用你的包装服务,你的包装服务会将输入映射到第三方服务或备份服务所需的输入。

您收到的错误听起来像代理客户端的生成中的问题,其中“Action”未被映射。查看已知工作配置中生成的代理代码,并将其与方案1中的代码进行比较。

修改的 比较生成的服务代理客户端和“真实”服务。关于行动 =“”的投诉可能是由于:

[System.ServiceModel.OperationContractAttribute(Action="", ReplyAction="")]

在您的客户端上没有映射到相应的操作。