IP Address Location In ASP.NET
There are a lot of paid as well as free services that can find Visitor Geographical information like country, region, city, latitude, longitude, ZIP code, time zone etc from I.P Addresses. http://iplocationtools.com/ip_location_api.php is one such free IP Geolocation API that returns geographical data in three formats: XML, JSON and CSV. In this article, we will consume this API and fetch visitor geographical information in XML format in the simplest possible way, using LINQ To XML.
Update: This service seems to be no longer working the way it was when i wrote this article. You can get more info over here and here
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
http://iplocationtools.com/ip_query2.php?ip=74.125.45.100
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.
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.
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 the XDocument.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:
The XML document is fetched and transformed using XSLT. The resultant output UI is as shown below, which in my honest (developer) opinion, looks decent!
Note: You cannot do much in terms of finding geolocation information if the person is behind an anonymous proxy.
The entire source code of this article can be downloaded from here
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn