Deserializing memory stream into XML instead of structure

R

RobinS

I inherited some code that calls a web service that returns an encrypted
string. It gets decrypted into a string and then converted to a memory
stream.

MemoryStream ms = new
MemoryStream(Convert.FromBase64String(decryptedresult));

This is then deserialized into an instance of the structure:

BinaryFormatter bf = new BinaryFormatter();

ProductDetails pd = (ProductDetails)bf.Deserialize(ms);

And then I can access the fields.

I want to remove the dependence on knowing the structure, and deserialize it
into an XML string that I can parse for fields and values. Is that possible,
and how would I go about doing that?

Thanks in advance,
RobinS.
GoldMail, Inc.
 
A

Arne Vajhøj

RobinS said:
I inherited some code that calls a web service that returns an encrypted
string. It gets decrypted into a string and then converted to a memory
stream.

MemoryStream ms = new
MemoryStream(Convert.FromBase64String(decryptedresult));

This is then deserialized into an instance of the structure:

BinaryFormatter bf = new BinaryFormatter();

ProductDetails pd = (ProductDetails)bf.Deserialize(ms);

And then I can access the fields.

I want to remove the dependence on knowing the structure, and
deserialize it into an XML string that I can parse for fields and
values. Is that possible, and how would I go about doing that?

XmlSerializer Serialize will produce an XML string.

On the other end you can use XmlDocument LoadXML and analyze it.

(using XmlSerializer Deserialize would keep the dependency)

Arne
 
J

Jeroen Mostert

RobinS said:
I inherited some code that calls a web service that returns an encrypted
string. It gets decrypted into a string and then converted to a memory
stream.

MemoryStream ms = new
MemoryStream(Convert.FromBase64String(decryptedresult));

This is then deserialized into an instance of the structure:

BinaryFormatter bf = new BinaryFormatter();

ProductDetails pd = (ProductDetails)bf.Deserialize(ms);

And then I can access the fields.

I want to remove the dependence on knowing the structure, and
deserialize it into an XML string that I can parse for fields and
values. Is that possible, and how would I go about doing that?
BinaryFormatter serializes objects by embedding the type name, and this type
must be accessible (and compatible) in order for deserialization to succeed.
If you don't have the type definition handy, you can't deserialize the data
without reverse engineering the format, which is, shall we say, not recommended.

If it's no objection to you that the assembly containing the type must be
accessible and you just don't want an explicit dependency in the code, then
it can be done by serializing the result with XMLSerializer:

object o = bf.Deserialize(ms);
MemoryStream xmlStream = new MemoryStream();
new XmlSerializer(o.GetType()).Serialize(xmlStream, o);
xmlStream.Position = 0;
XPathDocument document = new XPathDocument(xmlStream);
// use here

However, XmlSerializer is more demanding than BinaryFormatter (for example,
it wants the type to be publicly accessible) so serialization might not be
possible. Also, this method doesn't really buy you much -- both sides still
have to agree on the type being transmitted, so you might as well make the
dependency explicit.

Of course, if you can change the service producing the result, you should
modify that to produce XML rather than binary serialization, but I'm
assuming that's not an option.
 
R

RobinS

Jeroen Mostert said:
BinaryFormatter serializes objects by embedding the type name, and this
type must be accessible (and compatible) in order for deserialization to
succeed. If you don't have the type definition handy, you can't
deserialize the data without reverse engineering the format, which is,
shall we say, not recommended.

If it's no objection to you that the assembly containing the type must be
accessible and you just don't want an explicit dependency in the code,
then it can be done by serializing the result with XMLSerializer:

object o = bf.Deserialize(ms);
MemoryStream xmlStream = new MemoryStream();
new XmlSerializer(o.GetType()).Serialize(xmlStream, o);
xmlStream.Position = 0;
XPathDocument document = new XPathDocument(xmlStream);
// use here

However, XmlSerializer is more demanding than BinaryFormatter (for
example, it wants the type to be publicly accessible) so serialization
might not be possible. Also, this method doesn't really buy you much --
both sides still have to agree on the type being transmitted, so you might
as well make the dependency explicit.

Of course, if you can change the service producing the result, you should
modify that to produce XML rather than binary serialization, but I'm
assuming that's not an option.

What I'm trying to get away from is having the Type defined on both the web
services side and the client side, so when we add properties to the
structure on the web services side, I only have to add parsing for those
fields to the client side.

Can I return a string of XML data and still have it be encrypted? This is
what is happening on the other side:

MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();

