// December 5th, 2009 // No Comments » // Uncategorized
As an ASP/C# developer it’s key I work locally and save time wasted uploading files after every change to a page.  Then, when I’ve got a bunch of changes to share with a client and I want to update a staging/production environment, I can do it all at once.  Well, I resumed working on a project this afternoon that I haven’t worked on for a couple days – and I just couldn’t recall the local site address!
My laptop runs Vista Business and I use Internet Information Services (IIS) to run local apps. Â To map the various apps and keep everything running on port 80 I take advantage of the Windows Hosts file to create custom urls for local apps. Â For example, I can create an entry for clientname.localdev which enables me to setup and view a site at http://clientname.localdev/. Â You can learn more about Hosts files here if they’re new to you.
Back to this morning: I couldn’t recall if I setup localdev.project, project.localdev, project.local, or local.project. Â Only way to check is to open up the Hosts file and see what I had originally created. Â That’s when I thought: let’s write a quick page to read all the entries in my Hosts file. Â So I did, and I setup sites.local as my own, local directory of entries read directly from my Hosts file. Â Check it out:
I figured I’d create some categories to group the multiple entries I’ve got in my Hosts file – and add a quick flag for showing a category collapsed by default (more on this later). Â Here’s a modified (sample) Hosts file:
First, let’s look at a few changes to the Hosts file itself to make all this work:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| # Copyright (c) 1993-2006 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
127.0.0.1 localhost #ExcludeFromSites.Local
::1 localhost #ExcludeFromSites.Local
#Sites.Local.Category: New Projects Category#
127.0.0.1 project1.local
127.0.0.1 project2.dev
127.0.0.1 anotherclient.devel
127.0.0.1 project3.local
#Sites.Local.Category: Other Category Here#
127.0.0.1 project4.local
127.0.0.1 project5.dev
127.0.0.1 project6.local
#Sites.Local.Category: Archived/Past Por {start:collapsed}#
127.0.0.1 project7.local
127.0.0.1 project8.dev
127.0.0.1 client23.devel
127.0.0.1 project9.local
127.0.0.1 project10.local
127.0.0.1 project11.dev
127.0.0.1 clientname.devel
127.0.0.1 project12.local |
This obviously is not my Hosts file – I created a sample file for demo purposes. Â But either way, there are a couple things to note here – most of which will make sense as you look at the upcoming .aspx and code behind:
- Adding “#ExcludeFromSites.Local” to the end of the line will (you guessed) prevent the line’s display on our page
- You can group entries by adding “#Sites.Local.Category:Â categoryname# to a line above that group, where categoryname is some text you’d like to refer to this category by
- You can “{start:collapsed}” to a group name to display this group collapsed initially (each group can be collapsed/expanded by clicking the group name
Now onto the code – I made comments throughout the code behind to make things easy to follow. Â The code could certainly be simplified, but for the sake of clarity I expanded some of it.
First, the .aspx page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
| <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="siteslocal_default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Local Site Addresses</title>
<style type="text/css">
* {
font-family:Arial;
font-size:13px;
}
body {
background-color:#dfd;
}
div#centercontent {
width: 800px;
height: 500px;
text-align: center;
position: absolute;
left: 50%;
top: 50%;
margin-left: -400px;
margin-top: -250px;
}
div#header {
text-align:left;
font-size:23px;
font-weight:bold;
height:30px;
}
div#content {
border: 1px solid #000;
padding: 30px;
text-align:left;
height:360px;
background-color:#fff;
overflow-y:scroll;
}
div#footer {
text-align:left;
font-size:12px;
}
div.category {
margin-bottom:15px;
margin-left:10px;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div id="centercontent">
<div id="header">Local Site Addresses</div>
<div id="content">
<asp:Literal id="litHosts" runat="server"></asp:Literal>
</div>
<div id="footer">The contents of this page are being read directly
from the hosts file in C:WindowsSystem32driversetc</div>
</div>
</form>
</body>
</html> |
And for the meat of the page, here’s the code behind written in c#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
| using System.Web;
using System.Web.UI;
using System.IO;
public partial class siteslocal_default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
StreamReader reader = File.OpenText(@"C:WindowsSystem32driversetchosts");
string line = string.Empty;
while ((line = reader.ReadLine()) != null)
{
if (!line.StartsWith("# ") &&
!line.StartsWith(" ") &&
line != "#" &&
line != "" &&
!line.EndsWith("#ExcludeFromSites.Local"))
{
bool show_collapsed = false;
string showhidecode = string.Empty;
if (line.StartsWith("#"))
{
/******* Append the HTML for the start of a new category *******/
if (litHosts.Text != "")
litHosts.Text += ""; //only append if we're not on the first category
if (line.Contains("{start:collapsed}"))
show_collapsed = true;
string catText = line;
catText = catText.Replace(" ", "").Replace("t", ""); //remove spaces and tabs
catText = catText.Replace("{start:collapsed}", ""); //remove from display
catText = catText.Replace("Sites.Local.Category:", ""); //remove category prefix
catText = catText.Replace("#", ""); //remove any stray #'s
//prep the javascript onclick code and div id
string id = catText.ToLower();
string js = string.Format("document.getElementById('{0}').style.display",id);
showhidecode = _
@"onclick=""if({0}=='block'){{0}='none';}else{{0}='block';}""".Replace("{0}", js);
//append the <div> for this category's name
litHosts.Text += string.Format(@"<div style=""cursor:pointer;"" {0}> _
<b>{1}</b></div>", showhidecode, catText);
//append the <div> opening tag for this category
litHosts.Text += string.Format(@"<div id=""{0}"" class=""category"" _
style=""display:{1};"">", id, show_collapsed ? "none" : "block");
}
else
{
/******* Append the HTML for each item in the current category *******/
//first let's isolate the host name (assumes we don't need to display the IPs)
//so...let's the find the index of the first space or tab
string url = string.Empty;
line = line.Trim();
int spacer_location = 0;
spacer_location = line.IndexOf(' ');
if (spacer_location == -1)
spacer_location = line.IndexOf("t");
//display from the spacer to the end
url = line.Substring(spacer_location, line.Length - spacer_location);
url = url.Replace(" ", "").Replace("t", ""); //remove any spaces or tabs
//write out this line
litHosts.Text += string.Format(@"<a href=""http://{0}/"">{0}</a><br />", url);
}
}
}
litHosts.Text += ""; //close out the last div
reader.Dispose();
}
} |
The only other things to note are:
- I setup this page to run at http://sites.local and site this as my home page in Chrome – in IIS I changed the anonymous user to my own username (to ensure the code has permission to access the file)
- Be sure to not to start an entry in your Hosts file with a Tab – the code allows preceeding spaced, but would need to be changed to allow preceeding Tabs
That’s it, hope you find this useful and a bit of a timesaver too. Â Only took about 30 minutes to pull together, and I think you ought to be able to set it up in less time than that.
Happy coding!