使用消息合同上传文件
本文关键字:文件 合同 消息 | 更新日期: 2023-09-27 18:35:24
我一直在关注各种教程,这些教程解释了如何通过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( );