जगदीश खोलिया: Ajax,Linq and XML in ASP.NET 3.5 and C#

Friday, October 14, 2011

Ajax,Linq and XML in ASP.NET 3.5 and C#


AJAX and LINQ are probably the most-talked about Microsoft offerings at the moment, and rightly-so. Both provide us with powerful features to add to our development arsenal- AJAX allows us to create more user-friendly web applications that can almost rival our desktop equivalents; and then LINQ provides a unified way for us to communicate and interact with a wide array of data sources.
This tutorial will combine the two, and throw in a bit of XML too. In this example we are going to create a web application that will use an XML file to store small amounts of data, that we will display and also add to using AJAX and LINQ.
To demonstrate this, we will be storing names, cities and ages of people in the XML file. We will use a literal control to display the XML data and three textboxes to input new data.
Our XML file structure will look 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>

Because we are using VS.NET 2008, all we need to do to enable AJAX on our page is add the following:

<form id="form1" runat="server">
<asp:ScriptManager id="ScriptManager1" runat="server" />

<asp:UpdatePanel ID="updAdd" runat="server">
<ContentTemplate>

</ContentTemplate>
</asp:UpdatePanel>
</form>
This is the AJAX structure we will be using for our page. The ScriptManager will handle all of our AJAX calls, we don't need to do anything with that. The UpdatePanel specifies an area of the page that will partially refresh- instead of posting back the whole page. We will also add a trigger, to specify what will 'trigger' the partial refresh. To do this, though, we need the name of our button.
We add a button and the trigger to the page:

<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>

<asp:Button ID="butAdd" runat="server" Text="Add" onclick="butAdd_Click" />
</ContentTemplate>
</asp:UpdatePanel>
</form>


We reference the button in the trigger field of the UpdatePanel, which will cause the partial refresh to initiate when the button is clicked.
Next, we can add the rest of our form - the textboxes for data input, and the literal control for reading the XML. We can also add another button to initiate the reading of the XML file:

<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:Literal ID="litResults" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</form>

Notice that both of our buttons have the onclick handlers specified. We can now code these in the code-behind, like so:

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.";
}
}
We tell the read button to call another method when it is clicked because we can reuse it - notice we call the same method at the end of the add button. This is so we can update the displayed XML when we add new content. We are using LINQ to open the XML document first, and then add a new element into the parent element of Persons. Then we save changes to the XML file and let the user know.
The readXML method looks 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,
};

litResults.Text = "";
foreach (var person in persons)
{
litResults.Text = litResults.Text + "Name: " + person.Name + "<br />";
litResults.Text = litResults.Text + "City: " + person.City + "<br />";
litResults.Text = litResults.Text + "Age: " + person.Age + "<br /><br />";
}

if (litResults.Text == "")
litResults.Text = "No Results.";
}
As you can see, LINQ looks similar to SQL, but instead of communicating with a database only, we can use LINQ to communication with any data source - in this case an XML file. First we declare a variable persons and assign to it the collection from the XML file's descendants, Person. Then we select all the data from within and simply loop through our collection and output to the literal control.

No comments: