Using the Hosts file and Directory Junctions to Enable Flexibility in Development Environment Configuration January, 2009
There are a number of ways to setup configuration in the development, pre production and production environments. One way is to maintain independent .config files for different environments\developers and manually copy the appropriate file to the target during deployment. I've never warmed up to this approach as it leads to obvious headaches like difficulty keeping the config files in sync (And making sure everyone is using the most up to date config file), its error prone, and there ends up being many different .config files. I have been using an approach that I really like where there is one and only one .config file for all developers and all environments (Per project of course). Developers all share the same config file and thus the same configuration. When the config file is deployed to different environments, like UAT, staging and production, the deployment NANT script modifies the configuration during deployment (I also enforce a separation between NAnt script and configuration so setting and maintaining of configuration is fairly trivial). When the config file is modified it is automatically propagated to developers when they do an update and the new schema is guaranteed to make it to all the different environments. Of course the down side to this approach is the same as the up side, every developer has the same configuration... It would really be a pain to force every developer to have a strictly defined development environment; there is no flexibility and leeway for developer preference. In order to get the best of both worlds I've been using the hosts file and symbolic links to "map" the common configuration to the developers configuration. For example the default developer config (In source control) might look like this:
<configuration> <sweetApp> <paths> <mediaFiles localPath="C:\SweetCompany\SweetApp\SweetApp.Web.UI\MediaFiles"/> <uploads localPath="C:\SweetCompany\SweetApp\Uploads"/> paths> <web> <sites errorPage="/SystemMessage.aspx"> <main domainName="www.dev.sweetapp.com" /> <services domainName="services.dev.sweetapp.com" /> <administration domainName="admin.dev.sweetapp.com" /> sites> web> sweetApp> <system.net> <mailSettings> <smtp deliveryMethod="Network" from="firstname.lastname@example.org"> <network host="smtp.dev.sweetapp.com" port="25" defaultCredentials="true"/> smtp> mailSettings> system.net> configuration>
The hosts file, under %SystemRoot%\system32\drivers\etc\, allows you to point a network name to an IP address (You probably already know this...). So in the example above the developer could add to the following to their host file.
# SweetApp Dev Mappings
This will of course map all these network names the local machine. But if, for example, the developer wanted to run parts of their environment in a VM or on another box altogether they could easily point to the IP address elsewhere. If your creating a hosts file entry for your local SQL Server that you will be connecting to with Windows Auth, be sure to setup an alias as described here
The other issue is paths. I personally keep all my "data" (Including code) under a second partition. And I like to keep things under a particular folder structure. Others may not roll this way and have different path/drive preferences. Using directory junctions you can create a "shortcut" to another folder. This can be easily accomplished with the mklink command in Vista/Server 08 (In XP and earlier there is another utility in the resource kit but I forget the name.) For the above example you could issue the following command to create a junction that links to a working folder on the D: drive.
mklink /J c:\SweetCompany\SweetApp d:\Dev\WorkApps\SweetApp
This essentially maps the first folder to the second folder so the path references in the config file will be valid but the developer can work out of the path they choose. You can also accomplish something similar with the subst command (Which maps a drive letter to a path). The problem with this approach is that the mapping is only recognized in the current login session. An ASP.NET page, for example, will know nothing about it since its running under the logon session of its process identity.