<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><language>en</language><title>Blog posts by Jacob Nielsen</title> <link>https://world.optimizely.com/blogs/Jacob-Nielsen/</link><description></description><ttl>60</ttl><generator>Optimizely World</generator><item> <title>On-page edit with Composer</title>            <link>https://world.optimizely.com/blogs/Jacob-Nielsen/Dates/2011/7/On-page-edit-with-Composer/</link>            <description>&lt;p&gt;If you are using Composer, you might have noticed that you have lost the ability to edit properties on your Composer page, since Composer seems to override or at least hide the “On-page edit” option from the context menu. &lt;/p&gt;  &lt;p&gt;However, enabling “On-page edit” again is luckily pretty straightforward:&lt;/p&gt;  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span class=&quot;kwrd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;void&lt;/span&gt; AddPageOnEditToContextMenu()
{
    &lt;span class=&quot;kwrd&quot;&gt;if&lt;/span&gt; (!CurrentPage.ACL.QueryDistinctAccess(EPiServer.Security.AccessLevel.Edit))
        &lt;span class=&quot;kwrd&quot;&gt;return&lt;/span&gt;;

    RightClickMenuItem dopeItem = ContextMenu.CreateMenuItem(&lt;span class=&quot;str&quot;&gt;&amp;quot;On-page edit&amp;quot;&lt;/span&gt;, &lt;span class=&quot;kwrd&quot;&gt;null&lt;/span&gt;, &lt;span class=&quot;str&quot;&gt;&amp;quot;EPi.ope.onEdit()&amp;quot;&lt;/span&gt;, &lt;span class=&quot;str&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt;,
                                                             &lt;span class=&quot;str&quot;&gt;&amp;quot;/App_Themes/Default/Images/Tools/dark/Edit.gif&amp;quot;&lt;/span&gt;,
                                                             RightClickMode.View);
    dopeItem.EnabledScript = &lt;span class=&quot;str&quot;&gt;&amp;quot;!EPi.ope.isEditing()&amp;quot;&lt;/span&gt;;
    ContextMenu.Menu.Add(&lt;span class=&quot;str&quot;&gt;&amp;quot;DOPE item&amp;quot;&lt;/span&gt;, dopeItem);
}&lt;/code&gt;&lt;/pre&gt;
&lt;style type=&quot;text/css&quot;&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Call this method in the beginning of the OnInit-event on your Composer template, and you should have the ability to edit your pagetype properties directly on your page again.&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/Jacob-Nielsen/Dates/2011/7/On-page-edit-with-Composer/</guid>            <pubDate>Thu, 07 Jul 2011 13:02:15 GMT</pubDate>           <category>Blog post</category></item><item> <title>Targeting multiple environments and machines – part 2/2</title>            <link>https://world.optimizely.com/blogs/Jacob-Nielsen/Dates/2011/5/Targeting-multiple-environments-and-machines--part-221/</link>            <description>&lt;p&gt;In the &lt;a href=&quot;/link/560bbadeb3fc4432952ef634180f3cb7.aspx?epslanguage=en&quot;&gt;previous post&lt;/a&gt; we looked at why targeting multiple environments and machines can be a problem, and our approach to solving this problem. In this post I will walk you through our solution from a more technical perspective.&lt;/p&gt;  &lt;p&gt;Our solution to this problem is achieved primarily by the use of &lt;a href=&quot;http://nant.sourceforge.net/&quot;&gt;NAnt&lt;/a&gt; &lt;sup&gt;1 &lt;/sup&gt;and some extensions we have built on top of that. Our setup allows us to support different configurations on not only a per-environment basis, but also on a per-machine basis in each environment. Our solution is stand-alone, not requiring any external references, and it is easy to setup. Best of all? We are offering it to you, free of charge! A download link for an example project can be found at the bottom.&lt;/p&gt;  &lt;p&gt;Let us dive right into it and take a look at an example project setup, see the figure below:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/368cbbcca05a4e7294963bdd994f04e7.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/link/bd41b723745f43fea53a9bffb4080558.png&quot; width=&quot;328&quot; height=&quot;392&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The interesting bit here is the “Valtech.ConfigFramework” project. The project is divided into a number of folders:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;configfiles/dynamic:&lt;/strong&gt; This holds all the files that needs to be dynamically altered based on the target environment and/or machine. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;configfiles/include: &lt;/strong&gt;This holds all configuration properties for each target environment and/or machine, needed to alter the files in “configfiles/dynamic”. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;configfiles/static: &lt;/strong&gt;This holds all files that need to be included for a specific build configuration, but does not need to be altered, e.g. license files. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;framework&lt;/strong&gt;: This holds all necessary files needed. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;When building the project, the include files are merged with the dynamic files, and output along with any static files to the output folder( s). The actual folder structure looks like this:&lt;/p&gt;  &lt;p&gt;i&lt;a href=&quot;/link/d519818967ca4b0fbf64f2114bbcb284.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px&quot; title=&quot;physical folder structure-1&quot; border=&quot;0&quot; alt=&quot;physical folder structure-1&quot; src=&quot;/link/aec93f67142c4e48855d70aada34593b.png&quot; width=&quot;187&quot; height=&quot;168&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Here, there is only one application named “ConfigFrameworkTestApp”, but you could have any number of applications using the same Valtech.ConfigFramework.&lt;/p&gt;  &lt;p&gt;&lt;font size=&quot;3&quot;&gt;&lt;strong&gt;Dynamic and static files&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;In the previous solution overview, I showed an application alongside the configuration framework. In the figure below, two folders “License” and “Log” have been added to the application, and the “configfiles/dynamic” folder and “configfiles/static” folder for the Valtech.ConfigFramework project have both been expanded:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/91b690dafe8345cebf826f61efe46fa9.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/link/a788384695704297a0cf52d5265c5338.png&quot; width=&quot;323&quot; height=&quot;606&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;As you can see, there is one top-level folder below the “configfiles/dynamic” folder named “ConfigFrameworkTestApp”. This is simply the name of the application being targeted (see the physical folder structure figure above). One level below the application folder is a folder named &lt;a href=&quot;mailto:&amp;ldquo;@Log&quot;&gt;@Log&lt;/a&gt;. Files from the ConfigFramework project are output to the application root directory, and the prefix @ tells the ConfigFramework to copy any files in this folder to the corresponding folders in the application&lt;/p&gt;  &lt;p&gt;Below the “configfiles/static/ConfigFrameworkTestapp” folder there are three folders: development, prod and qa. These folders each act as containers for files specific to an environment. In the figure above, the qa-environment folder is expanded, and below this folder is a folder named @License containing a license file specific to this environment.&lt;/p&gt;  &lt;p&gt;So in this case the following files are copied from the ConfigFramework project to the application:&lt;/p&gt;  &lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;2&quot; width=&quot;637&quot;&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign=&quot;top&quot; width=&quot;257&quot;&gt;&lt;strong&gt;From (\configfiles\)&lt;/strong&gt;&lt;/td&gt;        &lt;td valign=&quot;top&quot; width=&quot;270&quot;&gt;&lt;strong&gt;To (\Applications\ConfigFrameworkTestapp\)&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign=&quot;top&quot; width=&quot;257&quot;&gt;dynamic\ConfigFrameworkTestapp\@Log\Log.config&lt;/td&gt;        &lt;td valign=&quot;top&quot; width=&quot;270&quot;&gt;Log\Log.config&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign=&quot;top&quot; width=&quot;257&quot;&gt;dynamic\ConfigFrameworkTestapp\App.config&lt;/td&gt;        &lt;td valign=&quot;top&quot; width=&quot;270&quot;&gt;App.config&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign=&quot;top&quot; width=&quot;257&quot;&gt;static\ConfigFrameworkTestapp\qa\@License\license.txt&lt;/td&gt;        &lt;td valign=&quot;top&quot; width=&quot;270&quot;&gt;License\license.txt&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;The files from the dynamic folder, are altered based on configuration properties from the “configfiles/include” folder (more on this below) whereas the static files are simply copied to the application. &lt;/p&gt;  &lt;p&gt;In this example we are only modifying and copying .xml and .txt files, but the ConfigFramework is not restricted to working with any specific file types, so you could for example add external .dll files as static files to be copied.&lt;/p&gt;  &lt;p&gt;&lt;font size=&quot;3&quot;&gt;&lt;strong&gt;Include files&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Now that we have an idea of what is going on, let us take a look at some actual examples. First take a look at the following figure:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/b40305c466174dd486899ff7eb447a9c.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/link/49551e2084c24dffaf7f5c2ae351970a.png&quot; width=&quot;321&quot; height=&quot;605&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;As you can see, the “configfiles/include” folder is expanded, once again revealing the application “ConfigFrameworkTestApp” as the top-level folder. Below that there are a number of folders: development, prod and qa, each used for targeting a specific environment. However, as evident below the “configfiles/include/ConfigFrameworkTestApp/development” folder (which holds all properties for configuring the application in the development environment), there are two more folders: dk-lt-jani64 and dk-lt-jeth64. These are both actual machine names, and any properties defined for a machine will automagically override properties defined on the environment (i.e. development in this case) level.&lt;/p&gt;  &lt;p&gt;Sounds confusing? Hopefully not so much if we look at an example. Below are a few lines from the App.config of the application:&lt;/p&gt;  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;appSettings&amp;gt;
    &amp;lt;add key=&lt;span class=&quot;str&quot;&gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;value&lt;/span&gt;=&lt;span class=&quot;str&quot;&gt;&amp;quot;${HelloWorld}&amp;quot;&lt;/span&gt;/&amp;gt;
    &amp;lt;add key=&lt;span class=&quot;str&quot;&gt;&amp;quot;GlobalWorld&amp;quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;value&lt;/span&gt;=&lt;span class=&quot;str&quot;&gt;&amp;quot;${GlobalWorld}&amp;quot;&lt;/span&gt;/&amp;gt;
