How To Set-up Your Episerver Project To Work With Different Developer Config Files

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’

Conclusion

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!

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

More Posts

6 replies
  1. Kevin Johansson Candlert
    Kevin Johansson Candlert says:

    Doesn’t your ConnectionStrings get overwritten every time your project is built (and your copy condition is met)?
    So you have to add ConnectionStrings to every developers private connectionstring.config?

    This is how I solved it although it’s not version handled:

    So the “[Configuration]/_Local” folder is ignored by git and every developer can add it’s own development environment variables.
    We could simply change “_Local” to “$(COMPUTERNAME)” (I prefer hostname over username, as I use my account/username on multiple computers) and allow users to commit their local configuration.

    When implementing an appsettings key for example; Simply add it to “_Base/AppSettings.Base.config” and if the developer needs to override this variable locally, he can copy the line from “AppSettings.Base.Config” and put it in the “AppSettings.Local.Config” – Change the value and add the xdt:Transform attributes.

    However, there’s one common problem with all this transformation hacking. If you update or install a NuGet package which adds references and config to your Web.config file it will be overwritten as soon as you hit build. So most of the time you have to loop up documentation and migrate the assembly binding, appsettings och whatever the nuget adds.

    Reply
    • jon
      jon says:

      Opps.. good spot. The script would require each developer to have a config file, I’ve updated the code as I missed out the ‘ Condition=”Exists(‘App_Config\ConnectionStrings.$(USERNAME).config’)”‘ part on the TransformXml 😛

      I like your idea of the base.config though, I use a similar technique for other CMS projects but hadn’t thought of using it in Epi. I usually create a file called Project.Settings.Local.config and put all project specific stuff in there, then my process is the same as yours, having individual dev configs with replaces for anything specific to them

      Reply
    • jon
      jon says:

      Thats definitely a workable solution. I personally like to have everything in source control so if I want to I can completely blat my who webroot completely without worrying, but that’s just my preference.

      Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *