Some time ago I've written a post about best practices in deploying web applications by mentioning the different environments
- Development environment
- Testing environment
- Production environment
Since the three different environments must be completely separated (no references between them to the DB or whatever), you have to have different connections strings in your web.config file (for each connection to the according development-/test- and production-DB).
In my last post I addressed this problem by suggesting as a possible solution to not let the web.config file being copied automatically when the web application is published.
So a possible solution is to do not automatically deploy your web.config file. When your application is first published to some environment you copy your web.config file manually and immediately update the connection string s.t. it points to the right environment. On all subsequent deployments, your web.config file won't be touched which avoids to run into troubles. The disadvantage: of course if you modify other parts on your web.config file beside the connection string, you have to manually copy it on the other web.config files on the different environments. But that shouldn't be a big deal.Well this is not really the most elegant solution because it may still happen that you have to change or add some new entries to the web.config file during the development. In this case you have to remember to copy those changes manually to the web.config file when you again deploy your application. This may be error prone because you have to remember those changes.
To avoid that you web.config file is automatically copied when you click on "Publish...", you have to open the properties of the web.config file and set the properties "Build Action" to "None" and "Copy to Output Directory" to "Do not copy" (see figure).
So a better solution is to externalize the critical part of the web.config file. In this specific case we have to externalize the connection strings from the web.config but potentially there could be also other settings where it would make sense. The following piece shows this section, where [DATASOURCE_HERE] etc.. has to be replaced with the right values of course.
Original web.config file
<?xml version="1.0"?> ... <connectionStrings> <add name="MasterOracle" connectionString="Data Source=[DATASOURCE_HERE];User ID=[USER_ID_HERE];Password=[PASSWORD_HERE]" providerName="System.Data.OracleClient" /> </connectionStrings> ...What can be done now is to create a new file in the same folder as the original web.config file and give it a meaningful name, i.e. "DBConnectionStrings.config" or "ConnectionStrings.config" etc. What's important is to use the ".config" file extension since this prevents that the file can be browsed over the web. Then the part of the connection strings in the original web.config file can be extracted and placed into the newly created file:
<?xml version="1.0"?> <connectionStrings> <add name="MasterOracle" connectionString="Data Source=[DATASOURCE_HERE];User ID=[USER_ID_HERE];Password=[PASSWORD_HERE]" providerName="System.Data.OracleClient" /> </connectionStrings>
The orginal web.config file has to be modified to point to the new external configuration file:
Modified web.config file
... <connectionStrings configSource="DBConnectionStrings.config"/> ...Now I think my strategy should be evident. You can now let your web.config file be copied on each publish as usual but you prevent the copying of the external DBConnectionString.config by setting the properties "Build Action" to "None" and "Copy to Output Directory" to "Do not copy" . So the first time you setup your different environments you copy your DBConnectionString.config to each of the different locations and apply the necessary corrections such that the connection string points to the correct DB.
This is much a cleaner and more elegant solution as you do the setup once and then you don't have to remember on each publish to eventually also copy the new changes of the web.config file manually to each of the deploy environment.