1

我正在探索ChannelFactory,在这样做的同时我做了以下事情:

名为“Common”的程序集中的服务合同:

namespace Common
{
    using System.ServiceModel;

    [ServiceContract(Name = "ITestService", Namespace = "http://test/")]
    public interface ITestService
    {
        [OperationContract(Name = "SayHello")]
        string SayHello(string request);
    }
}

托管在名为“WcfServiceApp”的 Web 应用程序下的服务:

请注意,我创建了另一个服务接口(合同)来创建服务。但合约的名称和命名空间与“Common”程序集中定义的合约相同。

namespace WcfServiceApp
{
     [ServiceContract(Name = "ITestService", Namespace = "http://test/")]
    public interface ITestServiceWithDiffDotNetName
    {
         [OperationContract(Name = "SayHello")]
         string SayHelloAgain(string name);
    }

    // This service implements new service contract.
    public class TestService : ITestServiceWithDiffDotNetName
    {
        public string SayHelloAgain(string request)
        {
            return "hello " + request;
        }
    }

    // This service implements common service contract
    public class TestService2 : Common.ITestService
    {
        public string SayHello(string request)
        {
            return "hello " + request;
        }
    }    
}

有两个“.svc”文件(TestService.svc 和 TestService2.svc),每个文件都用于上面创建的服务。Web.config有以下内容:

<system.serviceModel>
    <services>
      <service name ="WcfServiceApp.TestService" >
        <endpoint binding="basicHttpBinding" contract="WcfServiceApp.ITestServiceWithDiffDotNetName"></endpoint>
      </service>

      <service name ="WcfServiceApp.TestService2" >
        <endpoint binding="basicHttpBinding" contract="Common.ITestService"></endpoint>
      </service>
    </services>

    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

调用这两个服务的客户端:

请注意,客户端正在使用ChannelFactory“Common”库中定义的服务合同。

ChannelFactory<ITestService> commonServiceChannel = new ChannelFactory<ITestService>(new BasicHttpBinding(), "http://localhost/WcfServiceApp/TestService.svc");
            var proxy =  commonServiceChannel.CreateChannel();
            var response = proxy.SayHello("Mike"); // response = "Hello"


            ChannelFactory<ITestService> commonServiceChannel2 = new ChannelFactory<ITestService>(new BasicHttpBinding(), "http://localhost/WcfServiceApp/TestService2.svc");
            var proxy2 = commonServiceChannel2.CreateChannel();
            var response2 = proxy2.SayHello("Mike"); // response2 = "Hello Mike"

问题:

我观察到第一个服务(使用一些不同的服务合同创建)接收null参数,而在第二个服务(使用用于创建的服务合同创建)中收到的参数ChannelFactory是预期的“Mike”。

在 Fiddler 中,我可以正确看到该请求参数。

为什么会这样?

如果所有 XML 名称和命名空间都相同(尽管 .NET 接口的名称不同),服务调用是否应该不会成功,因为底层 SOAP 消息会相同

如果我的客户的应用程序想用 Java 创建服务并且我的应用程序应该调用它,我担心会发生什么?

4

2 回答 2

1

试试这个,从您的服务的每个版本中获取 WSDL 文档。比较 WSDL 文档(.NET 4.5 支持开箱即用的单个文件 WSDL 文档)以查看 WCF 在每个服务的肥皂消息中期望什么。很可能默认 XML 命名空间是从某个地方的 .NET(不同)命名空间中获取的,因此“相同”的服务合同实际上是不同的。WCF 在命名 XML 命名空间方面为您做了很多工作,您可能需要在整个服务、操作和数据协定中手动覆盖这些默认值,以使两个服务支持相同的肥皂消息。

在与 Java 集成时,只要可以从 WSDL 生成 Java 客户端,服务输出就有可能不会出现任何问题。最大的例外是配置 Java 客户端的安全和身份验证方面。在使用基于 Java 的客户端时,这篇关于 Java 互操作的特定 WCF 绑定的好博文值得一看。

于 2013-06-05T12:52:38.623 回答
0

首先感谢 Sixto Saez。

我比较了这两个服务生成的 WSDL 文件(使用 svcutil.exe),发现它们并不完全相同。但是,这不是由于任何一个ServiceContractOperationContract本身的名称或命名空间有任何冲突!

这是由于OperationContracts!的定义中使用的参数名称不同造成的。

可以看到OperationContract“SayHello”有一个名为“request”的参数。另一方面,OperationContract名为“SayHelloAgain”的参数有一个名为“name”的参数。当我将参数的名称从“请求”更改为“名称”时,它在 secondOperationContract中有效!

所以结论是:

当合同(.NET 类、接口)未在客户端和服务使用的某些公共库中定义时,ChannelFactory工作。唯一的问题是这些服务合同生成的 WSDL 必须相互匹配。

于 2013-06-06T05:22:16.477 回答