使用消息合同上传文件



我一直在关注各种教程,这些教程解释了如何通过WCF上传文件,当我尝试在客户端和服务器之间共享包含MessageContract的类时,我遇到了一些问题。

基本上我的问题如下:

我在单独的类库中有一个RemoteFileInfo MessageContract类:

[MessageContract]
public class RemoteFileInfo : IDisposable
{
    private System.IO.Stream fileByteStream;
    [MessageBodyMember(Order = 1)]
    public System.IO.Stream FileByteStream
    {
        set { this.fileByteStream = value; }
        get { return this.fileByteStream; }
    }
    /*More properties here declared as regular properties or [MessageHeader]*/
}

然后,我与服务器和客户端共享该库。这应该意味着客户端不应实现自己的RemoteFileInfo类。但是,在我将.dll添加到客户端项目,然后在启用Reuse Types的情况下使用 Add Service Reference 后,它仍然在服务引用的命名空间内重新制作 RemoteFileInfo 类,这会在自身和我最初声明它的类库中的类型之间产生歧义。

所以我的问题是,如何在客户端和服务器之间共享已声明为MessageContract的类?我需要这样做,因为我的OperationContract需要一个RemoteFileInfo对象,并且我想保留我在原始RemoteFileInfo类中声明的相同属性。

我的OperationContract

    [OperationContract]
    void uploadFile(RemoteFileInfo request);

我希望能够在客户端上完全按照服务协定中的声明方式调用该方法。到目前为止,即使我在添加服务引用时玩弄Generate message headers选项,我最终也会得到一个具有byte[]参数而不是流的方法uploadFile,我需要它是一个流。

有什么想法吗?

编辑:我打算发布一个客户端配置,但我需要提到我正在为Windows应用商店应用程序开发,所以我没有传统的app.config。

下面是 WCF 测试客户端为客户端配置生成的内容:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IRTMobileWebService" sendTimeout="00:05:00" />
      </basicHttpBinding>
      <netTcpBinding>
        <binding name="uploadEndpoint" sendTimeout="00:05:00" transferMode="Streamed">
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="http://ipaddress/RTWebServices/RTMobileWebService.svc/basic"
          binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IRTMobileWebService"
          contract="IRTMobileWebService" name="BasicHttpBinding_IRTMobileWebService" />
      <endpoint address="net.tcp://ipaddress/RTWebServices/RTMobileWebService.svc/upload"
          binding="netTcpBinding" bindingConfiguration="uploadEndpoint"
          contract="IRTMobileImageService" name="uploadEndpoint">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

如何在没有 app.config 的 Windows 应用商店应用中复制它?

如果您正在与其中已有的服务接口共享 dll,那么您不应该费心使用向导添加服务引用 - 它会在大部分时间丢失内容,并在很多情况下创建比您需要的更多的代码,包括服务接口的全新实例。

相反,在使用服务的应用程序中,为服务创建自己的代理类,如下所示:

class ClientServiceClass : ClientBase<ITheServiceContract>, ITheServiceContract
{
    public ClientServiceClass ( string endpointConfigurationName ) :
        base( endpointConfigurationName )
    {
    }
    internal void uploadFile(RemoteFileInfo request)
    {
        Channel.uploadFile(request);
    }
}

其中ITheServiceContract是共享 dll 中的接口,即服务协定,ClientServiceClass是要调用服务代理类实现的任何内容(向导通常按服务名称调用它)。

若要在代码中使用该服务,请按如下所示:

NetTcpBinding binding = new NetTcpBinding();
binding.TransferMode = TransferMode.Streamed;
binding.Security = new NetTcpSecurity();
binding.Security.Mode = SecurityMode.None;
EndpointAddress address = new EndpointAddress("net.tcp://serviceEndpointAddress");
ClientServiceClass uploadClient = new ClientServiceClass(binding, address);
uploadClient.Open( );
uploadClient.uploadFile( yourFileInfoRequest );
uploadClient.Close( );

最新更新