Skip to main content

Microsoft Silverlight

Answered Question How do I use Linq to convert xml from a webservice to a custom class?RSS Feed

(0)

jvcoacharchbold
jvcoacha...

Member

Member

2 points

21 Posts

How do I use Linq to convert xml from a webservice to a custom class?

I have figured out how to create an webservice that returns an xml representation of a dataset.  The xml in this case is for a dataset of "Users" with 2 fields:

UserName

Password

 

What I can't figure out how to do is to take this in my Silverlight 2 app and take the "e.Result" and using Linq, populate a collection of "User".

 I am working on this in VB.

 How do I go about this?

Are there any "Imports ...." that I need to do?

 Thanks for any help,

Shawn Ramirez

prujohn
prujohn

Contributor

Contributor

3567 points

703 Posts

Re: How do I use Linq to convert xml from a webservice to a custom class?

You'll need System.Linq and System.Xml.Linq;

Here I am converting XML into collections of class FileItemInfo and FileView.  Sorry this is in c#, but you can run it through any number of available converters if you need to:

                XElement file = XElement.Load(new StringReader(e.FilesAndViewsXML));

                //convert the xml return into strongly typed objects
                var fileItemResultSet = from xq in file.DescendantsAndSelf("File")
                                        select new FileItemInfo()
                                        {
                                            FileID = new Guid(xq.Element("FileID").Value),
                                            FileName = xq.Element("FileName").Value,
                                            FileSize = Convert.ToInt32(xq.Element("FileSize").Value),
                                            Tags = xq.Element("Tags").Value,
                                            CreatedOn = DateTime.Parse(xq.Element("CreatedOn").Value),
                                            MimeType = xq.Element("MimeType").Value,
                                            LastModified = DateTime.Parse(xq.Element("LastModified").Value),
                                            LastAccessed = DateTime.Parse(xq.Element("LastAccessed").Value)
                                        };
                _fileItems = fileItemResultSet.ToList();

                var fileViewResultSet = from vq in file.DescendantsAndSelf("View")
                                        select new FileView()
                                        {
                                            ViewID = new Guid(vq.Element("ViewID").Value),
                                            FriendlyName = vq.Element("FriendlyName").Value,
                                            ViewQuery = vq.Element("ViewQuery").Value
                                        };
                _fileViews = fileViewResultSet.ToList();

 

jvcoacharchbold
jvcoacha...

Member

Member

2 points

21 Posts

Re: How do I use Linq to convert xml from a webservice to a custom class?

Thank you, you got me part way there.

Would you be so kind as to  point me to a c# -> vb.net converter that knows how to interpret Linq?

 

Thanks for your time.

prujohn
prujohn

Contributor

Contributor

3567 points

703 Posts

Re: How do I use Linq to convert xml from a webservice to a custom class?

Hm I looked around a bit and converts supporting Linq seem to be a rarity. Perhaps someone on the forums here with VB skills will be kind enough to convert the example for you, or provide their own.

jvcoacharchbold
jvcoacha...

Member

Member

2 points

21 Posts

Re: How do I use Linq to convert xml from a webservice to a custom class?

 

prujohn:
var fileItemResultSet = from xq in file.DescendantsAndSelf("File")

Thanks for the code.  I finally found a C#  => VB.Net converter that does Linq

It gave me the code but I get an error when trying to build that says

  Name 'xq' is not declared.   

 

So what is 'xq'

 

Thanks for your help.

Shawn

prujohn
prujohn

Contributor

Contributor

3567 points

703 Posts

Re: How do I use Linq to convert xml from a webservice to a custom class?

Can you post me your converted code, and I'll see if I can fix it up.

jvcoacharchbold
jvcoacha...

Member

Member

2 points

21 Posts

Answered Question

Re: How do I use Linq to convert xml from a webservice to a custom class?

