A common problem when implementing either a hit counter or a download tracker is retrieving the DNS name of the client connecting to your Web Site. Although there is a property specifically meant for this task on the Request object called UserHostName, most of the time it just returns the IP address. At this point you may think to yourself that this is a bug in ASP.NET; however it isn't actually ASP.NET's fault. You have to enable DNS resolution at the server level in order for UserHostName to work as described in this Microsoft KB Article: http://support.microsoft.com/default.aspx?scid=kb;en-us;297795. Problem solved right? Not at all, if you look at the fine print (the Warnings Section) you'll see this:
Enabling reverse DNS on your IIS server can affect the performance of your Web server and DNS servers. Some examples are:
| • |
Resources such as CPU utilization and network bandwidth may be taken up. |
| • |
Client requests can take longer to process. |
| • |
Client requests can be blocked if IP restrictions by DNS domain names are used. |
Now that's a pretty big deal breaker if you ask me. After seeing those warnings I'd be surprised if anyone went though and actually enable that feature. So what do you do if you need/want to get the domain name but don't want to incur the issue above. ASP.NET to the rescue!! Both ASP.NET and ASP.NET 2.0 provide functionality to retrieve the DNS name, however ASP.NET 2.0's syntax is slightly different. ASP.NET provides Asynchronous methods to retrieve the DNS information. This is a lot better than enabling for the entire server, since we now have the ability to specify specific pages which will make use of this functionality. Also, by using Asynchronous methods we don't have to worry about the slowness of Reverse DNS Lookup affecting the user experience on page(s) that use them.
Coding Asynchronous DNS lookups is surprisingly easy. In order to begin a look you might have something like the code below:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
//The session is used so that a hit is only counted once.
if (((string)Session["HitCounted"]) != "1")
{
//Use Asynchronous BeginGetHostEntry to retrieve the dns record for this individual
Session["HitCounted"] = "1";
//ASP.NET 2.0
System.Net.Dns.BeginGetHostEntry(Request.UserHostAddress, new AsyncCallback(GetHostAddressCallBack), Request.UserHostAddress);
//ASP.NET 1.1
System.Net.Dns.BeginGetHostByName(Request.UserHostAddress, new AsyncCallback(GetHostAddressCallBack), Request.UserHostAddress);
}
}
}
The only syntatical different between 2.0 and 1.1 is the Method Name. The BeginGetHostByName method is marked Obsolete in ASP.NET 2.0. GetHostAddressCallBack is specified as the AsyncCallback delegate to be called. Here's that method's implementation:
public void GetHostAddressCallBack(IAsyncResult asyncResult)
{
string userHostAddress = (string)asyncResult.AsyncState;
//ASP.NET 2.0
System.Net.IPHostEntry hostEntry = System.Net.Dns.EndGetHostEntry(asyncResult);
//ASP.NET 1.1
System.Net.IPHostEntry hostEntry = System.Net.Dns.EndGetHostByName(asyncResult);
//Log this:: userHostAddress, hostEntry.HostName);
}
Again the methods only differ by name. Once in the GetHostAddressCallBack method you can retrieve the hostEntry by calling the EndGetHostEntry method (in 2.0) or the EndGetHostByName method in 1.1. As with BeginGetHostByName, EndGetHostByName has been marked obsolete in 2.0. Once you have the HostEntry, you can retrieve the DNS name by reading the HostName property. That's all there is to it.