Deserialize complex JSON (VB.NET) - vb.net

I'm trying to deserialize json returned by some directions API similar to Google Maps API. My JSON is as follows (I'm using VB.NET 2008):
jsontext =
{
"version":0.3,
"status":0,
"route_summary":
{
"total_distance":300,
"total_time":14,
"start_point":"43",
"end_point":"42"
},
"route_geometry":[[51.025421,18.647631],[51.026131,18.6471],[51.027802,18.645639]],
"route_instructions": [["Head northwest on 43",88,0,4,"88 m","NW",334.8],["Continue on 42",212,1,10,"0.2 km","NW",331.1,"C",356.3]]
}
So far I came up with the following code:
Dim js As New System.Web.Script.Serialization.JavaScriptSerializer
Dim lstTextAreas As Output_CloudMade() = js.Deserialize(Of Output_CloudMade())(jsontext)
I'm not sure how to define complex class, i.e. Output_CloudMade.
I'm trying something like:
Public Class RouteSummary
Private mTotalDist As Long
Private mTotalTime As Long
Private mStartPoint As String
Private mEndPoint As String
Public Property TotalDist() As Long
Get
Return mTotalDist
End Get
Set(ByVal value As Long)
mTotalDist = value
End Set
End Property
Public Property TotalTime() As Long
Get
Return mTotalTime
End Get
Set(ByVal value As Long)
mTotalTime = value
End Set
End Property
Public Property StartPoint() As String
Get
Return mStartPoint
End Get
Set(ByVal value As String)
mStartPoint = value
End Set
End Property
Public Property EndPoint() As String
Get
Return mEndPoint
End Get
Set(ByVal value As String)
mEndPoint = value
End Set
End Property
End Class
Public Class Output_CloudMade
Private mVersion As Double
Private mStatus As Long
Private mRSummary As RouteSummary
'Private mRGeometry As RouteGeometry
'Private mRInstructions As RouteInstructions
Public Property Version() As Double
Get
Return mVersion
End Get
Set(ByVal value As Double)
mVersion = value
End Set
End Property
Public Property Status() As Long
Get
Return mStatus
End Get
Set(ByVal value As Long)
mStatus = value
End Set
End Property
Public Property Summary() As RouteSummary
Get
Return mRSummary
End Get
Set(ByVal value As RouteSummary)
mRSummary = value
End Set
End Property
'Public Property Geometry() As String
' Get
' End Get
' Set(ByVal value As String)
' End Set
'End Property
'Public Property Instructions() As String
' Get
' End Get
' Set(ByVal value As String)
' End Set
'End Property
End Class
but it does not work. The problem is with complex properties, like route_summary. It is filled with "nothing". Other properties, like "status" or "version" are filled properly.
Any ideas, how to define class for the above JSON?
Can you share some working code for deserializing JSON in VB.NET?
Thanks,