I finally figured it out:

 

        Dim qryUsers = _
         From p In xdoc.Elements("Users").Elements("User") _
         Select New User With {.UserID = p.Element("username").Value, .Password = p.Element("password").Value}
        

This will do the trick.

Thanks for your time, I am greatful.

Shawn Ramirez

Elango.ka
Elango.ka

Participant

Participant

816 points

146 Posts

Re: How do I use Linq to convert xml from a webservice to a custom class?

 Hi, the below codes are may be help you to.

 Here im also put in how to assign your list data to listbox.

In your webservice(asmx) file have a webmethod return to string at below format,

<WebMethod()> _
Public Function getData(ByVal CNo As string) As String
        Dim busobj As New BusinessLayer
        Dim ds As New DataSet
        busobj.GetDataset(CNo)
        Dim dt As DataTable
        dt = ds.Tables(0)
        Dim doc As XDocument = New XDocument(New XDeclaration("1,0", Nothing, Nothing), _
        New XElement("EmployeeData", From c In dt Select New XElement("Employee", _
        New XElement("EmpNo", c.Item(0)),  _
        New XElement("EmpName", c.Item(1)))))
        getData = doc.ToString
End Function


Now you refer to your silverlight application to your webservice from localhost or where you have.

Page.xaml.vb code:

Imports System.Xml
Imports System.Xml.Linq

Public Sub LoadEmployee(Byval companyNo as integer)
        Dim obj As New WebRef.WebRefSoapClient  'webRef is your webservice name in SL application
        obj.getDataAsync(companyNo)
        AddHandler obj.getDataCompleted, AddressOf Me.obj_getDataCompleted
End Sub

Private Sub obj_getDataCompleted(ByVal sender As Object, ByVal e As WebRef.getDataCompleteddEventArgs)
        If e.Error Is Nothing Then
            Dim doc As XDocument = XDocument.Parse(e.Result)

            Dim c = From customer In doc.Descendants("Employee") Select New EmployeeData( _
                  customer.Element("EmpNo"), customer.Element("EmpName"))
            Me.lstEmployee.ItemsSource = c
        End If
End Sub


EmployeeData class is;

Public Class EmployeeData
    Private eEmpNo As Integer
    Private eEmpName As String
    Public Sub New(ByVal EmpNo As Integer, ByVal EmpName As String)
        Me.eEmpNo = EmpNo
        Me.eEmpName = EmpName
    End Sub
    Public Property EmpNo() As Integer
        Get
            Return eEmpNo
        End Get
        Set(ByVal value As Integer)
            eEmpNo = value
        End Set
    End Property
    Public Property EmpName() As String
        Get
            Return eEmpName
        End Get
        Set(ByVal value As String)
            eEmpName = value
        End Set
    End Property
End Class

And Finally, your SL listbox control can bind the below xaml;
<ListBox x:Name="lstEmployee" Height="35" Width="170" VerticalAlignment="Top" Margin="20,0,0,0" HorizontalAlignment="Left">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding EmpName}" FontSize="10" VerticalAlignment="Center" Foreground="Black"></TextBlock>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
</ListBox>

 

Thanks 

Elango

prabakaran.sr
prabakar...

Member

Member

14 points

7 Posts

Re: How do I use Linq to convert xml from a webservice to a Datagrid?

Hi Elango,

Thanks for the information. Can you please let me know how to bing xml from a webservice to a datagrid. Please let me know some sample.

Thanks In Advance,

Prabakaran

Elango.ka
Elango.ka

Participant

Participant

816 points

146 Posts

Re: Re: How do I use Linq to convert xml from a webservice to a Datagrid?

 Hi Prabakaran,

The SL datagrid binding is same as listbox bind. And xaml code is just change with your datas. (if autogeneratecolumns=false) . For ex,