&amp;lt;/appSettings&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;style type=&quot;text/css&quot;&gt;






.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&lt;style type=&quot;text/css&quot;&gt;















.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;And next are the contents of the configfiles\include\ConfigFrameworkTestApp\development\developer.properties file in the Valtech.ConfigFramework project: &lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&lt;span class=&quot;str&quot;&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt; encoding=&lt;span class=&quot;str&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;?&amp;gt;
&amp;lt;target xmlns=&lt;span class=&quot;str&quot;&gt;&amp;quot;http://nant.sf.net/release/0.86-beta1/nant.xsd&amp;quot;&lt;/span&gt;&amp;gt;
  &amp;lt;property name=&lt;span class=&quot;str&quot;&gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;value&lt;/span&gt;=&lt;span class=&quot;str&quot;&gt;&amp;quot;Hello World. I&#39;m from development&amp;quot;&lt;/span&gt;/&amp;gt;    
&amp;lt;/target&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;style type=&quot;text/css&quot;&gt;






.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;Notice the property with the name “HelloWorld”. When you build the Valtech.ConfigFramework, the value of this property will automatically replace the ${HelloWorld} token in any files under the configfiles\dynamic folder. Now, what if my personal HelloWorld value differ from the general development settings? Answer: I simply override the property in my machine specific developer.properties file – i.e. configfiles\include\ConfigFrameworkTestApp\development\dk-lt-jani64\my.properties:&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&lt;span class=&quot;str&quot;&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt; encoding=&lt;span class=&quot;str&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;?&amp;gt;
&amp;lt;target xmlns=&lt;span class=&quot;str&quot;&gt;&amp;quot;http://nant.sf.net/release/0.86-beta1/nant.xsd&amp;quot;&lt;/span&gt;&amp;gt;
  &amp;lt;property name=&lt;span class=&quot;str&quot;&gt;&amp;quot;HelloWorld&amp;quot;&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;value&lt;/span&gt;=&lt;span class=&quot;str&quot;&gt;&amp;quot;Hello World. I&#39;m from my own machine&amp;quot;&lt;/span&gt;/&amp;gt;
