Question Cannot Deserialize using XmlSerializer

njsokalski

Well-known member
Joined
Mar 16, 2011
Messages
102
Programming Experience
5-10
I have the following code that serializes an object:

Dim stream As New MemoryStream()
Dim xml As New XmlSerializer(GetType(SyncData))
xml.Serialize(stream, New SyncData(CType(Application.Current, App).Recipients, CType(Application.Current, App).Gifts))

However, when I later attempt to check whether it can be deserialized using the following code:

If New XmlSerializer(GetType(SyncData)).CanDeserialize(XmlReader.Create(stream)) Then

I receive the following error:

Data at the root level is invalid. Line 1, position 1.

The XML is all well formed, and the first line is the following:

<?xml version="1.0"?>

From what I could find, it sounds like this has something to do with encoding or some illegal character at the beginning of the file, but I am not sure how to fix it. Can anybody help me? Thanks.
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,439
Location
Norway
Programming Experience
10+
You write to a MemoryStream and then try to read from it, normally stream position is then at end of content and reader won't find anything from there on. Try this before reading from it:
stream.Position = 0
 

njsokalski

Well-known member
Joined
Mar 16, 2011
Messages
102
Programming Experience
5-10
Actually, I do include that. Here is the rest of the code for creating the XML, it serializes the object and then uploads it:

Private Sub btnUpload_Tap(sender As Object, e As System.Windows.Input.GestureEventArgs) Handles btnUpload.Tap
If Me.client IsNot Nothing Then
AddHandler Me.client.UploadCompleted, AddressOf Me.Client_UploadCompleted
Dim stream As New MemoryStream()
Dim xml As New XmlSerializer(GetType(SyncData))
xml.Serialize(stream, New SyncData(CType(Application.Current, App).Recipients, CType(Application.Current, App).Gifts))
stream.Position = 0
Me.client.UploadAsync("me/skydrive", datafilename, stream, OverwriteOption.Overwrite)
End If
End Sub

This uploads the file to my SkyDrive account, and then when I try to deserialize it I download it and use that stream, so the upload & download streams are different objects that don't even exist at the same time.
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,439
Location
Norway
Programming Experience
10+
I don't know SkyDrive, but I can confirm what I replied in previous post and I can not replicate your CanDeserialize test failure, it must be something related specifically to the API you're using.
 

njsokalski

Well-known member
Joined
Mar 16, 2011
Messages
102
Programming Experience
5-10
I don't know if this is the problem or not, but many of the things I managed to find online that mentioned this error said it had something to do with encoding. I do not specify a specific encoding anywhere in my code, so I am wondering if the fact that I use a MemoryStream while uploading is somehow causing an encoding problem. Here is my code again:

The upload code:

Dim stream As New MemoryStream()
Dim xml As New XmlSerializer(GetType(SyncData))
xml.Serialize(stream, New SyncData(CType(Application.Current, App).Recipients, CType(Application.Current, App).Gifts))
stream.Position = 0
Me.client.UploadAsync("me/skydrive", datafilename, stream, OverwriteOption.Overwrite)

The download code:

If New XmlSerializer(GetType(SyncData)).CanDeserialize(XmlReader.Create(e.Result)) Then
e.Result.Position = 0
Dim tempdata As SyncData = CType(New XmlSerializer(GetType(SyncData)).Deserialize(e.Result), SyncData)
CType(Application.Current, App).Recipients = tempdata.Recipients
CType(Application.Current, App).Gifts = tempdata.Gifts
End If
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,439
Location
Norway
Programming Experience
10+
If New XmlSerializer(GetType(SyncData)).CanDeserialize(Xm lReader.Create(e.Result)) Then
e.Result.Position = 0
This is more than likely a bad idea, you can only read network related streams read once and they don't support seeking (feel free to check CanSeek property). Get rid of that check and attempt deserialization directly.
If you need to check out things for debugging, read the stream to local storage (file/memory) and continue operate on that and not e.Result.
 

njsokalski

Well-known member
Joined
Mar 16, 2011
Messages
102
Programming Experience
5-10
I tried reducing the download code to just:

Dim tempdata As SyncData = CType(New XmlSerializer(GetType(SyncData)).Deserialize(e.Result), SyncData)

But it still gives the same error:

There is an error in XML document (1, 1).

So you may be correct about what you said (although CanSeek was True), but either way, the error is still the same even with just the one line, so there is still something I am missing. Any ideas? Thanks.
 

njsokalski

Well-known member
Joined
Mar 16, 2011
Messages
102
Programming Experience
5-10
What should I do to save it to a FileStream? I couldn't seem to find a constructor or good method for creating a FileStream with the stream that I have. Thanks.
 

njsokalski

Well-known member
Joined
Mar 16, 2011
Messages
102
Programming Experience
5-10
I changed the code to:

Private Sub Client_DownloadCompleted(sender As Object, e As LiveDownloadCompletedEventArgs)
If e.Error Is Nothing Then
System.Diagnostics.Debug.WriteLine("Checkpoint 1")
Dim fs As New FileStream("GiftTrackerData.xml", FileMode.Create)
e.Result.CopyTo(fs)
Dim tempdata As SyncData = CType(New XmlSerializer(GetType(SyncData)).Deserialize(fs), SyncData)
CType(Application.Current, App).Recipients = tempdata.Recipients
CType(Application.Current, App).Gifts = tempdata.Gifts
System.Diagnostics.Debug.WriteLine("Checkpoint 2")
Else
System.Diagnostics.Debug.WriteLine("Checkpoint 3")
MessageBox.Show(e.Error.Message, "Download Error", MessageBoxButton.OK)
System.Diagnostics.Debug.WriteLine("Checkpoint 4")
End If
RemoveHandler Me.client.DownloadCompleted, AddressOf Client_DownloadCompleted
End Sub

As you can see, I added System.Diagnostics.Debug.WriteLine statements at the beginning and end of both possibilities of the If statement. But what is probably the most confusing thing now is that when I run the code, it outputs "Checkpoint 1" (so the e.Error Is Nothing condition must be True), but then it gives the following error on the Checkpoint 3 line:

Attempt to access the method failed: System.IO.FileStream..ctor(System.String, System.IO.FileMode)

The thing that makes this so confusing is that Checkpoint 1 and Checkpoint 3 are in different parts of the If statement, how can it be executing code in the True AND False sections of the If statement? Also, how can I get it to show the whole error message instead of using the ..? I am guessing that the "ctor" in the error message is for constructor, so what did I do wrong in my FileStream constructor? Thanks.
 

njsokalski

Well-known member
Joined
Mar 16, 2011
Messages
102
Programming Experience
5-10
On what line should I close the file? I have used Notepad to view the contents, they are exactly what I wanted and expected (well, that's what they look like in Notepad). It is all valid XML, no spaces at the beginning or end (at least none that I can see in Notepad), so the file contents seem correct. Thanks.
 
Top Bottom