سؤال

I've got a WCF service that allows the uploading of files without using a MessageContract.

[OperationContract, WebInvoke(UriTemplate = "UploadFile?filename={filename}")]
bool UploadFile(string filename, Stream fileContents);

I'm allowed to use another parameter beside the Stream object because it's part of the UriTemplate. Since the service runs as a Managed Windows Service, I have to start the ServiceHost manually.

protected override void OnStart(string[] args)
{
    FileServiceHost = new ServiceHost(typeof(FileService), new Uri("http://" + Environment.MachineName + ":8000/FileService"));
    FileServiceHost.AddServiceEndpoint(typeof(IFile), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
    FileServiceHost.Open();
}

With all of this, the service starts up and works just fine. However I wanted to move some of the above to the app.config file. To do this, I commented out the second line of OnStart and replaced the first line with FileServiceHost = new ServiceHost(typeof(FileService)). Then I added that info to the app.config...

<system.serviceModel>

<services>
  <service name="Test.Server.FileService" behaviorConfiguration="DefaultBehavior">
    <host>
      <baseAddresses>
        <add baseAddress="net.tcp://localhost:8000/FileService"/>
      </baseAddresses>
    </host>
    <endpoint address="" binding="webHttpBinding" contract="IFile"/>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
</services>

<behaviors>
  <serviceBehaviors>
    <behavior name="DefaultBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
  </serviceBehaviors>
</behaviors>

And suddenly the service can no longer start up. It throws this exception on FileServiceHost.Open of the OnStart method: "For request in operation UploadFile to be a stream the operation must have a single parameter whose type is Stream."

There must be something wrong with the way I'm defining the service in app.config, because when I remove it from there, everything works fine. What am I doing wrong here?

هل كانت مفيدة؟

المحلول

Here's how I fixed the issue by adding webHttpBinding to the endpoint behavior.

Added behaviorConfiguration="TestBehavior" to <endpoint address="" binding="webHttpBinding" contract="IFile"/>, and then defined TestBehavior as follows:

<endpointBehaviors>
    <behavior name="TestBehavior">
      <webHttp />
    </behavior>
</endpointBehaviors>

نصائح أخرى

For streaming to be enabled in WCF, there are multiple restrictions. One of them is to have a single parameter of type Stream (or any of two other types.)

This possibly means that WCF "guessed" that you were trying to stream content in your contract and defaulted the TransferMode to Streamed (This is purely a guess. It's not what is documented. Documentation says TransferMode defaults to Buffered.)

One option would be to set the transfer mode to Buffered explicitly in XML:

<webHttpBinding>
    <binding name="MyWebBinding" transferMode="Buffered"/>
</webHttpBinding>

However, using the Buffered transfer mode, the content of the message would be entirely buffered before being sent, which is not a good thing with large files.

Another option would be to use the Streamed transfer mode. If you want to stream a file's content and provide a file name at the same time, you will have to define a custom Message class and send the file's metadata in the message headers:

[MessageContract]
public class UploadFileMessage
{
   [MessageHeader]
   public string Filename { get; set; }

   [MessageBodyMember]
   public Stream Content { get; set; }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top