&amp;lt;/target&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;style type=&quot;text/css&quot;&gt;






.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;But the ConfigFramework is not restricted to simply having key-value pairs. Supposing you only want to include parts of a Web.config for specific build configurations, and not others, you can do that too. For example, if I include the following line in my App.config file:&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;${SMTP}&lt;/code&gt;&lt;/pre&gt;
&lt;style type=&quot;text/css&quot;&gt;














.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;The ConfigFramework will look for a SMTP.property file under “configfiles/include”, and replace the line above with the contents of the file, e.g.:&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&amp;lt;system.net&amp;gt;
    &amp;lt;mailSettings&amp;gt;
        &amp;lt;smtp&amp;gt;
            &amp;lt;network host=&lt;span class=&quot;str&quot;&gt;&amp;quot;mailserver.mydomain.com&amp;quot;&lt;/span&gt; /&amp;gt;
        &amp;lt;/smtp&amp;gt;
    &amp;lt;/mailSettings&amp;gt;
&amp;lt;/system.net&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;style type=&quot;text/css&quot;&gt;






.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, &quot;Courier New&quot;, courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;&lt;font size=&quot;3&quot;&gt;&lt;strong&gt;Putting it all together&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;So how does all this work? The keen eyed reader may have noticed a number of .cmd files in the figures above, and this is where all the action is happening. Well, that and solution configurations in Visual Studio.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/link/7efe06efa678400a92ffae5d208c4464.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;physical folder structure-1&quot; border=&quot;0&quot; alt=&quot;physical folder structure-1&quot; src=&quot;/link/418ac7b2bbd047b3bba172d33b8a5748.png&quot; width=&quot;643&quot; height=&quot;403&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The figure above shows the different solution configurations for this solution. Depending on the active solution configuration, the application@environment (in this case ConfigFrameworkTestApp@development) will be built by calling the application@environment.cmd file. To create a new configuration, you simply need to copy one of the existing application@environment.cmd files, and rename it according to your Visual Studio solution configuration.&lt;/p&gt;

