Using LINQToXML to consume data from an IP Address Location XML API
Using the IP Address Location XML API is quite simple. Just specify the I.P. address as shown below
and you will receive an XML document with the visitor geographical information in the following format:
<Locations>
<Location id="0">
<Ip>74.125.45.100</Ip>
<Status>OK</Status>
<CountryCode>US</CountryCode>
<CountryName>United States</CountryName>
<RegionCode>06</RegionCode>
<RegionName>California</RegionName>
<City>Mountain View</City>
<ZipPostalCode>94043</ZipPostalCode>
<Latitude>37.4192</Latitude>
<Longitude>-122.057</Longitude>
</Location>
</Locations>
Note: In order to specify multiple I.P(maximum 25), use a comma(,) separator as shown here: http://iplocationtools.com/ip_query2_country.php?ip=74.125.45.100,206.190.60.37
However as you can observe, this is not a very UI friendly format. So our next step is to parse the XML and apply some styling to it.
Now in .NET 2.0, if someone were to consume this API, a standard practice would have been to create a WebClient class and use a StreamReader object to read the data as shown below:
C#
WebClient wc = new WebClient();
Stream data = wc.OpenRead(url);
String str;
using (StreamReader sr = new StreamReader(data))
{
str = sr.ReadToEnd();
data.Close();
}
VB.NET
Dim wc As New WebClient()
Dim data As Stream = wc.OpenRead(url)
Dim str As String
Using sr As New StreamReader(data)
str = sr.ReadToEnd()
data.Close()
End Using
However in .NET 3.0, consuming this API using LINQToXML is quite simple. There are two ways to consume this API using LINQToXML - Using the XElement class or the XDocument class. Both the classes contain the ‘Load()’ method which accepts a file, a URL or XMLReader and allows XML to be loaded. The primary difference between both the classes is that an XDocument can contain XML declaration, XML Document Type (DTD) and processing instructions. Moreover an XDocument contains one root XElement.
For those who are not familiar with LINQToXML, I strongly suggest you to read my article Some Common Operations using LINQ To XML
We will use the XDocument class to consume the XML API in just two lines of code. I will demonstrate that in a bit. Let us first create a page layout to accept I.P Address and display data.
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<style type="text/css">
body
{
font: normal 11px auto "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
background-color: #ffffff;
color: #4f6b72;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Panel ID="panelLoc" runat="server">
<asp:TextBox ID="txtIP" runat="server"></asp:TextBox>
<asp:Button ID="btnGetLoc"
runat="server" Text="Get IP Details" onclick="btnGetLoc_Click"/>
<br />
<asp:Xml ID="Xml1" runat="server"></asp:Xml>
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdateProgress ID="updProgress"
AssociatedUpdatePanelID="UpdatePanel1"
runat="server">
<ProgressTemplate>
<img alt="progress" src="images/progress.gif"/>
</ProgressTemplate>
</asp:UpdateProgress>
</div>
</form>
</body>
</html>
Shown above is a TextBox and Button control to accept I.P information from the user and submit it to the service. The controls have been kept inside an UpdatePanel to avoid postbacks. We have also added an UpdateProgress control to display a progress status to the user while the data is being fetched.
Note: If you are not familiar with the UpdateProgress control, read my article 3 Different Ways to Display Progress in an ASP.NET AJAX Application
You will also observe that an XML control (<asp:Xml ID="Xml1") has been added to the page. As given in the MSDN documentation, you can use the XML Web server control to write an XML document, or the results of an XSL Transformations (XSLT), into a Web page.
One drawback in using the XML control is that it has no way (not one that I know of) to accept an encoded HTML string.
Our XSLT will look similar to the following:
<?xmlversion='1.0'?>
<xsl:stylesheetxmlns:xsl="http://www.w3.org/1999/XSL/Transform"version="1.0">
<xsl:templatematch="/">
<HTML>
<BODY>
<TABLEcellspacing="3"cellpadding="8">
<TR>
<TDclass="heading">
<B>Ip</B>
</TD>
<TDclass="heading">
<B>Status</B>
</TD>
<TDclass="heading">
<B>CountryCode</B>
</TD>
<TDclass="heading">
<B>CountryName</B>
</TD>
<TDclass="heading">
<B>RegionCode</B>
</TD>
<TDclass="heading">
<B>RegionName</B>
</TD>
<TDclass="heading">
<B>City</B>
</TD>
<TDclass="heading">
<B>ZipPostalCode</B>
</TD>
<TDclass="heading">
<B>Latitude</B>
</TD>
<TDclass="heading">
<B>Longitude</B>
</TD>
</TR>
<xsl:for-eachselect="Locations/Location">
<TRbgcolor="#C1DAD7">
<TDwidth="5%"valign="top">
<xsl:value-ofselect="Ip"/>
</TD>
<TDwidth="5%"valign="top">
<xsl:value-ofselect="Status"/>
</TD>
<TDwidth="10%"valign="top">
<xsl:value-ofselect="CountryCode"/>
</TD>
<TDwidth="10%"valign="top">
<xsl:value-ofselect="CountryName"/>
</TD>
<TDwidth="10%"valign="top">
<xsl:value-ofselect="RegionCode"/>
</TD>
<TDwidth="10%"valign="top">
<xsl:value-ofselect="RegionName"/>
</TD>
<TDwidth="10%"valign="top">
<xsl:value-ofselect="City"/>
</TD>
<TDwidth="10%"valign="top">
<xsl:value-ofselect="ZipPostalCode"/>
</TD>
<TDwidth="10%"valign="top">
<xsl:value-ofselect="Latitude"/>
</TD>
<TDwidth="10%"valign="top">
<xsl:value-ofselect="Longitude"/>
</TD>
</TR>
</xsl:for-each>
</TABLE>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
The last step is to fetch the geographical data from the API. Add a reference to the System.Xml.Linq namespace and add the following code to the button click event
C#
protected void btnGetLoc_Click(object sender, EventArgs e)
{
String url = String.Empty;
if (txtIP.Text.Trim() != String.Empty)
{
url = String.Format("http://iplocationtools.com/ip_query2.php?ip={0}", txtIP.Text.Trim());
XDocument xDoc = XDocument.Load(url);
if (xDoc == null | xDoc.Root == null)
{
throw new ApplicationException("Data is not Valid");
}
Xml1.TransformSource = "IP.xslt";
Xml1.DocumentContent = xDoc.ToString();
}
}
VB.NET
Protected Sub btnGetLoc_Click(ByVal sender As Object, ByVal e As EventArgs)
Dim url As String = String.Empty
If txtIP.Text.Trim() <> String.Empty Then
url = String.Format("http://iplocationtools.com/ip_query2.php?ip={0}", txtIP.Text.Trim())
Dim xDoc As XDocument = XDocument.Load(url)
If xDoc Is Nothing Or xDoc.Root Is Nothing Then
Throw New ApplicationException("Data is not Valid")
End If
Xml1.TransformSource = "IP.xslt"
Xml1.DocumentContent = xDoc.ToString()
End If
End Sub
As you can observe, in order to consume the XML API, all we did was pass the url to theXDocument.Load(url)method. I hope you can realize how powerful LINQToXML is!
Once we received the XML document, we used the ‘DocumentContent’ property of the XML control to display the XML document. The XSLT was applied using the ‘TransformSource’ property.
Let us run the application. Type two I.P Addresses in the textbox as shown here and hit on the click button:







0 comments:
Post a Comment