The most efficient way to transfer binary data (in WCF) is to use an endpoint whose binding uses the BinaryMessageEncodingBindingElement, and a transport binding element. As long as you don't have security or other channels which add complexity to the message, the overhead of the infoset shouldn't be a problem.
Example:
public class Post2944384b
{
[
ServiceContract]
public interface ITest
{
[
OperationContract]
void Process(byte[] input);
}
public class Service : ITest
{
public void Process(byte[] input)
{
Console.WriteLine("Received {0} bytes from the client", input.Length);
}
}
static Binding CreateBinding()
{
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode =
SecurityMode.None;
binding.MaxReceivedMessageSize =
int.MaxValue;
binding.ReaderQuotas.MaxArrayLength =
int.MaxValue;
return binding;
}
public static void Test()
{
string baseAddress = "net.tcp://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(
typeof(ITest), CreateBinding(), "");
host.Open();
Console.WriteLine("Host opened");
ChannelFactory<ITest> factory = new ChannelFactory<ITest>(CreateBinding(), new EndpointAddress(baseAddress));
ITest proxy = factory.CreateChannel();
byte[] input = new byte[23456];
Random rndGen = new Random(1);
rndGen.NextBytes(input);
proxy.Process(input);
((IClientChannel)proxy).Close();
factory.Close();
Console.WriteLine("Press ENTER to close service");
Console.ReadLine();
host.Close();
}
}
Another option, if you're using .NetFX 3.5, is to use the web programming model's support for raw data - your operation would simply take (or return) a System.IO.Stream object, and it can receive (or return) any blob without any overhead at all. Notice that you could also use Stream in the first case.
Example:
public class Post2944384
{
[
ServiceContract]
public interface ITest
{
[
OperationContract, WebInvoke]
void Process(Stream input);
}
public class Service : ITest
{
public void Process(Stream input)
{
int bytesRead = 0, totalBytesRead = 0;
byte[] buffer = new byte[10000];
do
{
bytesRead = input.Read(buffer, 0, buffer.Length);
totalBytesRead += bytesRead;
}
while (bytesRead > 0);
Console.WriteLine("Received {0} bytes from the client", totalBytesRead);
}
}
public class MyContentTypeMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
return WebContentFormat.Raw;
}
}
static Binding CreateBinding()
{
WebMessageEncodingBindingElement webBE = new WebMessageEncodingBindingElement();
webBE.ContentTypeMapper =
new MyContentTypeMapper();
HttpTransportBindingElement httpBE = new HttpTransportBindingElement();
httpBE.MaxReceivedMessageSize =
int.MaxValue;
httpBE.ManualAddressing =
true;
CustomBinding result = new CustomBinding(webBE, httpBE);
return result;
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
WebHttpBinding serverBinding = new WebHttpBinding();
ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), CreateBinding(), "");
endpoint.Behaviors.Add(
new WebHttpBehavior());
host.Open();
Console.WriteLine("Host opened");
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(baseAddress + "/Process");
req.Method = "POST";
req.ContentType = "application/octet-stream";
string reqBody = @"whatever you want to send to the service in a binary blob";
byte[] reqBodyBytes = Encoding.UTF8.GetBytes(reqBody);
Stream reqStream = req.GetRequestStream();
reqStream.Write(reqBodyBytes, 0, reqBodyBytes.Length);
reqStream.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
Console.WriteLine(new StreamReader(resp.GetResponseStream()).ReadToEnd());
resp.Close();
Console.WriteLine("Now using the programming model to send data to the service...");
ChannelFactory<ITest> factory = new ChannelFactory<ITest>(CreateBinding(), new EndpointAddress(baseAddress));
factory.Endpoint.Behaviors.Add(new WebHttpBehavior());
ITest proxy = factory.CreateChannel();
FileStream fs = new FileStream(Assembly.GetEntryAssembly().Location, FileMode.Open, FileAccess.Read, FileShare.Read);
proxy.Process(fs);
fs.Close();
((IClientChannel)proxy).Close();
factory.Close();
Console.WriteLine("Press ENTER to close service");
Console.ReadLine();
host.Close();
}
}