<data:DataGrid Height="300" Width="390" HorizontalAlignment="Left" x:Name="grdEmployee" AutoGenerateColumns="False" HeadersVisibility="Column">
                <data:DataGrid.Columns>
                    <data:DataGridTemplateColumn Header="Emp No" Width="80">
                        <data:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                   <TextBlock Text="{Binding EmpNo}" TextAlignment="Left"></TextBlock>
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellTemplate>
                    </data:DataGridTemplateColumn>
                    <data:DataGridTemplateColumn Header="Employee Name" Width="70">
                        <data:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding EmployeeName}" TextAlignment="Left"></TextBlock>
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellTemplate>
                    </data:DataGridTemplateColumn>                  
                  </data:DataGrid.Columns>               
</data:DataGrid>

 

Thanks

 

prabakaran.sr
prabakar...

Member

Member

14 points

7 Posts

Re: Re: How do I use Linq to convert xml from a webservice to a Datagrid?

Thank you Mr. Elango. for your information.

 How to bind webservice return value to datagrid in silverlight. The webservice returns a XML string. Also i know the webservice structure. Now, Wen i call the webservice it returns some value as string. Please guide me how to bind the values to a datagrid. in vb.net

 Thanks For the information Again.

Regards,

Prabakaran

Elango.ka
Elango.ka

Participant

Participant

816 points

146 Posts

Re: Re: Re: How do I use Linq to convert xml from a webservice to a Datagrid?

Hi,

In your webservice(asmx) file have a webmethod return to string at below format,

<WebMethod()> _
Public Function getData(ByVal CNo As string) As String
        Dim busobj As New BusinessLayer
        Dim ds As New DataSet
        busobj.GetDataset(CNo)
        Dim dt As DataTable
        dt = ds.Tables(0)
        Dim doc As XDocument = New XDocument(New XDeclaration("1,0", Nothing, Nothing), _
        New XElement("EmployeeData", From c In dt Select New XElement("Employee", _
        New XElement("EmpNo", c.Item(0)),  _
        New XElement("EmpName", c.Item(1)))))
        getData = doc.ToString
End Function

So, Your data now in xml string

<EmployeeData><Employee><EmpNo>101</EmpNo><EmpName>Emp1</EmpName></Employee>....... </EmployeeData>

There we see the page.xaml code behind, 


Page.xaml.vb code:

Imports System.Xml
Imports System.Xml.Linq

 Public Sub New()
    LoadEmployee() ' call the function loading employee      
 End Sub


Public Sub LoadEmployee(Byval companyNo as integer)
        Dim obj As New WebRef.WebRefSoapClient  ' webRef is your webservice name in SL application
        obj.getDataAsync(companyNo)
        AddHandler obj.getDataCompleted, AddressOf Me.obj_getDataCompleted
End Sub

Now the function handler is return to your xml data. Therefore, "e.Result" is your XML string,

Private Sub obj_getDataCompleted(ByVal sender As Object, ByVal e As WebRef.getDataCompleteddEventArgs)
        If e.Error Is Nothing Then
           

            Dim doc As XDocument = XDocument.Parse(e.Result)

            Dim c = From customer In doc.Descendants("Employee") Select New EmployeeData( _
                  customer.Element("EmpNo"), customer.Element("EmpName"))  ' convert xml to your list data
            Me.grdEmployee.ItemsSource = c
       

         End If
End Sub

 

Thanks

prabakaran.sr
prabakar...

Member

Member

14 points

7 Posts

Re: Re: Re: How do I use Linq to convert xml from a webservice to a Datagrid?

Hi Elango,

This is my vb code. Here i am getting some problem in this code. Please let me know some suggestions abt this.

Imports System

Imports System.Collections

Imports System.Linq

Imports System.Net

Imports System.Windows

Imports System.Windows.Controls

Imports System.Windows.Documents

Imports System.Windows.Input

Imports System.Windows.Media

Imports System.Windows.Media.Animation

Imports System.Windows.Shapes

Imports System.Windows.Browser

Imports System.Xml

Imports System.Xml.Linq

Imports System.IO

Imports System.ServiceModel.Syndication