bf.Serialize(ms, usersproduct);
_result = Convert.ToBase64String(ms.GetBuffer());

If I change that to use an XML formatter instead, it still comes across as
encrypted, right?

I'm not sure where the encryption happens on the other side. It appears that
we have a web service and you pass in the name of the method to be called.
The code above is in that method. I assume the webservice is encrypting
before returning the result. I KNOW I have to decrypt it on the client side
for sure.

Thx,
RobinS.
 
J

Jeroen Mostert

RobinS said:
What I'm trying to get away from is having the Type defined on both the
web services side and the client side, so when we add properties to the
structure on the web services side, I only have to add parsing for those
fields to the client side.

Can I return a string of XML data and still have it be encrypted?

Of course. You can encrypt anything you like.
This is what is happening on the other side:

MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();

bf.Serialize(ms, usersproduct);
_result = Convert.ToBase64String(ms.GetBuffer());
There's no encryption in there. If there is encryption, it'll be of the
entire result, rather than this particular string. Base64-encoding is not
encryption, neither is piping something through a BinaryFormatter. These
steps are trivial to recognize and reverse for even a casual observer.
If I change that to use an XML formatter instead, it still comes across
as encrypted, right?
I suppose so. Since I don't see any encrypting happening, it's hard to tell,
but it's a safe assumption that the encryption doesn't care whether you're
encrypting Base64-encoded BinaryFormatter output or XmlSerializer output.
 
R

RobinS

Jeroen Mostert said:
Of course. You can encrypt anything you like.

There's no encryption in there. If there is encryption, it'll be of the
entire result, rather than this particular string. Base64-encoding is not
encryption, neither is piping something through a BinaryFormatter. These
steps are trivial to recognize and reverse for even a casual observer.

I suppose so. Since I don't see any encrypting happening, it's hard to
tell, but it's a safe assumption that the encryption doesn't care whether
you're encrypting Base64-encoded BinaryFormatter output or XmlSerializer
output.

I think the encryption is happening in the web service that calls the method
that gets the result.

So how do I pass back the result in XML. I assume I don't want to serialize
the structure, because then I have to have the structure on the other side
to deserialize. Is that right?

So could I create a datatable that basically contains [FieldName] and
[Value] and convert it to XML and return it? Would that work? Or is there an
easier way?

Thanks,
RobinS.
 
J

Jeroen Mostert

So how do I pass back the result in XML. I assume I don't want to
serialize the structure, because then I have to have the structure on
the other side to deserialize. Is that right?
No. Then you'll have XML, which you can process any way you like. You *can*
deserialize that, but (unlike the data you get from BinaryFormatter) you're
not obliged to deserialize it. You *do* have to have some idea of what's in
it before you can meaningfully process it, of course, but you don't need to
have the exact same type as the web service used for serialization.

In particular, it will allow you to define your own struct type and use that
for deserialization. As long as the existing fields are compatible, the
XmlSerializer will ignore any extraneous fields, and missing fields will be
left with their default values. This "loose conversion" can both be greatly
helpful and greatly harmful, because you can't see exactly what's happening.
So could I create a datatable that basically contains [FieldName] and
[Value] and convert it to XML and return it? Would that work?

That's another possible approach, yes.
 
R

RobinS

Jeroen Mostert said:
So how do I pass back the result in XML. I assume I don't want to
serialize the structure, because then I have to have the structure on the
other side to deserialize. Is that right?
No. Then you'll have XML, which you can process any way you like. You
*can* deserialize that, but (unlike the data you get from BinaryFormatter)
you're not obliged to deserialize it. You *do* have to have some idea of
what's in it before you can meaningfully process it, of course, but you
don't need to have the exact same type as the web service used for
serialization.

In particular, it will allow you to define your own struct type and use
that for deserialization. As long as the existing fields are compatible,
the XmlSerializer will ignore any extraneous fields, and missing fields
will be left with their default values. This "loose conversion" can both
be greatly helpful and greatly harmful, because you can't see exactly
what's happening.
So could I create a datatable that basically contains [FieldName] and
[Value] and convert it to XML and return it? Would that work?

That's another possible approach, yes.

Thanks for your help; you've definitely given me enough to go forward on for
now.

RobinS.
 
R

RobinS

Arne Vajhøj said:
XmlSerializer Serialize will produce an XML string.

On the other end you can use XmlDocument LoadXML and analyze it.

(using XmlSerializer Deserialize would keep the dependency)

Arne

Thanks; I'll check it out.

RobinS.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top