On most Episerver builds, you will be working within a team of developers. There are a number of different ways on how to structure your Episerver deployment process. In some scenarios, having a shared database works really well, in some instances, you may want each individual developer to have their own database.
If you go down the route of each developer having their own local database, then you’ll encounter the issue of config files and source control. In today’s tutorial, I’m going to cover a strategy to enable each developer in your team to have their own custom connection string config file stored in source control, without affecting anyone else. When you have to deal with multiple developers in a project, I suggest you split your web.config up and move your connection string settings to a separate config file. You can do this like so:
<?xml version="1.0"?> <configuration> <connectionStrings configSource="App_Config\ConnectionStrings.config"/> </configuration>
In your App_Config file (or wherever you want to put it), you can create a file called ‘ConnectionStrings.config’ that will look something like this:
<?xml version="1.0" encoding="utf-8"?> <connectionStrings> <add name="EPiServerDB" connectionString="user id=dev;password=password;Data Source=DEV\.;Database=DeveloperOneEpiserverDb" /> </connectionStrings>
As we work locally using the standard build transforms in a deployment package won’t work, however, we can add build tasks directly into the ‘AfterBuild’ section within your websites .csproj file.
Post Build Scripts
Now, we obviously don’t want to check in our ‘connectionstring.config’ with developer one’s settings as this will break everyone else’s configuration. Instead, we can create a new separate file unique to that developer, say called ‘ConnectionStrings.Jon.Jones.config’ and use transforms to copy/insert the details we want into ‘ConnectionStrings.config’. Using this approach we could either make sure a developer never checks the file ‘ConnectionStrings.config’ or with a bit more msBuild configuration, we could exclude ‘connectionstrings.config’ from source control entirely!
In my example, the ‘Jon.Jones’ part is my windows account log-in. By creating a new file for dev in your team, you can add as many developers settings as you want without treading on each others feet! We can access the Windows Username within in MSBuild by using the $(USERNAME) property. If you don’t want to differentiate by username, another option is to use PC name instead $(COMPUTERNAME), I personally think the Windows username is good enough in most circumstances, so I’m sticking with it 🙂
Ok, so I’m hoping you get the concept of what I’m trying to achieve, let’s cover the MsBuild script. You need to add the below configuration into your websites .csproj file right at the bottom. Usually, if you open it in notepad and scroll down you can see a commented out section like this:
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> </Target> <Target Name="AfterBuild"> </Target> -->
Add the below XML underneath the above commented out section:
<Target Name="AfterBuild"> <Copy SourceFiles="App_Config\ConnectionStrings.config" DestinationFiles="obj\$(Configuration)\Temp.ConnectionStrings.config" /> <TransformXml Source="obj\$(Configuration)\Temp.ConnectionStrings.config" Transform="App_Config\ConnectionStrings.$(USERNAME).config" Destination="obj\$(Configuration)\Transformed.Instant.Settings.local.config" Condition="Exists('App_Config\ConnectionStrings.$(USERNAME).config')" /> <ReadLinesFromFile File="obj\$(Configuration)\Transformed"> <Output TaskParameter="Lines" ItemName="TransformedWebConnectionStrings" /> </ReadLinesFromFile> <ReadLinesFromFile File="App_Config\Include\ConnectionStrings.config"> <Output TaskParameter="Lines" ItemName="UnTransformedConnectionStrings" /> </ReadLinesFromFile> <Copy Condition=" @(UnTransformedConnectionStrings) != @(TransformedWebConnectionStrings) " SourceFiles="obj\$(Configuration)\Transformed.ConnectionStrings.config" DestinationFiles="App_Config\ConnectionStrings.config" OverwriteReadOnlyFiles="True" /> </Target>
Ok. so there’s quite a lot going on above. Let’s talk through it line-by-line.
In the first line, MsBuid creates a temporary version of ‘ConnectionStrings.config’ called ‘Temp.ConnectionStrings.config’ in the obj folder in the webroot. On the next line, MsBuild searches for a configuration file for the logged on username, if it exists, it copies the developers individual connection string setting into the newly created ‘Temp.ConnectionStrings.config’. IN the last line if the ‘Temp.ConnectionStrings.config’ and the original ‘ConnectionStrings.config’ are different, it overrides ‘ConnectionStrings.config’ with ‘Temp.ConnectionStrings.config’
In today’s tutorial, I’ve detailed the problem of how you store individual developer’s configuration in source control. By adding some MSBuild task directly into your .csproj’s post build tasks, you can customise your visual studio’s post build process a lot.
In my example, I use a basic transform using the windows log-in. I copy the web.config into a new file. Check that a matching config file exists for the current logged-in user. If it does, we copy the developers setting and set the file ‘connectionstring.config’ file accordingly. If you do not want to use the logged in Windows User Account as the differentiator, you can always use the current PC name. Enjoy!