Imports TestXML.com.bodurov

Imports System.Windows.Data

=================================================== 

Private Sub BtnTest_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Dim WebClient As New WebClient

AddHandler WebClient.DownloadStringCompleted, AddressOf BindWSXml2Grid

WebClient.DownloadStringAsync(New Uri("sampleXML.xml", UriKind.RelativeOrAbsolute))

End Sub

=================================================== 

Public Sub BindWSXml2Grid(ByVal sender As Object, ByVal e As DownloadStringCompletedEventArgs)

If IsNothing(e.Error) Then

'Add Column To DataGrid

Dim TxtTitleName As New DataGridTextColumn

TxtTitleName.Header = "TITLE"

TxtTitleName.Binding = New Binding("title")

'TxtTitleName.Width.Auto

Me.dg.Columns.Add(TxtTitleName)

Dim TxtAuthorColumn As New DataGridTextColumn

TxtAuthorColumn.Header = "AUTHOR"

TxtAuthorColumn.Binding = New Binding("author")

Me.dg.Columns.Add(TxtAuthorColumn)

Dim TxtISBNColumn As New DataGridTextColumn

TxtISBNColumn.Header = "BOOK"

TxtISBNColumn.Binding = New Binding("BOOK")Me.dg.Columns.Add(TxtISBNColumn)

dg.ItemsSource = GenerateData(e.Result).ToDataSource

End If

End Sub

=================================================== 

Public Function GenerateData(ByVal ReturnXml As String) As IEnumerable(Of IDictionary)

Dim list As New List(Of IDictionary)()Dim XDoc As XDocument = New XDocument

XDoc = XDocument.Parse(ReturnXml)

'list = XDoc.Descendants("Book")

Dim abc As XElement

Dim title As String

Dim author As String

For i = 0 To XDoc.Descendants("Book").Count - 1

Dim dict As IDictionary = New Dictionary(Of String, Object)()

abc = (XDoc.Descendants("Book")).ElementAt(i)

title = abc.Document.Descendants("title").Value

author = abc.Document.Descendants("author").Value

dict.Add(abc.LastAttribute.ToString, abc.Value)

list.Add(dict)

Next

Return list

End Function

===================================================

Add a File as DataSourceCreator.vb

 ===================================================

Imports System

Imports System.Collections

Imports System.Collections.Generic

Imports System.Reflection

Imports System.Reflection.Emit

Imports System.Text.RegularExpressions

Imports System.Runtime.CompilerServices

Namespace com.bodurov

Public Module DataSourceCreator

Private ReadOnly PropertNameRegex As New Regex("^[A-Za-z]+[A-Za-z1-9_]*$", RegexOptions.Singleline)

<Extension()> _

Public Function ToDataSource(ByVal list As IEnumerable(Of IDictionary)) As IEnumerable

Dim firstDict As IDictionary = Nothing

Dim hasData As Boolean = False

For Each currentDict As IDictionary In list

hasData = True

firstDict = currentDict

Exit For

Next

If Not hasData Then

Return New Object() {}

End If

If firstDict Is Nothing Then

Throw New ArgumentException("IDictionary entry cannot be null")

End If

Dim objectType As Type = Nothing

Dim tb As TypeBuilder = GetTypeBuilder(list.GetHashCode())

Dim constructor As ConstructorBuilder = tb.DefineDefaultConstructor(MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.RTSpecialName)

For Each pair As DictionaryEntry In firstDict

If PropertNameRegex.IsMatch(Convert.ToString(pair.Key), 0) Then

Dim type As Type

If pair.Value Is Nothing Then

type = GetType(Object)

Else

type = pair.Value.[GetType]()

End If

CreateProperty(tb, Convert.ToString(pair.Key), type)

Else

Throw New ArgumentException("Each key of IDictionary must be alphanumeric and start with character.")

End If

Next

objectType = tb.CreateType()

