Returning a byte[] in WCF service - wcf

Is it a good practice to return a byte[] in a WCF service which will be invoked by many applications
below is the code
public byte[] GetDoc(string docParam)
{
byte[] doc;
doc = GenerateDoc(docParam);
}
Thanks

It's definitely possible to return byte[] and WCF allows you to do this using MTOM encoding.
If the size of the binary buffer is big you could use WCF streaming. In this case you would return Stream data type, and read from that Stream on the client side.

It's good practice to factor common code into a convenient method so that many callers could call this convenient method. This is regardless of return type. If the callers would need to manipulate the byte[], then this can become convenient and eliminate redundant code.
By the way, regarding the code that you posted, is that real code or just an example? If it's real code:
It won't compile, because it doesn't return a byte[].
If you were to call return doc; as the last line, why have GenerateDoc() inside GetDoc()? GetDoc() doesn't really provide any true benefit.

It's used when you want to transfer a binary buffer, and also perform Large Data Transfer using MTOM encoding (set on the Binding configuration). How to perform Large Data Transfer found here.

Related

WCF IsReference = true is resetting the values to Default

I have a very simple WCF 4.0 service in which I am returning an POCO entity object whose IsReference is set to true. When I return the object from my service, the values of primitive types (int, double, etc) are set correctly and the ones having references are also getting serialized properly, I've verified that the serialization happen correctly putting following code just before return statement. I've also verified that the members are correctly marked with [DataMember] and they have public getters/setters. However, when the object is received by the caller, all the primitive types are set to 0 and the ones with references are set to NULL.
Would appreciate any help!
try
{
var stream = new MemoryStream();
var dataContractSerializer = new DataContractSerializer(onlineSellItemDetail.GetType());
dataContractSerializer.WriteObject(stream, onlineSellItemDetail);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException.ToString());
}
This is almost always because no XML, empty XML, or incompatible XML was received on the client end. Sometimes, this is because the stream was not flushed or closed properly on the service side. Other times, the client side is operating with completely valid XML in its own stream, but is reading the XML by perhaps not starting at the beginning of the stream. If you enable tracing on the service side and the client side, generate tracing logs, and analyze with SvcTraceViewer, and in parallel, use Fiddler to monitor the wire traffic on both the client side and the service side, I think you'll find the answer for sure!

How to send byte[] using WCF efficiently

I need to send byte[] array using WCF services and I care about message size and performance. My question is: Does WCF convert my binary data to Base64 string internally? (I use netTcpBinding) If it does, how to prevent it?
My contract looks almost as simple as
IMyService
{
byte[] GetData()
}
In terms of the actual XML, byte arrays are serialized as xs:base64Binary, which is a Base64 encoding (obviously).
However, when you specify the netTcpBinding, WCF uses a binary message encoding of that XML (BinaryMessageEncodingBindingElement) which will encode those bytes as a binary stream.
It's a bit of a convoluted process, but at the end of the day, if you're using any of the net* bindings, byte arrays will go over the wire as raw bytes, not base64 strings. That's one of many reasons why it's generally more efficient to use the TCP or Named Pipe bindings, if you can.

Best practices for streaming response of WCF webservice

I'm trying to pull a large amount of data out of a WCF web service. The request is fairly small and the response message will be very big. Currently the web service is throwing SystemOutOfMemory exceptions due a limitation on IIS6 for the memory it can allocated (~1.4GB).
I have read in some blogs that implementing streaming will solve my problem.
Can anybody share their experiences with this topic? I'm most interested in any sample client-side & service-side code that can be shared or any recommendations/best practices. MemoryStream vs FileStream? Return type should be Stream, Message, Byte[]?
My operation looks like the following: (typically it will return a big number of elements in the response array, ~200K elements)
MediumSizeResponseClass[] GetData(SmallSizeRequestClass request)
If you want to stream back only the response, then use transferMode=streamedResponse in your binding configuration. This makes sure only the returned response will be streamed.
The return value of a streaming function must be a Stream. You can then read from that stream and do whatever you need to do with it (store it, analyse it, whatever).
So basically you'd have a service contract something like this:
[ServiceContract]
interface IYourService
{
[OperationContract]
Stream GetData(SmallSizeRequestClass request);
}
On the server, you basically just write to a stream, while on the client, you read from the stream.
Have you consulted the MSDN docs on WCF Streaming?

