1
votes

I am creating my first WCF service that uses Stream. The end product I want is to select a file from my hard disk and save it to a database. So the first step I am trying to complete is to read a selected .jpg file.

My Contract looks like this:

namespace Web
{
    interface name "IStreamingService" 
    [ServiceContract]
    public interface IStreamingService
    {
        [OperationContract]
        Stream GetStream(string data);
    }
}

My IService is:

public class StreamingService : IStreamingService
    {
        public Stream GetStream(string data)
        {
            string filePath = data;       
            try
            {
                FileStream imageFile = File.OpenRead(filePath);
                return imageFile;
            }
            catch (IOException ex)
            {
                Console.WriteLine(
                    String.Format("An exception was thrown while trying to open file {0}", filePath));
                Console.WriteLine("Exception is: ");
                Console.WriteLine(ex.ToString());
                throw ex;
            }
        }
    }

My Web.Config file looks like this with httpRuntime maxRequestLength="2147483647" added to allow for a large file being streamed.

<!-- language: xaml -->
   <?xml version="1.0"?>
     <configuration>

      <system.web>
        <compilation debug="true" targetFramework="4.0" />
        <!-- ADDED ASP.NET doesn’t know about WCF and it has it’s own limits for the request size, now increased to match maxReceivedMessageSize. -->
        <httpRuntime maxRequestLength="2147483647"/>
      </system.web>
      <system.serviceModel>
        <behaviors>
         <serviceBehaviors>
            <behavior>
              <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
              <serviceDebug includeExceptionDetailInFaults="false"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
      </system.serviceModel>
     <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
      </system.webServer>

    </configuration>

Then I have Console application with the Service Reference added. I have altered the app.config so the transferedMode="Streamed" and the maxReceivedMessageSize="2147483647" to again to allow large files to transferred.

Finally my program is :

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string data = @"C:/Users/Admin/Desktop/IMG_0038.JPG";

            StreamingServiceClient serviceHost = new StreamingServiceClient();

            serviceHost.GetStream(data);
        }
    }
}

When i run the application i get the error The remote server returned an unexpected response: (400) Bad Request.

Can anyone point me in the right direction so I can move on, so that once I have read in the file I can the save it.

1
How is this hosted, on IIS/WAS or self hosted? Do have a requirement to present the endpoint externally or is it only internal?Ira Rainey
I am self hosting and only need the endpoint internalfreerider11
Well I've got some code pretty much the same as yours, other than I'm using a netTcp endpoint and hosting it on WAS, and it works just fine. If you only need to serve internally then changing the endpoint to netTcp would result in better performance, plus it uses binary formatting as standard.Ira Rainey

1 Answers

2
votes

You have two options. The first is to use one of the binary-encoded message transmission mechanisms. You can choose the binary encoder if you don't have concerns about interoperability with other platforms (IOW, .NET-to-.NET communications) or you can use MTOM if you want to talk to other systems that are not .NET. In this case you would change the signature to a byte array and make sure to transmit the actual bytes, not a stream. Depending on the size of the images and how many you are delivering at a time, this could or could not place a strain on memory in your system.

The second option is to use streaming. In this case, you can only use the Basic HTTP binding (not the WS HTTP binding, that does not support streaming). You would retain the message signature with the Stream return parameter, but set up the binding to support streaming.

Niraj Bhatt has a great blog entry titled "MTOM vs. Streaming vs. Compression – Large attachments over WCF" which goes into detail about how to implement each of the options presented above, as well as more information as to when one might be more useful over the other.