Mehfuz's WebLog

Live crazy, think different!

Sponsors

News

Passionate about cutting edge technologies and facinated by the modern web and phone revolution.Currently working at Telerik Corporation, the leading .net component vendor.
Follow me


Articles


Projects

REST with LINQ to XML

With LINQ to XML, what I have learned so far, it's awesome, it is not only the first class concept of processing XML data, but also let you process a complex XML doc in the most simplest and readable way.

I have a project called, Linq.Flickr , and I often need to process  XML data for REST query.

To show a simple example of LINQ to XML, lets take a REST response from a Flickr method called flickr.people.getUploadStatus and see how it is processed.

<user id="12037949754@N01" ispro="1">  
<username>Bees</username> 
<bandwidth maxbytes="2147483648" maxkb="2097152" 
usedbytes="383724" usedkb="374" remainingbytes="2147099924" remainingkb="2096777" /> 
<filesize maxbytes="10485760" maxkb="10240" /> 
<sets created="27" remaining="lots" /> 
</user>

Before .net 3.5. it could have been done by GetElementyByTagName("users") - > inside the while loop getting the element, reading value, storing it in private variables , going to next sibling and repeat, if nested , then take the first child and so forth. But , in .net 3.5 using LINQ , the translation is not only just like XML itself, moreover , in XElement.Load , we can directly pass the REST query string.

So, Two, steps to do a REST with LINQ

  1. Build the URL and pass it to XElement.Load
  2. Parse the response and take necessary actions.

For example, for the above XML, I wrote something like below, in PhotoRepository.cs, that does a selective parsing.

try
{  
    XElement element = GetElement(##REQUEST URL##);

    People people = (from p in element.Descendants("user")
      select new People
      {
            Id = p.Attribute("id").Value ?? string.Empty,
            IsPro =
            Convert.ToInt32(p.Attribute("ispro").Value) == 0 ? false : true,
            BandWidth =
            (from b in element.Descendants("bandwidth")
               select new BandWidth
                {
                      RemainingKB = 
                      Convert.ToInt32(b.Attribute("remainingkb").Value),
                      UsedKB = Convert.ToInt32(b.Attribute("usedkb").Value)
                 }).Single<BandWidth>()
               }).Single<People>();

    return people;
}
catch (Exception ex)
{
    throw new ApplicationException("Could not process response", ex);
}

Note :GetElement is a local method that does a XElement.Load, with some validation check.

Here my Client-Side object looks like

People
Id
IsPro
BandWidth
   RemainingKB
   UsedKB

The most interesting thing is, everything is done on the fly , no loop, no intermediate result tracking, no headache of sibling and first child.Overall, the code has a high point in terms of readability.

Take that !!

kick it on DotNetKicks.com

Comments

Michael Washington said:

Good Linq code example. Thanks

# January 11, 2008 11:35 AM

Denny Ferrassoli said:

Excellent, I wasn't aware you could use a rest URL with GetElement. This will make parsing XML much easier. Thanks!

# January 11, 2008 12:07 PM

mehfuzh said:

Michael and Denny thanks a lot for your comments, it is my pleasure that you liked it.

# January 11, 2008 12:30 PM

mehfuzh said:

Thanks, kazi, noted!

# January 11, 2008 10:38 PM

Rajesh said:

Hi

I am very new to linq.

I have xml structure like below

<Page Name="Page1">

 <Controls>

 <control>

 <TextBox1 ID="TextBox1" ControlType="System.Web.UI.WebControls.TextBox" ControlData="rajesh" />

</control>

 <control>

 <TextBox2 ID="TextBox2" ControlType="System.Web.UI.WebControls.TextBox" ControlData="ajay" />

</control>

 <control>

 <TextBox3 ID="TextBox3" ControlType="System.Web.UI.WebControls.TextBox" ControlData="poonam" />

 </control>

 <control>

 <TextBox4 ID="TextBox4" ControlType="System.Web.UI.WebControls.TextBox" ControlData="manoj" />

 </control>

 <control>

 <txtpntest1 ID="txtpntest1" ControlType="System.Web.UI.WebControls.TextBox" ControlData="" />

 </control>

 <control>

 <txtpntest2 ID="txtpntest2" ControlType="System.Web.UI.WebControls.TextBox" ControlData="" />

 </control>

 <control>

 <txtpntest3 ID="txtpntest3" ControlType="System.Web.UI.WebControls.TextBox" ControlData="" />

 </control>

 <control>

 <pnltest ID="pnltest" ControlType="System.Web.UI.WebControls.Panel" />

 </control>  

 </Controls>

<DocCollection>

<DocName>

Purchase order

</DocName>

<DocDescription>

to raise a purchase order

</DocDescription>

</DocCollection>

</Page>

i have business entity class which has three property

1>Controlcollection of type string

2>DocDescription of type string

3>DocName of type string

what i want is to fill Controlcollection  with the data in control collection within Controls node and DocDescription  with DocDescription within DocCollection node and DocName with DocName within DocCollection  node

Please help to resolve above issuse

Thanks

# March 24, 2008 11:46 AM

mehfuzh said:

Hi Rajesh,

As i have showed in my post that if you want to find nodes under a certain node ,

you can do like

var query = from control in doc.Decendants("control")

           select new SomeClass

           {

              SomeProperty = control.Element("Textbox1").Attribute("ID").Value ?? string.Empty.

           }

This is the simplest form to start with, you can furter do it dynamic by getting all the textbox Element and running a query for each.

Hope this helps,

# March 24, 2008 6:12 PM