WCF System.ServiceModel.Channel.Message: binary message contents (non-XML)?

I need to retrieve binary (non-XML) documents as Messages in a custom WCF LOB Adapter (for consumption by BizTalk). The messages need to be represented as instances of System.ServiceModel.Channel.Message.
I can't find how to create an instance of this class when the content is binary (by "binary" I mean any arbitrary byte array or Stream, and not only binary representations of XML documents).
Is this possible? Or would wraping the binary contents in an XML enveloppe be the only way to do this in WCF?
Fundamentally, WCF messages are XML, since the S.S.C.Message class uses the Xml InfoSet as the base message representation.
So yes, in some way you need to "wrap" your binary content into an XML envelope (which doesn't need to be a SOAP envelope, mind you, depending on how your binding is configured).
That said, note that this doesn't preclude streaming to deal with large message payloads without buffering the entire message in memory; WCF still allows you to do this, though sometimes it's not greatly obvious how it works.
Since you're working with a custom channel, you've got one of two choices, I think:
Have your own channel add the XML wrapper around your binary content before passing it upwards or
Create a custom MessageEncoder that adds it in for you automatically.
In either case, if you're dealing with large messages, you'll want to make sure you use the MessageEncoder overloads that handle Streams instead of buffers, as they are the ones that give you the option of doing coordinated streaming with the service implementation.
WCF offers some ways to send binary attachments and stream data in various ways. We have an application at work that does this, but I haven't had a chance to dig through the code, so I can't offer too much help. Here are a few links that might get you started (Nicholas Allen's Indigo Blog is a great place for WCF info):
http://blogs.msdn.com/drnick/archive/2006/03/31/565558.aspx
http://weblogs.asp.net/cibrax/archive/2007/08/29/sending-attachments-with-wcf.aspx

WCF Chunking / Streaming

I'm using WCF and want to upload a large file from the client to the server. I have investigated and decided to follow the chunking approach outlined at http://msdn.microsoft.com/en-us/library/aa717050.aspx
However, this approach (just like streaming) restricts the contract to limited method signitures:
[OperationContract(IsOneWay=true)]
[ChunkingBehavior(ChunkingAppliesTo.InMessage)]
void UploadStream(Stream stream);
The sample uses the rather convenient example of uploading a file from a fixed path and saving it to a fixed path on the server. Therefore, my question is how do I pass additional parameters to specify things like filename, filepath etc.
eg. I would like something like:
[OperationContract(IsOneWay=true)]
[ChunkingBehavior(ChunkingAppliesTo.InMessage)]
void UploadStream(Stream stream, String filePath);
Thanks in advance,
Mark.
This article explains how to use the MessageHeader attribute to force things to be passed in the header, and therefore not count as a parameter. So, instead of passing a stream and other meta data, create a class that has the attribute MessageContract and mark all of the meta data as a MessageHeader. Then, mark the stream as a MessageBodyMember (which the article incorrect calls "MessageBody"). Have your UploadStream method take a single parameter whose type is that of the MessageContract class you've just created. I've done this successfully, but I haven't done it in tandem with chunking. Good luck.
You could make your service session-ful and have an initialization method in the contract with the IsInitiating property set to true. Something like:
[OperationContract(IsInitiating = true)]
void InitializeUploadService(string filename);
[OperationContract(IsOneWay = true, IsInitiating = false)]
[ChunkingBehavior(ChunkingAppliesTo.InMessage)]
void UploadStream(Stream stream);
I have never tried it with streaming services but it should basically make WCF enforce that InitializeUploadService is always called before UploadStream.
More documentation can be found here:
http://msdn.microsoft.com/en-us/library/system.servicemodel.description.operationdescription.isinitiating.aspx
I would look at MessageContracts and add those values as message headers to your object. This should allow you to pass the stream and any values related to the stream as message headers.
Setting up the maxItemsInObjectGraph in the Client side and Server side worked for me.
(Dont forget the client side.) http://social.msdn.microsoft.com/Forums/en/wcf/thread/0af69654-2d89-44f3-857a-583b57844ca5