Below is a sample Converter class that will take an incoming stream of JSON and convert to to an object you specify. I should note the below code is .Net 4.0. The JSON serializer in 4 is much easier to use. Let me know if you can't use 4 and I'll see if I can dig up a 3.5 version. Basically you need to create a class structure to map the JSON to a Class. I created the Route and RouteSummary classes for you. I left route_geometry and route_instructions as objects. You should create class definitions for each but this should get you started.
Imports System.IO
Imports System.Runtime.Serialization.Json
Imports System.Runtime.Serialization
<DataContract(Namespace:="")> _
Public Class Route
<DataMember(Name:="version")>
Public Property version As Double
<DataMember(Name:="status")>
Public Property status As Double
<DataMember(Name:="route_summary")>
Public Property route_summary As route_summary
<DataMember(Name:="route_geometry")>
Public Property route_geometry As Object()
<DataMember(Name:="route_instructions")>
Public Property route_instructions() As Object
End Class
<DataContract(Name:="route_summary", Namespace:="")> _
Public Class route_summary
<DataMember(Name:="total_distance")>
Public Property total_distance As Double
<DataMember(Name:="total_time")>
Public Property total_time As Double
<DataMember(Name:="start_point")>
Public Property start_point As Double
<DataMember(Name:="end_point")>
Public Property end_point As Double
End Class
Public Class Converter(Of t)
Public Function ReturnJSON(ByRef sreader As StreamReader) As t
If GetType(t).Equals(GetType(String)) Then
Dim result As Object = sreader.ReadToEnd.Replace("""", "")
Return result
Else
Dim ds As New DataContractJsonSerializer(GetType(t))
Dim result As t = DirectCast(ds.ReadObject(sreader.BaseStream), t)
ds = Nothing
Return result
End If
End Function
End Class
Sub Main()
Dim json As String = "{""version"":0.3, ""status"":0, ""route_summary"": { ""total_distance"":300, ""total_time"":14, ""start_point"":""43"", ""end_point"":""42"" }, ""route_geometry"":[[51.025421,18.647631],[51.026131,18.6471],[51.027802,18.645639]], ""route_instructions"": [[""Head northwest on 43"",88,0,4,""88 m"",""NW"",334.8],[""Continue on 42"",212,1,10,""0.2 km"",""NW"",331.1,""C"",356.3]]}"
Dim encoding As New System.Text.UTF8Encoding
Dim bytes() As Byte = encoding.GetBytes(json)
Using os As New MemoryStream
os.Write(bytes, 0, bytes.Length)
os.Position = 0
Using reader As New StreamReader(os)
Dim converter As New Converter(Of Route)
Dim output As Route
output = converter.ReturnJSON(reader)
'output contains data
End Using
End Using
End Sub
See this page for a detailed description of how to read the JSON data. http://www.json.org/

Related

How to convert a list of different data types into string in vb.net

I created a list using a class which has different data types. It is populated as follows:
[1/16/2015 10:30:14 PM] 241.167.2.72:5
[1/17/2015 11:30:06 PM] 100.133.2.55:6
[1/18/2015 12:30:33 PM] 206.140.3.10:7
Now I just want to display this in a textbox on a page. But get this:
ClientWebApp.DedicatedServerApi.Formatted_DDoS_SampleFlows
ClientWebApp.DedicatedServerApi.Formatted_DDoS_SampleFlows
ClientWebApp.DedicatedServerApi.Formatted_DDoS_SampleFlows
I'm using this line of code with the ToString()...but obviously it is not correct.
strSampleFlowLine = formattedDDoSSampleFlow.ToString() & vbCrLf & vbCrLf
Any Ideas?
The code (and classes) that attempts to populate the text box on the page:
Dim ddosDetailsInfoResult As New DedicatedServerApi.DDoSDetailsInfoResult
Dim formattedDDoSSampleFlow As New DedicatedServerApi.Formatted_DDoS_SampleFlows
' Create a list field - an array of the DDoS sample flows.
Dim formattedDDoSSampleFlowsList As New List(Of DedicatedServerApi.Formatted_DDoS_SampleFlows)
If ddosDetailsInfoResult.DDoS_Details.Formattted_DDoS_SampleFlows_List.Count > 0 Then
' Note: had to add .ToList() as it was giving a syntax error: cannot be converted to a 1-dimensional array.
' Does not make sense as the "Formattted_DDoS_SampleFlows_List" variable is defined exactly like the receiving field.
formattedDDoSSampleFlowsList = ddosDetailsInfoResult.DDoS_Details.Formattted_DDoS_SampleFlows_List.ToList()
For Each formattedDDoSSampleFlow In formattedDDoSSampleFlowsList
' Example of entry in the list: [1/16/2015 10:30:14 PM] 241.167.2.72:5
strSampleFlowLine = formattedDDoSSampleFlow.ToString() & vbCrLf & vbCrLf
' Build the sample flow list textbox.
txtGDHDApiSampleFlowList.Text = txtGDHDApiSampleFlowList.Text & strSampleFlowLine
Next
Else
'An empty list.
txtGDHDApiSampleFlowList.Text = ""
End If
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Holds formatted DDoS sample flows settings.
' [1/16/2015 10:30:14 PM] 241.167.2.72:5
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Public Class Formatted_DDoS_SampleFlows
Private _open_bracket_delimeter As String
Public Property Open_Bracket_Delimeter() As String
Get
Return _open_bracket_delimeter
End Get
Set(value As String)
_open_bracket_delimeter = value
End Set
End Property
Private _time_received As Date
Public Property Time_Received() As Date
Get
Return _time_received
End Get
Set(value As Date)
_time_received = value
End Set
End Property
Private _close_backet_and_space_delimeter As String
Public Property Close_Bracket_And_Space_Delimeter() As String
Get
Return _close_backet_and_space_delimeter
End Get
Set(value As String)
_close_backet_and_space_delimeter = value
End Set
End Property
Private _source_ip As String
Public Property Source_IP() As String
Get
Return _source_ip
End Get
Set(value As String)
_source_ip = value
End Set
End Property
Private _colon1_delimeter As String
Public Property Colon1_Delimeter() As String
Get
Return _colon1_delimeter
End Get
Set(value As String)
_colon1_delimeter = value
End Set
End Property
Private _source_port As String
Public Property Source_Port() As String
Get
Return _source_port
End Get
Set(value As String)
_source_port = value
End Set
End Property
End Class
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Holds DDoSDetailsInfoResult.
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Public Class DDoSDetailsInfoResult
Private _message As String
Public Property Message() As String
Get
Return _message
End Get
Set(value As String)
_message = value
End Set
End Property
Private _ddos_details As New DDoS_Details
Public Property DDoS_Details() As DDoS_Details
Get
Return _ddos_details
End Get
Set(ByVal value As DDoS_Details)
_ddos_details = value
End Set
End Property
End Class
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' Holds DDoS details.
'+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Public Class DDoS_Details
Private _formatted_ddos_sampleflows_list As New List(Of Formatted_DDoS_SampleFlows)
Public Property Formattted_DDoS_SampleFlows_List() As List(Of Formatted_DDoS_SampleFlows)
Get
Return _formatted_ddos_sampleflows_list
End Get
Set(ByVal value As List(Of Formatted_DDoS_SampleFlows))
_formatted_ddos_sampleflows_list = value
End Set
End Property
End Class
Your Formatted_DDoS_SampleFlows class need to define what ToString does.
Something like:
Class Formatted_DDoS_SampleFlows
Public Overrides ToString() As String
Return _open_bracket_delimeter & _time_received.ToString() & _close_backet_and_space_delimeter & _source_ip
End Sub
End Class
use CDate to convert the original value into a Date. The ToString is being operated on the entire class. Then use String.Format to output the date into the correct format you want. Should look something closer to this:
strSampleFlowLine = String.Format("MM/dd/yyyy", CDate(formattedDDoSSampleFlow.something)) & vbCrLf & vbCrLf

VB: Problems with using variable from another class + what to do with not used interface`s functions

I have a problem with getting variable from another class and cannot understand what to do with interface`s functions which have already existed in another class.
What I have:
Form where clicking on a button I should see reversed string:
(I want to call pooraja.StringReverse which is below)
Private Sub btnPoora1_Click(sender As System.Object, e As System.EventArgs) _
Handles btnPoora1.Click
'Dim text As PrjTekstiPooraja.ITeisendused = New PrjTekstiPooraja.CtekstiPooraja
Dim text As PrjTekstiPooraja.ITeisendused = New PrjTekstiPooraja.CtekstiPooraja
Dim pooraja As PrjTekstiPooraja.ITeisendused = New PrjTekstiPooraja.CAlgrotimilinePooraja
text.strText = txtSisendTekst.Text
txtValjundTekst1.Text = pooraja.stringReverse
text.intStart = 1
text.intEnd = Len(txtSisendTekst.Text)
ascFSymbol.Text = text.ascFirstSymbol
ascLSymbol.Text = text.ascLastSymbol()
End Sub
CtekstiPooraja:
(Thiss class will be used to store data.Under data I mean strPooratavText. Data will be used in CAlgoritmilinePooraja)
Public Class CtekstiPooraja
Implements ITeisendused
Public intStartSymbol As Integer
Public intEndSymbol As Integer
Public strPooratavText As String
Private Property intEnd As Integer Implements ITeisendused.intEnd
Get
Return intEndSymbol
End Get
Set(ByVal value As Integer)
intEndSymbol = value
End Set
End Property
Private Property intStart As Integer Implements ITeisendused.intStart
Get
Return intStartSymbol
End Get
Set(ByVal value As Integer)
intStartSymbol = value
End Set
End Property
Public Function pooraText() As String Implements ITeisendused.pooraText
Return StrReverse(strPooratavText)
End Function
Public Property strText As String Implements ITeisendused.strText
Get
Return strPooratavText
End Get
Set(ByVal value As String)
strPooratavText = value
MsgBox(strPooratavText)
End Set
End Property
Public Sub teisendaText(ByRef strSisendText As String) Implements ITeisendused.teisendaText
strPooratavText = StrReverse(strSisendText)
End Sub
Public Function ascFirstSymbol() As String Implements ITeisendused.ascFirstSymbol
Return Asc(GetChar(strPooratavText, intStartSymbol))
End Function
Public Function ascLastSymbol() As String Implements ITeisendused.ascLastSymbol
Return Asc(GetChar(strPooratavText, intEndSymbol))
End Function
Public Function stringReverse() As String Implements ITeisendused.stringReverse
Return Nothing
End Function
End Class
CAlgrotimilinePooraja:
(This class will be called by form button. There I need to use stringReverse function with data from CtekstiPooraja. The problem is that everywhere is used the same interface and there is some functions and procedures from this interface which isnt necessary. I dont know what value should return these unused functions/procedures. Just using "return Nothing or return 0/ "" is bad idea, may be there is possible somehow referenceto to CTekstiPooraja functions/procedures variables")
Public Class CAlgrotimilinePooraja
Implements ITeisendused
Private x As New PrjTekstiPooraja.CtekstiPooraja
Public Function stringReverse() As String Implements ITeisendused.stringReverse
MsgBox(x.strPooratavText)
Dim i As Integer = 0
Dim j As Integer
Dim characters(j) As Char
Dim newString(j) As Char
characters = x.strPooratavText.ToCharArray()
newString = x.strPooratavText.ToCharArray()
Do While i <= j - 1
newString(i) = characters(j - 1)
newString(j - 1) = characters(i)
i += 1
j -= 1
Loop
Return newString
End Function
Public Function ascFirstSymbol() As String Implements ITeisendused.ascFirstSymbol
Return x.ascFirstSymbol()
End Function
Public Function ascLastSymbol() As String Implements ITeisendused.ascLastSymbol
Return Nothing
End Function
Public Property intEnd As Integer Implements ITeisendused.intEnd
Get
Return x.intEndSymbol
End Get
Set(ByVal value As Integer)
End Set
End Property
Public Property intStart As Integer Implements ITeisendused.intStart
Get
Return x.intStartSymbol
End Get
Set(ByVal value As Integer)
End Set
End Property
Public Function pooraText() As String Implements ITeisendused.pooraText
Return x.pooraText()
End Function
Public Property strText As String Implements ITeisendused.strText
Get
Return x.strPooratavText
End Get
Set(ByVal value As String)
End Set
End Property
Public Sub teisendaText(ByRef strSisendText As String) Implements ITeisendused.teisendaText
x.strPooratavText = StrReverse(strSisendText)
End Sub
End Class
MyInterface:
Public Interface ITeisendused
Property intStart As Integer
Property intEnd As Integer
Property strText As String
Function pooraText() As String
Function ascFirstSymbol() As String
Function ascLastSymbol() As String
Function stringReverse() As String
Sub teisendaText(ByRef strSisendText As String)
End Interface
I cannot understand how to get variable strPooratavText from CTekstiPooraja to CAlgrotimilinePooraja. Usually that instancewhich I create worked but not now. And I cannot understand what to do with already existed function and procedures in CAlgoritmilinePooraja when the same function and procedures has in another class. Maybe, it is possible to reference them somehow to existed functions/procedures in CTekstiPooraja? Could you explain me how to id, already tired to surf Internet to find a solution for it, have already try a lot.
Well, I think you have a fundamental problem with understanding interfaces. They describe data and behavior, it should be extremely rare to want to implement part of an interface.
That said, if you do want to implement part of an interface, instead of returning bogus data, throw an exception for behavior you don't implement.
Your specific problem is that CAlgoritmilinePooraja works on an instance of CtekstiPooraja, but it creates a new instance instead of using an existing one. Add
Sub New(incomingX as CtekstiPooraja)
x = incomingX
End Sub
to CAlgoritmilinePooraja. And then in your event, use....
Dim text As PrjTekstiPooraja.CtekstiPooraja = New PrjTekstiPooraja.CtekstiPooraja
text.strText = txtSisendTekst.Text
Dim pooraja As PrjTekstiPooraja.ITeisendused = New PrjTekstiPooraja.CAlgrotimilinePooraja(text)
That is the minimum change to your design that gets what you want to happen to happen but it's problably not what you should do. Other than implementing strReverse, CtekstiPooraja seems to be what you want, CAlgrotimilinePooraja looks to do just one thing, the actual string reversal.
I would move the implementation of strReverse into CtekstiPooraja, and then eliminate CAlgrotimilinePooraja.
PS I would try to stick to English for class names as well as functions and variables.

Error says x is not a member of y, but it is

I have a sp that I added to my linq designer, which generated the result class:
Partial Public Class web_GetTweetsByUserIDResult
Private _userid As Integer
Private _tweetid As Integer
Private _TweeterFeed As String
Public Sub New()
MyBase.New
End Sub
<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_userid", DbType:="Int NOT NULL")> _
Public Property userid() As Integer
Get
Return Me._userid
End Get
Set
If ((Me._userid = value) _
= false) Then
Me._userid = value
End If
End Set
End Property
<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_tweetid", DbType:="Int NOT NULL")> _
Public Property tweetid() As Integer
Get
Return Me._tweetid
End Get
Set
If ((Me._tweetid = value) _
= false) Then
Me._tweetid = value
End If
End Set
End Property
<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_TweeterFeed", DbType:="NVarChar(100)")> _
Public Property TweeterFeed() As String
Get
Return Me._TweeterFeed
End Get
Set
If (String.Equals(Me._TweeterFeed, value) = false) Then
Me._TweeterFeed = value
End If
End Set
End Property
End Class
However, in this one section of code where I am trying to use the "TweeterFeed" member of the result class I am getting the error, "Error 4 'TweeterFeed' is not a member of 'System.Data.Linq.ISingleResult(Of web_GetTweetsByUserIDResult)'."
My code in this section is, :
<WebMethod()> _
Public Function GetTweetsByUserID(ByVal userID As Integer) As List(Of SimpleTweet)
Dim result As New List(Of SimpleTweet)
Dim urlTwitter As String = "https://api.twitter.com/1/statuses/user_timeline.xml?include_entities=true&include_rts=true&screen_name={0}&count=20"
Dim lq As New lqDFDataContext
Dim var = lq.web_GetTweetsByUserID(userID).ToList()
If Not var Is Nothing Then
For Each twitterfeed In var
Dim listURL As String = String.Format(urlTwitter, var.TweeterFeed)
Dim tweetXML As XmlDocument = utils.GetXMLForURL(listURL)
Dim tweetnodelist As XmlNodeList = tweetXML.ChildNodes(1).ChildNodes
For Each node As XmlNode In tweetnodelist
Dim tweet As New SimpleTweet
tweet.CreatedAt = node.SelectSingleNode("created_at").InnerText
tweet.HTMLText = utils.ReturnTextWithHRefLink(node.SelectSingleNode("text").InnerText)
tweet.ID = node.SelectSingleNode("id").InnerText
tweet.Name = node.SelectSingleNode("user/name").InnerText
tweet.ScreenName = node.SelectSingleNode("user/screen_name").InnerText
tweet.Text = node.SelectSingleNode("text").InnerText
tweet.UserID = node.SelectSingleNode("user/id").InnerText
tweet.ProfileImageURL = node.SelectSingleNode("user/profile_image_url_https").InnerText
result.Add(tweet)
Next
Next
End If
Return result
End Function
Does anyone have any idea what is going on? As far as I see "TweeterFeed" is clearly a member of the class, I can't figure out why I would be getting this error.
You're using var.TweeterFeed when you should be using twitterFeed.TweeterFeed. twitterFeed is a result extracted from var which is a sequence of results.
Using a more descriptive variable name than var would probably have made this clearer to you :)
I have this class
Public Class Tamano
Private pWidth As Integer
Private pHeight As Integer
Public Property Width As Integer
Public Property Height As Integer
End Class
I got the compilation error message 'Height' is not a member of 'TamaƱo' in IIS
To fix it, add Set and Get to the properties and it compiles.
Public Class Tamano
Private pWidth As Integer
Private pHeight As Integer
Public Property Width As Integer
Get
Return pWidth
End Get
Set(value As Integer)
pWidth = value
End Set
End Property
Public Property Height As Integer
Get
Return pHeight
End Get
Set(value As Integer)
pHeight = value
End Set
End Property
End Class
This might not be directly related to your question but It might help someone else.

Getting a NullReferenceException when adding something to a list

I get a null reference exception when I try to use this webservice I'm working on. I have two fields in the object ipadarticle called fullname and tags, which are declared to be lists, so that ipadarticle can return multiple tags and authors. The null reference exception points to
ipadarticle2.FullName.Add(a_var.firstname + " " + a_var.lastname)
ipadarticle2.Tag.Add(a_var.tagtext)
I'm pretty new to vb programming, so I'm not really to sure what is causing this. To clarify, what is going on is that this stored procedure is fetching entries from a db, which has a list of articles with -among other things- tags and authors associated with it. Since articles have multiple tags and authors there are multiple entries for each article. When I return the info in the web service I am trying to make it so that only one ipadarticle object is returned for reach article, and then that contains a list of the multiple tags and authors associated with each article. I'm having a headache trying to figure this out.
Dim lq As New lqDFDataContext
Dim var = lq.mobile_IpadGetSavedArticlesAR(simpuser.UserID, tempParamKW(0), tempParamKW(1), tempParamKW(2), tempParamKW(3), tempParamKW(4), pageNum, pageLen)
Dim ipadarticle2 As New ipadArticle()
For Each a_var In var
If a_var.articleID <> temp Then
If flag = 0 Then
result.add(ipadarticle2)
Dim ipadarticle1 As New ipadArticle()
ipadarticle2 = ipadarticle1
End If
ipadarticle2.ArticleID = a_var.articleID
ipadarticle2.PublishedOn = a_var.publicationdate
ipadarticle2.Title = a_var.title
ipadarticle2.MedAbbr = a_var.medabbr.Replace(" ", "-").ToLower()
ipadarticle2.FullName.Add(a_var.firstname + " " + a_var.lastname)
ipadarticle2.Tag.Add(a_var.tagtext)
flag = 1
Else
ipadarticle2.Tag.Add(a_var.tagtext)
ipadarticle2.FullName.Add(a_var.firstname + " " + a_var.lastname)
flag = 0
End If
temp = a_var.articleID
Next
End If
Return result
ipadArticle class:
Imports Microsoft.VisualBasic
Public Class ipadArticle
Inherits SimpleObject
Public Sub New()
End Sub
Private _ArticleID As Integer
Public Property ArticleID() As Integer
Get
Return _ArticleID
End Get
Set(ByVal value As Integer)
_ArticleID = value
End Set
End Property
Private _Title As String
Public Property Title() As String
Get
Return _Title
End Get
Set(ByVal value As String)
_Title = value
End Set
End Property
Private _PublishedOn As String
Public Property PublishedOn() As String
Get
Return _PublishedOn
End Get
Set(ByVal value As String)
_PublishedOn = value
End Set
End Property
Private _MedAbbr As String
Public Property MedAbbr() As String
Get
Return _MedAbbr
End Get
Set(ByVal value As String)
_MedAbbr = value
End Set
End Property
Private _Tag As List(Of String)
Public Property Tag() As List(Of String)
Get
Return _Tag
End Get
Set(ByVal value As List(Of String))
_Tag = value
End Set
End Property
Private _FullName As List(Of String)
Public Property FullName() As List(Of String)
Get
Return _FullName
End Get
Set(ByVal value As List(Of String))
_FullName = value
End Set
End Property
End Class
The most likely cause is that the objects FullName and Tag have not been created (are Nothing) in ipadarticle2. These should most likely be created as new objects in the class constructor.
EDIT:
Based on the posted class, the above assumption was correct: FullName and Tag are defined as List(Of String), but the backing members are never created.
This can be fixed in a couple of ways:
1) Instantiate the backing member variables directly in their definition, i.e.:
Private _FullName As New List(Of String)
2) Instantiate the backing member variables in the constructor:
Public Sub New()
_FullName = New List(Of String)
_Tag = New List(Of String)
End Sub
3) Instantiate the backing member variable in the getter if it is nothing:
Public Property Tag() As List(Of String)
Get
If _Tag Is Nothing Then
_Tag = New List(Of String)
End If
Return _Tag
End Get
Basically, any variable types other than simple data types must be instantiated before they can be used (unless you test them for Nothingness).

Deseralizing XML into simple .NET class, cannot populate property from root node attribute

I have a simple class that I trying to populate from an XML document.
The XML file has an attribute called TrackingID in the root node which I would like to get as a property. For some reason, when I deseralize the class, the TrackingID is null. Everything else populates fine. I have tried various attributes on the TrackingID property with no luck.
Any ideas?
Code:
Dim faultXML As String = "<?xml version='1.0' encoding='UTF-8' ?>"
faultXML += "<myxmlns:Fault xmlns:myxmlns='http://somename/space' xmlns:myxmlns_base=http://somename/base' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://somename/space
faultXML += "myxmlns_102809.xsd http://idealliance.org/maildat/Specs/md091/myxmlns70C/base myxmlns_base_102809.xsd' myxmlns:TrackingID='160217057912'>"
faultXML += "<myxmlns:FaultCode>500</myxmlns:FaultCode>"
faultXML += "<myxmlns:FaultDescription>Some Description.</myxmlns:FaultDescription>"
faultXML += "</myxmlns:Fault>"
Dim fault As WebServiceFault
Dim Serializer As New XmlSerializer(GetType(WebServiceFault))
Using sr As New System.IO.StringReader(faultXML)
fault = DirectCast(Serializer.Deserialize(sr), WebServiceFault)
End Using
Class:
Imports System.Xml.Serialization
<System.SerializableAttribute(), _
System.Xml.Serialization.XmlTypeAttribute(AnonymousType:=True, [Namespace]:="http://somename/space"), _
System.Xml.Serialization.XmlRootAttribute([ElementName]:="Fault", [Namespace]:="http://somename/space", IsNullable:=False)> _
Public Class WebServiceFault
Private faultCodeField As String
Private faultDescriptionField As String
Private trackingIDField As String
Public Property FaultCode() As String
Get
Return Me.faultCodeField
End Get
Set(ByVal value As String)
Me.faultCodeField = value
End Set
End Property
Public Property FaultDescription() As String
Get
Return Me.faultDescriptionField
End Get
Set(ByVal value As String)
Me.faultDescriptionField = value
End Set
End Property
Public Property TrackingID() As String
Get
Return Me.trackingIDField
End Get
Set(ByVal value As String)
Me.trackingIDField = value
End Set
End Property
End Class
I was able to find an answer. Adding the below attribute solved my problem.
<System.Xml.Serialization.XmlAttributeAttribute(Form:=System.Xml.Schema.XmlSchemaForm.Qualified)> _
Public Property TrackingID() As String
Get
Return Me.trackingIDField
End Get
Set(ByVal value As String)
Me.trackingIDField = value
End Set
End Property