How to deserialise a proto that was received as a byte[] - serialization

I am using the Spring.Rest framework.
If we receive a 402, the body will contain a proto which in turn will contain various error information.
The Exception raised on a 402 is an instance of Spring.Rest.Client.HttpClientErrorException.
The response within the exception is an instance of Spring.HttpResponseMessage.
The Body within the response is of type byte[].
This means I have a byte[] while the Deserialiser is expecting a Stream.
In order to deserialise the proto contained in the body I have done the following:
MemoryStream mStream = new MemoryStream();
mStream.Write(exception.Response.Body,0,exception.Response.Body.Length);
var proto = Serializer.Deserialize<XXXRestProtoException>(mStream);
when I inspect the proto returned, its properties are all null.
Is my approach correct, or do I need to do more before presenting the Stream to the Deserialize method?
We have confirmed that the proto definitions used on Client and Server are in sync and the body is well formed on the server.
The Stream produced by this code has the same length and contents as the given byte[], which in turn matches the content-length header.

If you Write to a stream, then the Position is left at the end of the stream; 2 simple options:
rewind the stream; between the Write and the Deserialize, put:
ms.Position = 0;
initialize the stream from the blob:
MemoryStream mStream = new MemoryStream(exception.Response.Body);
I'd usually use the latter.

Related

WCF Change message encoding from Utf-16 to Utf-8

I have a WCF connected service in a .net core application. I'm using the code that is autogenerated taken the wsdl definition.
Currently at the top of the request xml is including this line:
<?xml version="1.0" encoding="utf-16"?>
I can't find a simple way to change this encoding to UTF-8 when sending the request.
Since I could find a configuration option a the request/client objects, I've tried to change the message with following code at IClientMessageInspector.BeforeSendRequest
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
// Load a new xml document from current request
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(request.ToString());
((XmlDeclaration)xmlDocument.FirstChild).Encoding = Encoding.UTF8.HeaderName;
// Create streams to copy
var memoryStream = new MemoryStream();
var xmlWriter = XmlWriter.Create(memoryStream);
xmlDocument.Save(xmlWriter);
xmlWriter.Flush();
xmlWriter.Close();
memoryStream.Position = 0;
var xmlReader = XmlReader.Create(memoryStream);
// Create a new message
var newMessage = Message.CreateMessage(request.Version, null, xmlReader);
newMessage.Headers.CopyHeadersFrom(request);
newMessage.Properties.CopyProperties(request.Properties);
return null;
}
But the newMessage object still writes the xml declaration using utf-16. I can see it while debugging at the watch window since.
Any idea on how to accomplish this (should be) simple change will be very apreciated.
Which binding do you use to create the communication channel? The textmessageencoding element which has been contained in the CustomBinding generally contains TextEncoding property.
https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/textmessageencoding
WriteEncoding property specifies the character set encoding to be used for emitting messages on the binding. Valid values are
UnicodeFffeTextEncoding: Unicode BigEndian encoding
Utf16TextEncoding: Unicode encoding
Utf8TextEncoding: 8-bit encoding
The default is Utf8TextEncoding. This attribute is of type Encoding.
As for the specific binding, it contains the textEncoding property too.
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.basichttpbinding.textencoding?view=netframework-4.0
Feel free to let me know if there is anything I can help with.

Why JAX-RS Response.fromResponse(anotherResponse) not copying the entity?

This is part of a JAX-RS server which receives a response from another server and sends the same response back to its client.
This copies the entity from anotherResponse to responseForClient:
Response responseForClient = Response.fromResponse(anotherResponse).entity(anotherResponse.readEntity(InputStream.class)).build();
This doesn't copy the entity:
Response responseForClient = Response.fromResponse(anotherResponse).build();
The second one should also work as JAX-RS Response.fromResponse() should copy the entity also.
Why setting the entity is required?
I am using RestEasy-3.0.
You have to consume the InputStream before calling fromResponse because it only will copy the response. The JAX-RS won't do it automatically, and if you provide the new instance to the client then the entity will not be consumed
See the documentation of fromResponse
public static Response.ResponseBuilder fromResponse(Response response)
Create a new ResponseBuilder by performing a shallow copy of an existing Response.
The returned builder has its own response headers but the header values are shared with the original Response instance. The original response entity instance reference is set in the new response builder.
Note that if the entity is backed by an un-consumed input stream, the reference to the stream is copied. In such case make sure to buffer the entity stream of the original response instance before passing it to this method.
Buffer the response reading the InputStream to a byte array
InputStream is = anotherResponse.readEntity(InputStream.class);
byte[] bytes = IOUtils.toByteArray(is);
ByteArrayInputStream in= new ByteArrayInputStream (bytes);
This code is equivalent to yours
Response responseForClient =
Response.fromResponse(anotherResponse).entity(in).build()

vb- networkstream write only returns first result (need all)

