Reputation: 3601
I have a WCF service hosted in a ASP.NET application and am trying to upload a file from another client ASP.NET application using streaming mode. I keep getting following error:
The remote server returned an unexpected response: (400) Bad Request.
I have browsed the net to get help but to no avail.
Host configuration:
<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>
Contracts code:
[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;
}
}
}
Client configuration:
<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>
Client code:
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);
The call fails for both clientUpload.TestMethod() and clientUpload.UploadFile(uploadRequestInfo). With buffered mode clientUpload.TestMethod() is invoked so the issue is with the configuration in the streaming mode.
I'd be grateful to find any help on this matter. Thanks.
Upvotes: 4
Views: 6332
Reputation: 604
I've got the same problems and I found this article explain to solve your error. http://www.c-sharpcorner.com/uploadfile/BruceZhang/stream-operation-in-wcf/.
Hope this help!
Upvotes: 2
Reputation: 49185
Issue is in your data contract - public System.IO.Stream FileByteStream;
. Remove this member from data contract and use stream
in your operation contract - for example:
[OperationContract(OneWay=true)]
void UploadFile(RemoteFileInfo request, System.IO.Stream fileData);
Quoted from 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.
Streaming Data section from the same link explains this in details.
Issue is in your data contract - public System.IO.Stream FileByteStream;
. Remove this member from data contract and use stream
in your operation contract - for example:
[OperationContract(OneWay=true)]
void UploadFile(RemoteFileInfo request, System.IO.Stream fileData);
Quoted from 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.
Streaming Data section from the same link explains this in details.
EDIT:
Apologies - I have overlooked restrictions. You have two ways to solve the issue - use MessageContract
or use multiple operations for a single transaction. Example of using multiple operations will be
[OperationContract]
Token UploadFile(System.IO.Stream fileData);
[OperationContract]
void ProvideFileInfo(Token token, RemoteFileInfo request);
First upload the data to server and server will issue a token (e.g. guid), use the token to update other information.
More preferable way will be using MessageContract
and which you have already trying. Few suggestions to trouble-shoot:
Upvotes: 2