Return GenerateEnumerable(objectType, list, firstDict)

End Function

Private Function GenerateEnumerable(ByVal objectType As Type, ByVal list As IEnumerable(Of IDictionary), ByVal firstDict As IDictionary) As IEnumerable

Dim listType As Type = GetType(List(Of )).MakeGenericType(New Type() {objectType})

Dim listOfCustom As IList = Activator.CreateInstance(listType) For Each currentDict As IDictionary In list

If currentDict Is Nothing Then

Throw New ArgumentException("IDictionary entry cannot be null")

End If

Dim row As Object = Activator.CreateInstance(objectType) For Each pair As DictionaryEntry In firstDict

If currentDict.Contains(pair.Key) Then

Dim [property] As PropertyInfo = objectType.GetProperty(Convert.ToString(pair.Key)) [property].SetValue(row, Convert.ChangeType(currentDict(pair.Key), [property].PropertyType, Nothing), Nothing)

End If

Next

listType.GetMethod("Add").Invoke(listOfCustom, New Object() {row})

Next

Return TryCast(listOfCustom, IEnumerable)

End Function

Private Function GetTypeBuilder(ByVal code As Integer) As TypeBuilder

Dim an As New AssemblyName("TempAssembly" & code.ToString())

Dim assemblyBuilder As AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run)

Dim moduleBuilder As ModuleBuilder = assemblyBuilder.DefineDynamicModule("MainModule")

Dim tb As TypeBuilder = moduleBuilder.DefineType("TempType" & code.ToString(), TypeAttributes.[Public] Or TypeAttributes.[Class] Or TypeAttributes.AutoClass Or TypeAttributes.AnsiClass Or TypeAttributes.BeforeFieldInit Or TypeAttributes.AutoLayout, GetType(Object)) Return tb

End Function

Private Sub CreateProperty(ByVal tb As TypeBuilder, ByVal propertyName As String, ByVal propertyType As Type)Dim fieldBuilder As FieldBuilder = tb.DefineField("_" & propertyName, propertyType, FieldAttributes.[Private])

 

Dim propertyBuilder As PropertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, Nothing)

Dim getPropMthdBldr As MethodBuilder = tb.DefineMethod("get_" & propertyName, MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, propertyType, Type.EmptyTypes)Dim getIL As ILGenerator = getPropMthdBldr.GetILGenerator()

getIL.Emit(OpCodes.Ldarg_0)

getIL.Emit(OpCodes.Ldfld, fieldBuilder)

getIL.Emit(OpCodes.Ret)

Dim setPropMthdBldr As MethodBuilder = tb.DefineMethod("set_" & propertyName, MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, Nothing, New Type() {propertyType})Dim setIL As ILGenerator = setPropMthdBldr.GetILGenerator()

setIL.Emit(OpCodes.Ldarg_0)

setIL.Emit(OpCodes.Ldarg_1)

setIL.Emit(OpCodes.Stfld, fieldBuilder)

setIL.Emit(OpCodes.Ret)

propertyBuilder.SetGetMethod(getPropMthdBldr)

propertyBuilder.SetSetMethod(setPropMthdBldr)

End Sub

End Module

End Namespace

===================================================

Elango.ka
Elango.ka

Participant

Participant

816 points

146 Posts

Re: Re: Re: Re: How do I use Linq to convert xml from a webservice to a Datagrid?

 Hi,


Private Sub BtnTest_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    Dim WebClient As New WebClient
    WebClient.DownloadStringAsync(New Uri("sampleXML.xml", UriKind.RelativeOrAbsolute))
    AddHandler WebClient.DownloadStringCompleted, AddressOf BindWSXml2Grid
End Sub

Why you are here want to New uri, i thought you were create one xml file in your server side. We dont need to create a xml file.
For ex, your webservice function have a following way

