Using AJAX, LINQ and XML in C#

| Using AJAX, LINQ and XML in C# |
This tutorial was created with Visual Stuiod.NET 2008. It can be recreated in 2005, but you will need to download and install Microsoft's ASP.NET AJAX Extensions from this link.
AJAX and LINQ are two of the main focuses of Microsoft right now; and no wonder - both have huge potential and power behind them.
In this example, we will show how we can use AJAX coupled with LINQ and XML to create a Web Application that we can use to view stored data instantaneously, as well as add to it in the same way. AJAX provides the ease of use, by making the application run smoothly and efficiently, as if it was a desktop application, while LINQ provides the means to communicate and interact with the XML file and data stored within.
The first thing we need to do is create our XML file. For this example, we will be using something like this:
<?xml version="1.0" encoding="utf-8"?>
<Persons>
<Person>
<Name>Paxton</Name>
<City>Munich</City>
<Age>29</Age>
</Person>
<Person>
<Name>Mike</Name>
<City>Orlando</City>
<Age>33</Age>
</Person>
</Persons> |
We will create a form to both read and write to the XML file: We will need three textboxes and a button for additions, and then a button and a textbox for reading. We will construct a form similar to this:
<form id="form1" runat="server">
<strong>Add to XML</strong><br />
Name:<br />
<asp:TextBox ID="txtName" runat="server" /><br />
City:<br />
<asp:TextBox ID="txtCity" runat="server" /><br />
Age:<br />
<asp:TextBox ID="txtAge" runat="server" /><br />
<asp:Button ID="butAdd" runat="server" Text="Add" onclick="butAdd_Click" /><br />
<asp:Label ID="lblStatus" runat="server" />
<br /><br />
<strong>Read XML:</strong><br />
<asp:Button ID="butRead" runat="server" Text="Read" onclick="butRead_Click" /><br />
<asp:TextBox ID="txtResults" runat="server" Columns="25" Rows="10"
TextMode="MultiLine" />
</form> |
Notice that our buttons have the OnClick handlers pointing to a method. We will get to those in a minute, but first, let's finish off our ASPX page. The only thing left to do is enable AJAX on this page. We do this by adding a ScriptManager and an UpdatePanel, like so:
<form id="form1" runat="server">
<asp:ScriptManager id="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="updAdd" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="butAdd" EventName="Click" />
</Triggers>
<ContentTemplate>
<strong>Add to XML</strong><br />
Name:<br />
<asp:TextBox ID="txtName" runat="server" /><br />
City:<br />
<asp:TextBox ID="txtCity" runat="server" /><br />
Age:<br />
<asp:TextBox ID="txtAge" runat="server" /><br />
<asp:Button ID="butAdd" runat="server" Text="Add" onclick="butAdd_Click" /><br />
<asp:Label ID="lblStatus" runat="server" />
<br /><br />
<strong>Read XML:</strong><br />
<asp:Button ID="butRead" runat="server" Text="Read" onclick="butRead_Click" /><br />
<asp:TextBox ID="txtResults" runat="server" Columns="25" Rows="10"
TextMode="MultiLine" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
|
Before we start coding, we should make sure we have the correct namespaces. We will be making use of LINQ to XML, so we need System.Xml.Linq.
Our directives will look something like this:
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq; |
Now back to the buttons. We already added our handlers to the buttons, so we're now done with the ASPX page and now we can code our methods. We will create a method for the reading of the XML file, as we are likely to use this more than once (other than just on the button click - you'll see why). Our method will look something like this:
protected void readXML()
{
XDocument xmlDoc = XDocument.Load(Server.MapPath("People.xml"));
var persons = from person in xmlDoc.Descendants("Person")
select new
{
Name = person.Element("Name").Value,
City = person.Element("City").Value,
Age = person.Element("Age").Value,
};
txtResults.Text = "";
foreach (var person in persons)
{
txtResults.Text = txtResults.Text + "Name: " + person.Name + "\n";
txtResults.Text = txtResults.Text + "City: " + person.City + "\n";
txtResults.Text = txtResults.Text + "Age: " + person.Age + "\n\n";
}
if (txtResults.Text == "")
txtResults.Text = "No Results.";
} |
This method makes use of LINQ to first connect with the XML file and then make a selection of all the data within. Once selected, we loop each 'record' and output to the textbox control.
We call this method from the button click event:
protected void butRead_Click(object sender, EventArgs e)
{
readXML();
lblStatus.Text = "";
} |
Next up is adding to the XML file. This actually requires less code than reading. We will code this directly into the button click event. It will look something like this:
protected void butAdd_Click(object sender, EventArgs e)
{
try
{
XDocument xmlDoc = XDocument.Load(Server.MapPath("People.xml"));
xmlDoc.Element("Persons").Add(new XElement("Person", new XElement("Name", txtName.Text),
new XElement("City", txtCity.Text), new XElement("Age", txtAge.Text)));
xmlDoc.Save(Server.MapPath("People.xml"));
lblStatus.Text = "Data successfully added to XML file.";
readXML();
}
catch
{
lblStatus.Text = "Sorry, unable to process request. Please try again.";
}
} |
We use a try, catch to reduce the number of errors in processing. Again, we are using LINQ to add data to the XML file - first we load the file, and then we simply add a new element into the parent element, referring back to our XML structure will be useful for understanding.
The entire code-behind will look something like this:
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void butRead_Click(object sender, EventArgs e)
{
readXML();
lblStatus.Text = "";
}
protected void butAdd_Click(object sender, EventArgs e)
{
try
{
XDocument xmlDoc = XDocument.Load(Server.MapPath("People.xml"));
xmlDoc.Element("Persons").Add(new XElement("Person", new XElement("Name", txtName.Text),
new XElement("City", txtCity.Text), new XElement("Age", txtAge.Text)));
xmlDoc.Save(Server.MapPath("People.xml"));
lblStatus.Text = "Data successfully added to XML file.";
readXML();
}
catch
{
lblStatus.Text = "Sorry, unable to process request. Please try again.";
}
}
protected void readXML()
{
XDocument xmlDoc = XDocument.Load(Server.MapPath("People.xml"));
var persons = from person in xmlDoc.Descendants("Person")
select new
{
Name = person.Element("Name").Value,
City = person.Element("City").Value,
Age = person.Element("Age").Value,
};
txtResults.Text = "";
foreach (var person in persons)
{
txtResults.Text = txtResults.Text + "Name: " + person.Name + "\n";
txtResults.Text = txtResults.Text + "City: " + person.City + "\n";
txtResults.Text = txtResults.Text + "Age: " + person.Age + "\n\n";
}
if (txtResults.Text == "")
txtResults.Text = "No Results.";
}
} |
Download this sample project
|
| Comments |
John said:
Simple but straight forward. Good work.
Everything works perfectly fine using Visual Web Dev 2008.
Only thing is that, if I add a new record, VWD will tell me that "People.xml" file has been modified outside the source editor. Do you want to reload it? sort of question. Is this a normal thing?
Anyway, thanks a lot.
|
Atul sharma said:
Ya obviously this is a pretty normal thing. Its not only the case with this change in xml, even if u make change in any file from outside the solution, the same message pop ups. :)
|
Sam said:
Hi
This seems to a great work.
I am a newbie. What is the advantage of storing records in XML file?
|
Dave Kirkby said:
www.thetrainline.com stores all of its railway stations in xml documents e.g.
one xml document for 'a' stations, one xml document for 'b' stations, one xml document 'c' stations, etc...
the search textbox uses ajax and these xml documents to autocomplete a users search e.g. they type der and it comes back with derby etc...
the beauty of storing the stations in a series of xml documents for a site with very high hits, is that you don't have the overhead of high concurrent database requests.
i think that's the reason. it makes sense.
|
Girish Rajadhyaksha said:
|
Girish R said:
i Implemented it on my site and very help full to me... thanks!!!!
|
Rich said:
Sam, I wouldn't take this article to mean that XML is the 'best' way to store data, it's 'one' way to store data.
|
Andrei said:
For John and Atul.
you get the "file has been modified outside the source editor" message because you obviously have the xml file open in your editor. Then the file gets changed by your code, and finally both VWD and VS detect such a change as soon as you move your focus to it. It's a normal message, one that obviously will never be seen by a user of your website.
|
Andrei said:
I've read this article and I can see several things that are not really good practice.
First of all please look at the butAdd_Click method.
the try ... catch block encapsulates several operations. the error can come from various sources. For example, what if the People.xml does not exist ? what if it's read only ? what if the save operation fails ? All we get is one generic message that really does not help at all if something goes wrong.
a quick solution would be to use an exception variable in your catch part and use that variable's .message method to display the error. This way your user knows what went wrong and can let you know. Or you can encapsulate each potential "trouble maker" statement inside it's own try catch block and deal with it this way.
Second, what is this statement :
if (txtResults.Text == "") ???
that value is a string. You do not compare a string to something this way. you do it like this :
if (txtResults.Text.Equals(string.Empty)) ....
I would be carefull when posting explanation articles as usually these things lead to other people blindly copying mistakes and poor practices.
|
zeron said:
for a website with very high hits, using xml document might reduce the overhead of high concurrent database requests but if i have thousands of records, is xml documents still good?
|
Jim said:
"Second, what is this statement :
if (txtResults.Text == "") ???
that value is a string. You do not compare a string to something this way. you do it like this :
if (txtResults.Text.Equals(string.Empty)) ....
I would be carefull when posting explanation articles as usually these things lead to other people blindly copying mistakes and poor practices."
His statement is not a mistake, and I would not say it is poor practice either. This isn't Java, .Equals() is not required, and is not preferred due to readability. Using String.Empty over "" is personal preference, and makes no difference
|
jkm said:
FxCop recommends checking the string length, i.g.,
if (txtResults.Text.Length == 0) ...
|
nafs said:
Hi, very good article. Thanks
|
Dulles Antony said:
Very Nice tutorial to learn and update new skills.
|
Garudanagiri Raghu said:
Excellent code
Thanks ®ards
Raghu
|
|
|