2011-07-06 57 views
4

我有一個WCF服務在ASP.NET應用程序中託管,並且正嘗試使用流模式從另一個客戶端ASP.NET應用程序上傳文件。 我不斷收到以下錯誤:WCF與ASP.NET的Streaming問題

The remote server returned an unexpected response: (400) Bad Request.

我瀏覽過網得到幫助,但無濟於事。

主機配置:

<bindings> 
     <basicHttpBinding> 
     <binding name="FileTransferServicesBinding" 
      transferMode="Streamed" 
      messageEncoding="Mtom" 
      sendTimeout="01:05:00" 
      maxReceivedMessageSize="10067108864"> 
     </binding> 
     </basicHttpBinding> 
    </bindings> 
    <services> 
     <service behaviorConfiguration="FileTransferServiceBehavior" name="WebServiceHost.TransferService"> 
     <clear /> 
     <endpoint address="" binding="basicHttpBinding" 
      bindingConfiguration="FileTransferServicesBinding" contract="WebServiceHost.ITransferService"> 
      <identity> 
      <dns value="localhost"/> 
      <certificateReference storeName="My" storeLocation="LocalMachine" 
       x509FindType="FindBySubjectDistinguishedName" /> 
      </identity> 
     </endpoint> 
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"> 
     </endpoint> 
     <host> 
      <baseAddresses> 
      <add baseAddress="http://localhost:11291/TransferService.svc" /> 
      </baseAddresses> 
     </host> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
     <behavior name="FileTransferServiceBehavior"> 
      <serviceMetadata httpGetEnabled="true" /> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    </system.serviceModel> 

合約代碼:

[ServiceContract] 
public interface ITransferService 
{ 
    [OperationContract] 
    RemoteFileInfo DownloadFile(DownloadRequest request); 

    [OperationContract] 
    void UploadFile(RemoteFileInfo request); 

    [OperationContract] 
    string TestMethod(); 
} 

[MessageContract] 
public class DownloadRequest 
{ 
    [MessageBodyMember] 
    public string FileName; 
} 

[MessageContract] 
public class RemoteFileInfo : IDisposable 
{ 
    [MessageHeader(MustUnderstand = true)] 
    public string FileName; 

    [MessageHeader(MustUnderstand = true)] 
    public long Length; 

    [MessageBodyMember(Order = 1)] 
    public System.IO.Stream FileByteStream; 

    public void Dispose() 
    { 
     if (FileByteStream != null) 
     { 
      FileByteStream.Close(); 
      FileByteStream = null; 
     } 
    } 
} 

客戶端配置:

<bindings> 
    <basicHttpBinding> 
    <binding name="FileTransferServicesBinding" sendTimeout="01:05:00" 
     maxReceivedMessageSize="10067108864" messageEncoding="Mtom" 
     transferMode="Streamed" /> 
    </basicHttpBinding> 
</bindings> 
<client> 
    <endpoint address="http://localhost:11291/TransferService.svc/" 
     binding="basicHttpBinding" bindingConfiguration="FileTransferServicesBinding" 
     contract="TransferServiceReference.ITransferService" name="FileTransferService" 
     kind=""> 
    <identity> 
     <dns value="localhost" /> 
     <certificateReference storeName="My" storeLocation="LocalMachine" 
      x509FindType="FindBySubjectDistinguishedName" /> 
    </identity> 
    </endpoint> 
</client> 
<behaviors> 
    <serviceBehaviors> 
    <behavior> 
     <serviceMetadata httpGetEnabled="true" /> 
     <serviceDebug includeExceptionDetailInFaults="true" /> 
    </behavior> 
    </serviceBehaviors> 
</behaviors> 

客戶機代碼:

ITransferService clientUpload = new TransferServiceClient(); 

string datetime = clientUpload.TestMethod(); 

var uploadRequestInfo = new RemoteFileInfo(); 

uploadRequestInfo.FileName = FileUpload1.FileName; 
uploadRequestInfo.Length = FileUpload1.PostedFile.ContentLength; 
uploadRequestInfo.FileByteStream = FileUpload1.PostedFile.InputStream; 
clientUpload.UploadFile(uploadRequestInfo); 

調用失敗兩者clientUpload.TestMethod()和clientUpload.UploadFile(uploadRequestInfo)。緩衝模式clientUpload.TestMethod()被調用,因此問題出現在流模式下的配置。

我很感謝在這件事上找到任何幫助。謝謝。

+0

我看不到任何明顯錯誤的配置。您可能必須對服務進行[啓用跟蹤](http://msdn.microsoft.com/zh-cn/library/ms733025.aspx)以深入挖掘 – Smudge202

回答

2

問題在於您的數據合同 - public System.IO.Stream FileByteStream;。從數據合同中刪除此成員,在你的經營合同使用stream - 例如:

[OperationContract(OneWay=true)] 
void UploadFile(RemoteFileInfo request, System.IO.Stream fileData); 

Large Data and Streaming(MSDN)報價:

You should not be using System.IO.Stream derived types inside of data contracts. Stream data should be communicated using the streaming model, explained in the following "Streaming Data" section.

從相同的鏈接流數據部分的細節說明這一點。

問題在於您的數據合同 - public System.IO.Stream FileByteStream;。從數據合同中刪除此成員,在你的經營合同使用stream - 例如:

[OperationContract(OneWay=true)] 
void UploadFile(RemoteFileInfo request, System.IO.Stream fileData); 

Large Data and Streaming(MSDN)報價:

You should not be using System.IO.Stream derived types inside of data contracts. Stream data should be communicated using the streaming model, explained in the following "Streaming Data" section.

從相同的鏈接流數據部分的細節說明這一點。

編輯: 道歉 - 我忽視了限制。您有兩種方法可以解決問題 - 使用MessageContract或對單個事務使用多個操作。使用多個操作的示例將是

[OperationContract] 
Token UploadFile(System.IO.Stream fileData); 

[OperationContract] 
void ProvideFileInfo(Token token, RemoteFileInfo request); 

首先將數據上傳到服務器和服務器將發出的令牌(例如GUID),使用令牌來更新其它信息。

更優選的方式將使用MessageContract和你已經嘗試。幾個建議,以排除故障:

  1. 如果您在IIS中託管它,請檢查web.config中的maxRequestLength。嘗試上傳小文件。
  2. 不是直接使用PostedFile流,而是將其存儲到磁盤並在其上使用流。正在進行上傳時,推理爲http請求流可能會清理乾淨。
  3. 使用諸如fiddler之類的工具並查看通過電報傳遞給服務的消息,這可能會提供線索。
+0

使用Stream時,它會施加很少的限制: 可以使用只是流類型的一個參數或返回值,並且如果傳遞了其他類型參數,則會引發以下錯誤: 「System.InvalidOperationException:對於操作中的請求UploadFile是流,操作必須具有單個參數,其類型爲Stream 「。 – rageit

+0

我還需要傳遞一些與流有關的數據,例如標識值,因此使用了MessageContract。同樣,當允許在單個參數上使用MessageContract時。 – rageit

+0

僅供參考:void void UploadFile(RemoteFileInfo request,System.IO.Stream fileData); 「操作UploadFile具有一個參數或返回類型,該參數或返回類型歸屬於MessageContractAttribute。爲了使用消息合約表示請求消息,操作必須具有一個由MessageContractAttribute賦值的參數。爲了表示響應消息使用消息合約,操作的返回值必須是由MessageContractAttribute歸類的類型,並且操作可能沒有任何out或ref參數。「 – rageit