<WebMethod()> _
Public Function DownloadString() As String
        Dim busobj As New BusinessLayer
        Dim ds As New DataSet
        busobj.GetDataset()
        Dim dt As DataTable
        dt = ds.Tables(0) ' here i have my exmaple, you ll used your datas
        Dim doc As XDocument = New XDocument(New XDeclaration("1,0", Nothing, Nothing), _
        New XElement("EmployeeData", From c In dt Select New XElement("Employee", _
        New XElement("EmpNo", c.Item(0)),  _
        New XElement("EmpName", c.Item(1))))) 'here c.item(0) means first column of datatable, and so on...
        getData = doc.ToString
End Function

So, this DownloadString is return a string. Now we look at your code,

Private Sub BtnTest_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    Dim WebClient As New WebClient
    WebClient.DownloadStringAsync() 'no need xml file download, becoz this function return a xml string
    AddHandler WebClient.DownloadStringCompleted, AddressOf BindWSXml2Grid
End Sub

Then, BindWSXml2Grid function,

Public Sub BindWSXml2Grid(ByVal sender As Object, ByVal e As DownloadStringCompletedEventArgs)

If IsNothing(e.Error) Then
    ' here you are dynamically create a datagrid, just your datagrid design with xaml code. my above posts are explained that
       Dim doc As XDocument = XDocument.Parse(e.Result)

           Dim c = From customer In doc.Descendants("Employee") Select New EmployeeData( _
                  customer.Element("EmpNo"), customer.Element("EmpName"))  ' convert xml to your list data
            
       Me.grdEmployee.ItemsSource = c
End if

End sub

Here i have used my EmployeeData(above posts i have put this class file example also, you will used your data).


Thanks

prabakaran.sr
prabakar...

Member

Member

14 points

7 Posts

Re: Re: Re: Re: How do I use Linq to convert xml from a webservice to a Datagrid?

Hi,

I tried, what u said. But the EmployeeData class is not invoking. I am getting empty datagrid. Can you please post a sample EmployeeData class.

Elango.ka
Elango.ka

Participant

Participant

816 points

146 Posts

Re: Re: Re: Re: Re: How do I use Linq to convert xml from a webservice to a Datagrid?

Hi,

Make sure your class properties are correct, becoz xml is case sensitive.

<data:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                   <TextBlock Text="{Binding EmpName}" TextAlignment="Left"></TextBlock>
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellTemplate>

That class is,

Public Class EmployeeData
    Private eEmpNo As Integer
    Private eEmpName As String
    Public Sub New(ByVal EmpNo As Integer, ByVal EmpName As String)
        Me.eEmpNo = EmpNo
        Me.eEmpName = EmpName
    End Sub
    Public Property EmpNo() As Integer
        Get
            Return eEmpNo
        End Get
        Set(ByVal value As Integer)
            eEmpNo = value
        End Set
    End Property
    Public Property EmpName() As String
        Get
            Return eEmpName
        End Get
        Set(ByVal value As String)
            eEmpName = value
        End Set
    End Property
End Class

 

prabakaran.sr
prabakar...

Member

Member

14 points

7 Posts

Oracle application server - web service to silverlight + vb.net 2008

Hi,

Thanks for that information.

We have got the solutions and woks fine with your best suggestion.

Need Some other Information. Earlier we where using tomcat server for the webservice. Currently we are going to work with Oracle application server.

I am trying to asscess the the web serivce which hosted in oracle application server. Once i created a service Reference with ".wsdl" file to my project. After add the service Reference i have created a object to wsdl file. But, i am unable to get the webmethod to the service reference object. Also it say's error that client access policy.xml file has to be pasted in the root directly. But we dont know what is the root directory of the oracle application server.

Link for sample: http://www.longhorncorner.com/UploadFile/john_charles/WCFandOracle04112007032407AM/WCFandOracle.aspx

But couldnt get some idea. please help me on this.

Thanks in Advance,

Regards,

Prabakaran

  • Unanswered Question
  • Answered Question
  • Announcement
Microsoft Communities