My code looks very similar to this post Read bytes from NetworkStream (Hangs), which I copied below. ( I realize this is c# - I need a vb solution)
// Create a TcpClient.
// Note, for this client to work you need to have a TcpServer
// connected to the same address as specified by the server, port
// combination.
TcpClient client = new TcpClient(server, port);
// Translate the passed message into ASCII and store it as a Byte array.
Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);
// Get a client stream for reading and writing.
NetworkStream stream = client.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", message);
// Receive the TcpServer.response.
// Buffer to store the response bytes.
data = new Byte[256];
// String to store the response ASCII representation.
String responseData = String.Empty;
// Read the first batch of the TcpServer response bytes.
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
Console.WriteLine("Received: {0}", responseData);
// Close everything.
stream.Close(); client.Close();
My issue lies in this:
I have a form that takes user input on which tif file(s) to find (which ends up being the getBytes(message) ). When one does this, it always returns one result - the first tif file that fits the criteria, However, I know in certain instances I should recieve more than one match.
Then I send the results to a picturebox and should be able to scroll through results (which this part works fine)
I've tried a few ways to get multiple results, but maybe I'm missing the obvious? My best guess is using the asyncronous beginread/write....
I've attempted using a for loop but I end up getting a bunch of the same tif files as a result...
Could anyone help me (even with a generic direction)? I'm not a pro. Thanks in advance for the help.
I ended up finding out what the issue was. the data i was looking for wasn't standardized as so the results were the same data over and over. I changed what items I was looking for and tada it worked. anyway, thanks for the help

Restful WCF Service - returning byte[]?

I'm working with a RESTful WCF service. One of the service methods returns byte[] (which contains a file).
On the client side, I have some code that uses the WebRequest class to invoke that particular service method. Using the WebRequest, I'm getting the response stream like:
Stream stream = webReq.GetResponse().GetResponseStream();
From this stream, I am then reconstructing a byte[] and then outputting the File locally. The problem is that the reconstructed file on the client-side doesn't resemble the file that was returned from the service side (I get a corrupt PDF file that is much larger in size than the one sent from the service side). Just before the service method returns the byte[], I outputted that byte[] to disk on the service side and it created the file fine... This points to something going wrong between that method returning the byte[] and my client side reconstructing the byte[] from a Stream on the client side... to reconstruct the byte[] from the Stream, I'm using the following method which someone posted in the past on stackoverflow:
public static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16*1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
Any ideas what could be going wrong?
I guess that the response from the server contains some envelope in addition to the raw bytes. Like a XML envelope or something. Which would of course suppose that the bytes are base64 encoded string in the response because you cannot store binary data into XML. It would also explain why you are getting a bigger buffer on the client than the actual PDF that the server has sent.
This will of course depend on what binding your WCF service uses and how is it configured. When you dump the contents of the MemoryStream you are reading on the client what exactly do you see? This should give you further hints on how the actual PDF file is encoded in the HTTP response body.

How to edit WCF Message - WCF message interceptors

i'm having some problems implementing my WCF message interceptor. Basically i'm accessing the body contents and performing an xslt tranform over the nodeset to sort it alphabethicaly.
I've tested the XSLT stylesheet and it's working no problems. I write the result of the transform to a MemoryStream object and then attempt to recreate the message from the stream contents.
I examine the resulting stream using either a StreamReader or by loading it into an XmlDocument and i can see the the xml it contains it my expected result from the XSLT transform.
My problem occures when i try to recreate the message! I create an XmlReader based on the stream and use this as my body source for Message.CreateMessage(.....);
I cannot understand why i'm suddenly losing the "correct" contents in the stream when i could examine it and see a couple of statements earlier.
Help very much appreciated!
Full code of the method below:
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
MessageBuffer msgbuf = request.CreateBufferedCopy(int.MaxValue);
Message tmpMessage = msgbuf.CreateMessage();
XmlDictionaryReader xdr = tmpMessage.GetReaderAtBodyContents();
MemoryStream ms = new MemoryStream();
_compiledTransform.Transform(xdr,null,ms);
ms.Position = 0;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(ms);
MemoryStream newStream = new MemoryStream();
xmlDoc.Save(newStream);
newStream.Position = 0;
//To debug contents of the stream
StreamReader sr = new StreamReader(newStream);
var temp = sr.ReadToEnd();
//At this point the XSLT tranforms has resulted in the fragment we want so all good!
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
newStream.Position = 0;
XmlReader reader = XmlReader.Create(newStream,settings);
reader.MoveToContent();
//Reader seems to have lost the correct fragment!!! At least returned message does not contain correct fragment.
Message newMessage = Message.CreateMessage(request.Version, null, reader);
newMessage.Properties.CopyProperties(request.Properties);
request = newMessage;
return request;
}
I think your code works Griff. I've just plugged it into an existing an existing IDispatchMessageInspector implementation and it generated a good (transformed) message. I therefore suspect your problem lies elsewhere.
How are you establishing that the 'losing' the correct contents? Could whatever is inspecting the transformed message be reading the message prior to transformation by mistake?
Unless you are trying to correlate state with the BeforeSendReply method then you should be returning null instead of the request reference.