&lt;p&gt;&lt;font size=&quot;3&quot;&gt;&lt;strong&gt;Wrapping things up&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;

&lt;p&gt;This solution, allow us to automatically build configurations for any number of environments and machines. It does require some initial setup, but once that bit is over, you don’t ever have to worry about manually merging config files from one environment with another. Secondly, if you pair this approach with a continuous integration package (e.g. &lt;a href=&quot;http://www.jetbrains.com/teamcity&quot;&gt;TeamCity&lt;/a&gt;) you can automate the entire process of building and deploying your applications across multiple environments.&lt;/p&gt;

&lt;p&gt;Now, for what you’ve all been scrolling to: &lt;/p&gt;

&lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:F60BB8FA-6F02-4999-8F5E-9DD4E92C4DA7:883f653a-b4c0-48f0-88e2-2752f1899102&quot; class=&quot;class&quot;&gt;
  &lt;div&gt;&lt;a href=&quot;http://blog.tchami.com/ConfigFrameworkTestApp.zip&quot; target=&quot;_blank&quot;&gt;Download example project&lt;/a&gt;&lt;/div&gt;

  &lt;div&gt;&amp;#160;&lt;/div&gt;
&lt;/div&gt;
Make sure to replace the folder names “your-machine-hostname” with the name of your machine and try to play around with the different build configurations: 

&lt;ul&gt;
  &lt;li&gt;ConfigFrameworkTestApp@development &lt;/li&gt;

  &lt;li&gt;ConfigFrameworkTestApp@prod &lt;/li&gt;

  &lt;li&gt;Manual configuration update &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first two work as explained above, where as the third “Manual configuration update” bypasses the configuration builder which is useful if you would like to build your application without also building all configuration files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Notes:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; &lt;em&gt;NAnt is a (free) .NET build tool based on &lt;/em&gt;&lt;a href=&quot;http://ant.apache.org&quot;&gt;&lt;em&gt;Apache Ant&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, designed for developing software across multiple platforms. There are tons of examples on how to use NAnt on the projects homepage, so if you are new to NAnt I’d advise you to take a look at the project’s homepage here: &lt;/em&gt;&lt;a href=&quot;http://nant.sourceforge.net/&quot;&gt;&lt;em&gt;http://nant.sourceforge.net/&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/Jacob-Nielsen/Dates/2011/5/Targeting-multiple-environments-and-machines--part-221/</guid>            <pubDate>Tue, 24 May 2011 11:38:35 GMT</pubDate>           <category>Blog post</category></item><item> <title>Targeting multiple environments and machines - part 1/2</title>            <link>https://world.optimizely.com/blogs/Jacob-Nielsen/Dates/2011/5/Targeting-multiple-environments-and-machines---part-12/</link>            <description>&lt;p&gt;A classic problem, or challenge if you are a glass half-full type of person, in software development is how to target multiple environments. By environments, I really mean different machines. Machines for development, for testing, for staging and for production, e.g.:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/06ce119fc17647119d9aceef222c4e7e.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;blog&quot; border=&quot;0&quot; alt=&quot;blog&quot; src=&quot;/link/418143ed150a49a6946151545d2802f6.png&quot; width=&quot;541&quot; height=&quot;275&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size=&quot;4&quot;&gt;&lt;strong&gt;The problem&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;In some areas of software development, this is a problem of supporting different hardware setups, but in web development we (most often) only have to worry about different database connection strings, mail server setup, paths to e.g. upload folders, and similar configuration differences on different environments. &lt;/p&gt;  &lt;p&gt;Several solutions to this problem have been suggested, but common for all solutions is a goal to automate this process of supporting multiple environments without having to manually figure out which configuration bits that needs to be flipped. &lt;/p&gt;  &lt;p&gt;Furthermore, as developers we are used to working by contracts. At a very lowest level we have an unspoken contract with the compiler, making sure that we keep to the rules of our language of choice. Our types and methods too define contracts on what we are allowed to do. Webservices rely heavily on contracts, just as any services in the real world do. Surprisingly though, while our applications and websites more often than not rely on configuration files to keep them running, our configuration files are just flat files. In other words, there is no contract preventing us or at least warning us from making errors that in worst case scenarios could bring everything crashing down around our ears. Solving this part of the problem is hard. While you can build procedures to automatically check that everything looks nice, actually validating the data is a topic worthy of a book in itself.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size=&quot;4&quot;&gt;Solution&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Automatically building environment specific configurations is nothing new, in fact a tool is built right into Visual Studio 2010. &lt;/p&gt;  &lt;p&gt;The &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dd465326.aspx&quot;&gt;Web.config transformation tool in Visual Studio&lt;/a&gt; allows you to:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;set attributes &lt;/li&gt;    &lt;li&gt;remove attributes &lt;/li&gt;    &lt;li&gt;delete nodes &lt;/li&gt;    &lt;li&gt;replace nodes &lt;/li&gt;    &lt;li&gt;insert nodes &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;in your Web.config file. This is great.. as long as all you require is the ability to modify your Web.config file from environment to environment but if either of the following statements are true:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;I keep certain configuration bits outside the Web.config file &lt;/li&gt;    &lt;li&gt;I’m not .NET web developer using Visual Studio &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;this solution is not for you. Not to mention, this does not ensure that aconfig file for a specific environment is not missing a vital property.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size=&quot;3&quot;&gt;Our solution&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;While our work primarily involves ASP.NET web development, the projects we work on require a much high degree of configuration customization than the Web.config transformation tool described above facilitates. &lt;/p&gt;  &lt;p&gt;Our goal was to create a configuration framework that would provide us with a high degree of customization and at the same time be statically compiled, preventing us from building and then deploying a bad environment configuration.&lt;/p&gt;  &lt;p&gt;We ended up with a solution looking something like the figure below:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/c1246b48810c4497a5c47c3e9d616fc3.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px&quot; title=&quot;overview-1&quot; border=&quot;0&quot; alt=&quot;overview-1&quot; src=&quot;/link/2968a4c5fbc84bc3a008e9c597df488c.png&quot; width=&quot;410&quot; height=&quot;332&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In the figure above, the boxes on the left (“Templates” and “Environment specific properties”) are especially interesting.    &lt;br /&gt;“Templates”, surprisingly, contains templates. For example, it might contain a Web.config template in which connection string values are not defined. It could also contain a license file template, in which the license key was not defined. Instead of defining the environment specific values, that is connection string and license key values, a uniquely named property is written. This property will then be substituted for an environment specific value by the configuration framework when the project is built.     &lt;br /&gt;    &lt;br /&gt;At build time, we then invoke the configuration framework, which collects all the templates and attempts to populate them with properties from a specific environment configuration. Now, if a property is not found, the build will fail and warn us about the missing property. This is great, since we only have to maintain one configuration file (the template), but can still modify and build it across multiple environments and at the same time ensure that all configuration files contain all required properties.&lt;/p&gt;  &lt;p&gt;The figure below illustrates this process:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/e3450a57295f467e8614407c47371580.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;process-1&quot; border=&quot;0&quot; alt=&quot;process-1&quot; src=&quot;/link/f589d568dc584c34aba0dffe3c03f4e8.png&quot; width=&quot;546&quot; height=&quot;110&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Hopefully this has piqued your interest. If so, stay tuned for the next post in which we will go into the technical details of our solution and best of all, offer it to you free of charge.&lt;/p&gt;</description>            <guid>https://world.optimizely.com/blogs/Jacob-Nielsen/Dates/2011/5/Targeting-multiple-environments-and-machines---part-12/</guid>            <pubDate>Mon, 23 May 2011 13:17:45 GMT</pubDate>           <category>Blog post</category></item></channel>
</rss>