<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Vidar's Musings</title>
	<atom:link href="http://www.kongsli.net/nblog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kongsli.net/nblog</link>
	<description>Deep thoughts on shallow topics</description>
	<lastBuildDate>Mon, 14 May 2012 10:52:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Powershell gotchas: standard out breaks lines to fit console</title>
		<link>http://www.kongsli.net/nblog/2012/05/14/powershell-gotchas-standard-out-breaks-lines-to-fit-console/</link>
		<comments>http://www.kongsli.net/nblog/2012/05/14/powershell-gotchas-standard-out-breaks-lines-to-fit-console/#comments</comments>
		<pubDate>Mon, 14 May 2012 10:52:54 +0000</pubDate>
		<dc:creator>vidarkongsli</dc:creator>
				<category><![CDATA[Microsoft technologies]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Software development]]></category>
		<category><![CDATA[console]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[powershell gotcha]]></category>
		<category><![CDATA[teamcity]]></category>

		<guid isPermaLink="false">http://www.kongsli.net/nblog/?p=446</guid>
		<description><![CDATA[When Powershell writes to standard out, and there is now redirection in the Powershell script itself, it will assume that it writes to a console. Because of this, it kindly breaks lines if they are longer than 80 characters. So, &#8230; <a href="http://www.kongsli.net/nblog/2012/05/14/powershell-gotchas-standard-out-breaks-lines-to-fit-console/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>When Powershell writes to standard out, and there is now redirection in the Powershell script itself, it will assume that it writes to a console. Because of this, it kindly breaks lines if they are longer than 80 characters. So, given the following powershell file (.ps1):</p>

<p><pre name="code" class="csharp"># line-gunk.ps1
"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"</pre></p>

<p>If you run this Powershell file from the Windows command line, and redirects output to a file:</p>

<p><pre name="code" class="csharp">C:\&gt;@powershell -file .\line-gunk.ps1 &gt; foo.txt</pre></p>

<p>Then you will get:</p>

<p><pre>1234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890</pre></p>

<p></p>

<p>However, if you do the redirection in Powershell, it&#8217;s fine:</p>

<p><pre name="code" class="csharp">PS C:\&gt; .\line-gunk.ps1 &gt; bar.txt</pre></p>

<p>A näive fix to this, would be to change your script to use <code>Write-Host</code> to explicity write the text to the console. However, I consider this a bad practice because it would restrict the usage of your script as you could not manipulate the output further if reusing the script. I found this entry on stackoverflow which provides a better solution. Going back to the original script, here is a fixed one that worked for me:</p>

<p><pre name="code" class="csharp"># line-gunk-fixed.ps1
$Host.UI.RawUI.BufferSize = New-Object Management.Automation.Host.Size(500, 25)
"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"</pre></p>

<p>Notice that I used the simplifed version from the stackoverflow entry, which might not work in all circumstances.</p>

<h2>Backstory</h2>

<p>How did I come across this problem? I running Powershell build scripts in <a href="http://www.jetbrains.com/teamcity/">TeamCity</a> and I was trying to <a href="http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ReportingBuildProgress">report the build progress</a> back to <a href="http://www.jetbrains.com/teamcity/">TeamCity</a>. However, it somehow did not work. I then discovered that the status messages written by my script were broken by the line breaks, rendering them useless&#8230;</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kongsli.net%2Fnblog%2F2012%2F05%2F14%2Fpowershell-gotchas-standard-out-breaks-lines-to-fit-console%2F&amp;title=Powershell%20gotchas%3A%20standard%20out%20breaks%20lines%20to%20fit%20console" id="wpa2a_2"><img src="http://www.kongsli.net/nblog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kongsli.net/nblog/2012/05/14/powershell-gotchas-standard-out-breaks-lines-to-fit-console/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Running chocolatey behind an authenticating firewall</title>
		<link>http://www.kongsli.net/nblog/2012/05/07/running-chocolatey-behind-an-authenticating-firewall/</link>
		<comments>http://www.kongsli.net/nblog/2012/05/07/running-chocolatey-behind-an-authenticating-firewall/#comments</comments>
		<pubDate>Mon, 07 May 2012 10:36:03 +0000</pubDate>
		<dc:creator>vidarkongsli</dc:creator>
				<category><![CDATA[Microsoft technologies]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[.net4]]></category>
		<category><![CDATA[407]]></category>
		<category><![CDATA[chocolatey]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[proxy authentication]]></category>

		<guid isPermaLink="false">http://www.kongsli.net/nblog/?p=453</guid>
		<description><![CDATA[I long grappled with a problem installing applications using chocolatey. Specifically, all installations that required downloading an MSI (or similar) file outside the .nupkg caused the following error message: The remote server returned an error: (407) Proxy Authentication Required. Yes, &#8230; <a href="http://www.kongsli.net/nblog/2012/05/07/running-chocolatey-behind-an-authenticating-firewall/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I long grappled with a problem installing applications using <a href="http://www.chocolatey.org">chocolatey</a>. Specifically, all installations that required downloading an MSI (or similar) file outside the <code>.nupkg</code> caused the following error message:</p>

<p><pre>The remote server returned an error: (407) Proxy Authentication Required.</pre></p>

<p>Yes, I am behind a firewall that requires authentication. I found several references to this error message on the chocolatey forums, but they all seemed to be fixed in the latest chocolatey version.</p>

<p>Through some googling I was able to track down the problem. Acutally, it is <a href="http://knowledgebase.solarwinds.com/kb/questions/3226/You+receive+error+407+when+using+McAfee+Web+Gateway.">a problem with the .NET 3.5 runtime</a> that causes the <code>System.Net.WebClient</code> to give up on an NTLM authentication challenge from proxies. Chocolatey uses Powershell, and indeed the <code>System.Net.WebClient</code> to download installation packages (all though not the package manifest itself, where it uses NuGet). As you my or may not know, Powershell uses the .NET 3.5 runtime per default.</p>

<p>Hence, the fix was to make Powershell use the .NET 4.0 runtime, where this bug is fixed. I figured out how to do this based on <a href="http://stackoverflow.com/questions/2094694/how-can-i-run-powershell-with-the-net-4-runtime">this entry</a> on <a href="http://www.stackoverflow.com">stackoverflow</a>.
</p>

<p>I then wrote this little Powershell snippet which changes Powershell on my machine to use .NET 4.0 instead of .NET 3.5:</p>

<p><pre name="code" class="csharp">if ([Environment]::Version.Major -lt 4) {
    $configFile = Join-Path $PSHOME -ChildPath '.\powershell.exe.config'
    if (-not(Test-Path $configFile)) {
        @'
&lt;?xml version="1.0"?&gt;
&lt;configuration&gt;
  &lt;startup useLegacyV2RuntimeActivationPolicy="true"&gt;
    &lt;supportedRuntime version="v4.0.30319" /&gt;
    &lt;supportedRuntime version="v2.0.50727" /&gt;
  &lt;/startup&gt;
&lt;/configuration&gt;
'@ | Out-File -FilePath $configFile -Encoding UTF8
        "Created $configFile"
    }
    'Restart powershell in order to make it run in .NET 4'
}</pre></p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kongsli.net%2Fnblog%2F2012%2F05%2F07%2Frunning-chocolatey-behind-an-authenticating-firewall%2F&amp;title=Running%20chocolatey%20behind%20an%20authenticating%20firewall" id="wpa2a_4"><img src="http://www.kongsli.net/nblog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kongsli.net/nblog/2012/05/07/running-chocolatey-behind-an-authenticating-firewall/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powershell gotchas: getting multiline string literals correct</title>
		<link>http://www.kongsli.net/nblog/2012/05/03/powershell-gotchas-getting-multiline-string-literals-correct/</link>
		<comments>http://www.kongsli.net/nblog/2012/05/03/powershell-gotchas-getting-multiline-string-literals-correct/#comments</comments>
		<pubDate>Thu, 03 May 2012 12:46:26 +0000</pubDate>
		<dc:creator>vidarkongsli</dc:creator>
				<category><![CDATA[Microsoft technologies]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Software development]]></category>
		<category><![CDATA[gotcha]]></category>
		<category><![CDATA[powershell gotcha]]></category>

		<guid isPermaLink="false">http://www.kongsli.net/nblog/?p=436</guid>
		<description><![CDATA[The gotcha here is that the opening token @' or @" has to be at the end of the line, and the closing token, '@ or "@, has to be a the beginning of a line. Wrong: @'1 2 3 &#8230; <a href="http://www.kongsli.net/nblog/2012/05/03/powershell-gotchas-getting-multiline-string-literals-correct/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The gotcha here is that the opening token <code>@'</code> or <code>@"</code> has to be at the end of the line, and the closing token, <code>'@</code> or <code>"@</code>, has to be a the beginning of a line.</p>

<p>Wrong:
<pre name="code" class="csharp">@'1
2
3
'@</pre>
<pre>Unrecognized token in source text.
At ...ps1:1 char:1
+  &lt;&lt;&lt;&lt; @'1
    + CategoryInfo          : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : UnrecognizedToken</pre>
<pre name="code" class="csharp">@'
1
2
3'@</pre>
<pre>The string starting:
At ...:12 char:6
+ $s =  &lt;&lt;&lt;&lt; @'
is missing the terminator: '@.
At ...ps1:34 char:3
+ #> &lt;&lt;&lt;&lt;
    + CategoryInfo          : ParserError: (1
2
3'@
:String) [], ParseException
    + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString</pre>
Correct:
<pre name="code" class="csharp">@'
1
2
3
'@</pre>
<pre>1
2
3</pre></p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kongsli.net%2Fnblog%2F2012%2F05%2F03%2Fpowershell-gotchas-getting-multiline-string-literals-correct%2F&amp;title=Powershell%20gotchas%3A%20getting%20multiline%20string%20literals%20correct" id="wpa2a_6"><img src="http://www.kongsli.net/nblog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kongsli.net/nblog/2012/05/03/powershell-gotchas-getting-multiline-string-literals-correct/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powershell gotchas: redirect to file encodes in Unicode</title>
		<link>http://www.kongsli.net/nblog/2012/04/20/powershell-gotchas-redirect-to-file-encodes-in-unicode/</link>
		<comments>http://www.kongsli.net/nblog/2012/04/20/powershell-gotchas-redirect-to-file-encodes-in-unicode/#comments</comments>
		<pubDate>Fri, 20 Apr 2012 09:56:13 +0000</pubDate>
		<dc:creator>vidarkongsli</dc:creator>
				<category><![CDATA[Microsoft technologies]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Software development]]></category>
		<category><![CDATA[gotcha]]></category>
		<category><![CDATA[powershell gotcha]]></category>

		<guid isPermaLink="false">http://www.kongsli.net/nblog/?p=425</guid>
		<description><![CDATA[The other day, I wrote a Powershell script that would manipulate a Windows command prompt file. After some troubleshooting (note to self: RTFM) I found Powershell file redirection encodes in Unicode, more specifically UCS-2 Little Endian. The problem in this &#8230; <a href="http://www.kongsli.net/nblog/2012/04/20/powershell-gotchas-redirect-to-file-encodes-in-unicode/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The other day, I wrote a Powershell script that would manipulate a Windows command prompt file. After some troubleshooting (note to self: RTFM) I found Powershell file redirection encodes in Unicode, more specifically UCS-2 Little Endian. The problem in this case is that <code>cmd.exe</code> does not understand Unicode. So, the follwing yields a not runnable file:
<pre name="code" class="csharp">@'
@echo off
echo Wi nøt trei a høliday in Sweden this ÿer?
'@ &gt; '.\Opening titles (unicode).cmd'
&amp; '.\Opening titles (unicode).cmd'</pre>
<pre>Output: '■@' is not recognized as an internal or external command,
operable program or batch file.</pre>
The trick is to use the <code>Out-File</code> Cmdlet instead and explicitly set the encoding. So, the following yields runnable code:
<pre name="code" class="csharp">@'
@echo off
echo Wi nøt trei a høliday in Sweden this ÿer?
'@ | Out-file '.\Opening titles (Ascii).cmd' -Encoding ASCII
&amp; '.\Opening titles (Ascii).cmd'</pre><pre>Output: Wi n?t trei a h?liday in Sweden this ?er?</pre>
In this case, it executes. However, the non-ASCII characters are not properly displayed. To achieve that as well, I used the following:
<pre name="code" class="csharp">@'
@echo off
echo Wi nøt trei a høliday in Sweden this ÿer?
'@ | Out-file '.\Opening titles (OEM).cmd' -Encoding OEM
&amp; '.\Opening titles (OEM).cmd'</pre><pre>Output: Wi nøt trei a høliday in Sweden this ÿer?</pre></p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kongsli.net%2Fnblog%2F2012%2F04%2F20%2Fpowershell-gotchas-redirect-to-file-encodes-in-unicode%2F&amp;title=Powershell%20gotchas%3A%20redirect%20to%20file%20encodes%20in%20Unicode" id="wpa2a_8"><img src="http://www.kongsli.net/nblog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kongsli.net/nblog/2012/04/20/powershell-gotchas-redirect-to-file-encodes-in-unicode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Powershell: another alternative to ternary operator</title>
		<link>http://www.kongsli.net/nblog/2012/02/23/powershell-another-alternative-to-ternary-operator/</link>
		<comments>http://www.kongsli.net/nblog/2012/02/23/powershell-another-alternative-to-ternary-operator/#comments</comments>
		<pubDate>Thu, 23 Feb 2012 13:13:05 +0000</pubDate>
		<dc:creator>vidarkongsli</dc:creator>
				<category><![CDATA[Microsoft technologies]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[powershell]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://www.kongsli.net/nblog/?p=401</guid>
		<description><![CDATA[In C# (as well as in Java and C++), you can use the ternary operator (?:) for a shorthand notation for conditionally assigning a value: var index = (a == "a") ? 1 : 2; In Powershell, such an operator &#8230; <a href="http://www.kongsli.net/nblog/2012/02/23/powershell-another-alternative-to-ternary-operator/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>
In C# (as well as in Java and C++), you can use the <a href="http://msdn.microsoft.com/en-us/library/ty67wk28%28v=vs.80%29.aspx">ternary operator (?:)</a> for a shorthand notation for conditionally assigning a value:
</p>

<p><pre class="csharp" name="code">
var index = (a == "a") ? 1 : 2;
</pre></p>

<p>
In Powershell, such an operator is (to my knowledge) not available. One solution is described <a href="http://blogs.msdn.com/b/powershell/archive/2006/12/29/dyi-ternary-operator.aspx">here</a>. As an alternative without having to create a function and alias, I suggest:
</p>

<p><pre class="csharp" name="code">
$index = @{$true=1;$false=2}[$a -eq 'a']
</pre></p>

<p>Mmmmm, one-liner FTW <img src='http://www.kongsli.net/nblog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kongsli.net%2Fnblog%2F2012%2F02%2F23%2Fpowershell-another-alternative-to-ternary-operator%2F&amp;title=Powershell%3A%20another%20alternative%20to%20ternary%20operator" id="wpa2a_10"><img src="http://www.kongsli.net/nblog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kongsli.net/nblog/2012/02/23/powershell-another-alternative-to-ternary-operator/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ASCII vs ISO-8859-1</title>
		<link>http://www.kongsli.net/nblog/2012/01/27/ascii-vs-iso-8859-1/</link>
		<comments>http://www.kongsli.net/nblog/2012/01/27/ascii-vs-iso-8859-1/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 07:36:55 +0000</pubDate>
		<dc:creator>vidarkongsli</dc:creator>
				<category><![CDATA[Microsoft technologies]]></category>
		<category><![CDATA[Software development]]></category>

		<guid isPermaLink="false">http://www.kongsli.net/nblog/?p=389</guid>
		<description><![CDATA[Note to self: var ascii7BitEncoding = Encoding.ASCII; // ASCII var ascii8BitEncodingIsh = Encoding.GetEncoding("iso-8859-1"); // Extended ASCII for almost all practical purposes Where Extended ASCII differs from ISO-8859-*, according to Wikipedia: One notable way in which ISO character sets differ from &#8230; <a href="http://www.kongsli.net/nblog/2012/01/27/ascii-vs-iso-8859-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>Note to self:</strong></p>

<p><pre class="csharp" name="code">
var ascii7BitEncoding = Encoding.ASCII; // ASCII
var ascii8BitEncodingIsh = Encoding.GetEncoding("iso-8859-1"); // Extended ASCII for almost all practical purposes
</pre></p>

<p>Where Extended ASCII differs from ISO-8859-*, according to <a title="Wikipedia:Extended ASCII" href="http://en.wikipedia.org/wiki/Extended_ASCII">Wikipedia</a>:</p>

<p><em>One notable way in which ISO character sets differ from code pages is that the character positions 128 to 159, corresponding to ASCII control characters with the high-order bit set, are specifically unused and undefined in the ISO standards, though they had often been used for printable characters in proprietary code pages, a breaking of ISO standards that was almost universal.</em></p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kongsli.net%2Fnblog%2F2012%2F01%2F27%2Fascii-vs-iso-8859-1%2F&amp;title=ASCII%20vs%20ISO-8859-1" id="wpa2a_12"><img src="http://www.kongsli.net/nblog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kongsli.net/nblog/2012/01/27/ascii-vs-iso-8859-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enabling Web Transforms when debugging ASP.NET apps</title>
		<link>http://www.kongsli.net/nblog/2012/01/13/enabling-web-transforms-when-debugging-asp-net-apps/</link>
		<comments>http://www.kongsli.net/nblog/2012/01/13/enabling-web-transforms-when-debugging-asp-net-apps/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 13:47:23 +0000</pubDate>
		<dc:creator>vidarkongsli</dc:creator>
				<category><![CDATA[Microsoft technologies]]></category>
		<category><![CDATA[Software development]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[aspdotnet]]></category>
		<category><![CDATA[msbuild]]></category>
		<category><![CDATA[visual studio]]></category>
		<category><![CDATA[web transforms]]></category>

		<guid isPermaLink="false">http://www.kongsli.net/nblog/?p=344</guid>
		<description><![CDATA[Web Transformations is a great feature. When a web application is packaged or published, the Web.config file is transformed dependent on which Visual Studio / MSBuild configuration you are running, enabling environment-specific settings to change accordingly. However, to my mind &#8230; <a href="http://www.kongsli.net/nblog/2012/01/13/enabling-web-transforms-when-debugging-asp-net-apps/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://msdn.microsoft.com/en-us/library/dd465326.aspx">Web Transformations</a> is a great feature. When a web application is packaged or published, the <code>Web.config</code> file is transformed dependent on which Visual Studio / MSBuild configuration you are running, enabling environment-specific settings to change accordingly.</p>

<p>However, to my mind there is a shortcoming. Since the transformation happens during packaging or publishing of the application, transformation rules do not take effect when debugging a web application (typically by hitting <strong>F5</strong> in Visual Studio) because the application is served from the project directory. Here&#8217;s how to solve this: essentially, we can change the the project setup so that the transformation happens right after the project build step. Here&#8217;s how:</p>

<h3>Step 1: Unload the project in Visual Studio</h3>

<p>In the Solution Explorer in Visual Studio, right-click on the project and select <strong>Unload project</strong> from the context menu:</p>

<p><a href="http://www.kongsli.net/nblog/wp-content/uploads/2011/12/unload_project.png"><img class="alignnone size-full wp-image-343" title="unload_project" src="http://www.kongsli.net/nblog/wp-content/uploads/2011/12/unload_project.png" alt="" width="469" height="724" /></a></p>

<h3>Step 2: Rename Web.config on the file system</h3>

<p>In the Windows Explorer, browse to the project directory, and rename <code>Web.config</code> to <code>Web.template.config</code>:</p>

<p><a href="http://www.kongsli.net/nblog/wp-content/uploads/2011/12/rename-web-config.png"><img src="http://www.kongsli.net/nblog/wp-content/uploads/2011/12/rename-web-config.png" alt="" title="rename-web-config" width="604" height="171" class="alignnone size-full wp-image-340" /></a></p>

<h3>Step 3: Rename Web.config in the project file</h3>

<p>What we will do here, is to rename the existing <code>Web.config</code> to <code>Web.template.config</code> in the project file (.csproj or .vbproj). This will be the file that we keep in the version control system, and the final <code>Web.config</code> will instead be generated for us when building the application.</p>

<p>In the Solutuion Explorer in Visual Studio, right-click on the project and select <strong>Edit &lt;project name&gt;</strong>:</p>

<p><a href="http://www.kongsli.net/nblog/wp-content/uploads/2011/12/edit-project.png"><img src="http://www.kongsli.net/nblog/wp-content/uploads/2011/12/edit-project.png" alt="" title="edit project" width="513" height="206" class="alignnone size-full wp-image-339" /></a></p>

<p>Search for &#8220;web.config&#8221; in the project file to locate where the <code>Web.config</code> and transformation files definitions. It looks something like so:</p>

<p><pre class="xml" name="code">
&lt;Content Include="Web.config" /&gt;
&lt;Content Include="Web.Debug.config"&gt;
   &lt;DependentUpon>Web.config&lt;/DependentUpon&gt;
&lt;/Content&gt;
&lt;Content Include="Web.Release.config"&gt;
   &lt;DependentUpon>Web.config&lt;/DependentUpon&gt;
&lt;/Content&gt;
</pre></p>

<p>In the project file, for instance on the line after the one with <code>Web.config</code>, add the following:</p>

<p><pre class="xml" name="code">
&lt;None Include="Web.template.config" /&gt;
</pre></p>

<p>Then, change the text of the <code>DependentUpon</code> element to read <code>Web.template.config</code> instead of <code>Web.config</code>. Finally, change the <code>Content</code> elements for for <code>Web.Debug.config</code> and <code>Web.Release.config</code> to <code>None</code> elements. This prevents these files from being included in the deployment package. They don&#8217;t need to be, as the transformations have already been run. All in all, the snippet from above should now read:</p>

<p><pre class="xml" name="code">
&lt;Content Include="Web.config" /&gt;
&lt;None Include="Web.template.config" /&gt;
&lt;None Include="Web.Debug.config"&gt;
   &lt;DependentUpon>Web.template.config&lt;/DependentUpon&gt;
&lt;/None&gt;
&lt;None Include="Web.Release.config"&gt;
   &lt;DependentUpon>Web.template.config&lt;/DependentUpon&gt;
&lt;/None&gt;
</pre></p>

<h3>Step 4: Running transformation when building</h3>

<p>Now that we have a reference to <code>Web.template.config</code> in the project file, the next step is to run the transformation during the build step. Add a custom target that runs the transformation and then include it at the begining of the build task using the {{BuildDependsOn}} property. The resulting XML snippet looks like so:</p>

<p><pre class="xml" name="code">
&lt;PropertyGroup&gt;
  &lt;BuildDependsOn&gt;
    CustomWebConfigTransform;
    $(BuildDependsOn);
  &lt;/BuildDependsOn&gt;
&lt;/PropertyGroup&gt;
&lt;Target Name="CustomWebConfigTransform"&gt;
   &lt;TransformXml&gt; source="Web.template.config"
      transform="Web.$(Configuration).config"
      destination="Web.config" /&gt;
&lt;/Target&gt;
</pre></p>

<p>Save the file and reload the project into the Visual Studio solution. Then, in the Solution Explorer, observe that the <code>Web.config</code> file now is denoted as missing, and that the <code>Web.template.config</code> is present with the two transformation files beneath it in the file tree:</p>

<p><a href="http://www.kongsli.net/nblog/wp-content/uploads/2011/12/solution-explorer-changed.png"><img src="http://www.kongsli.net/nblog/wp-content/uploads/2011/12/solution-explorer-changed.png" alt="" title="solution-explorer-changed" width="264" height="345" class="alignnone size-full wp-image-342" /></a></p>

<h3>Step 5: Test running transformations during build</h3>

<p>In this step, we will test that the transformations will be run when launching the application by hitting <code>F5</code> in Visual Studio. First, we need to create a configuration example in <code>Web.Debug.config</code>. Remove all the gunk that Microsoft so helpfully has filled the file with during project creation, and insert one simple <code>appSettings</code> entry, making the <code>Web.Debug.config</code> look like this:</p>

<p><pre class="xml" name="code">
&lt;configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"&gt;
  &lt;appSettings&gt;
    &lt;add key="Configuration" value="Debug" xdt:Transform="Insert"/&gt;
  &lt;/appSettings&gt;
&lt;/configuration&gt;
</pre></p>

<p>Take care to include the <code>xdt</code> XML namespace definition. Without it, the transformations will not be run.</p>

<p>Open up an <code>ASPX</code> page, for instance <code>Default.aspx</code>, and enter a label that will display the value of our confiugration setting:</p>

<p><pre class="xml" name="code">
&lt;p&gt;
   Configuration: &lt;asp:Label ID="Configuration" runat="server" /&gt;
&lt;/p&gt;</pre></p>

<p>Next, enter this in the code behind:</p>

<p><pre class="c-sharp" name="code">
protected void Page_Load(object sender, EventArgs e)
{
   Configuration.Text = ConfigurationManager.AppSettings["Configuration"];
}
</pre></p>

<p>Hit <strong>F5</strong> to run the application and verify that it in fact is able to read from the transformed <code>Web.config</code>:</p>

<p><a href="http://www.kongsli.net/nblog/wp-content/uploads/2011/12/result.png"><img src="http://www.kongsli.net/nblog/wp-content/uploads/2011/12/result.png" alt="" title="result" width="546" height="216" class="alignnone size-full wp-image-341" /></a></p>

<h3>Step 6: Disable transformations during packaging and publishing</h3>

<p>Since <code>msbuild</code> by default runs the transformations, we need to disable this to prevent the transformations to be applied twice. To do this, unload the project from the solution as we did in step 1, and then edit the project file in Visual Studio. For each of the configurations that you have in your solution, disable the built-in transformation runs by adding the <code>TransformWebConfigEnabled</code> element and setting it to false. Like so:</p>

<p><pre class="c-sharp" name="code">
&lt;PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "&gt;
   &lt;TransformWebConfigEnabled&gt;False&lt;/TransformWebConfigEnabled&gt;
   ...
&lt;/PropertyGroup&gt;
</pre></p>

<h3>Summary / other tweaks</h3>

<p>What we have achieved, is that the transformations are applied when building the application, making the transformed file available when running the application locally from Visual Studio. Another tip with regards to Web Transformations is to use the <a href="http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5">SlowCheetah</a> Visual Studio Add-in that Scott Hanselman has <a href="http://www.hanselman.com/blog/SlowCheetahWebconfigTransformationSyntaxNowGeneralizedForAnyXMLConfigurationFile.aspx">described very well here</a>. It will give you a nice transformation preview on the context menu in Visual Studio which is extremely helpful.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kongsli.net%2Fnblog%2F2012%2F01%2F13%2Fenabling-web-transforms-when-debugging-asp-net-apps%2F&amp;title=Enabling%20Web%20Transforms%20when%20debugging%20ASP.NET%20apps" id="wpa2a_14"><img src="http://www.kongsli.net/nblog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kongsli.net/nblog/2012/01/13/enabling-web-transforms-when-debugging-asp-net-apps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NLog: writing log entries to Azure Table Storage</title>
		<link>http://www.kongsli.net/nblog/2012/01/05/nlog-writing-log-entries-to-azure-table-storage/</link>
		<comments>http://www.kongsli.net/nblog/2012/01/05/nlog-writing-log-entries-to-azure-table-storage/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 13:49:20 +0000</pubDate>
		<dc:creator>vidarkongsli</dc:creator>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Microsoft technologies]]></category>
		<category><![CDATA[Software development]]></category>
		<category><![CDATA[azure]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[nlog]]></category>
		<category><![CDATA[tablestorage]]></category>

		<guid isPermaLink="false">http://www.kongsli.net/nblog/?p=372</guid>
		<description><![CDATA[In August last year, I blogged about how to get Log4Net log entries written to Azure Table Storage. In this article, I will show how the same thing can be easily achieved using NLog. The concepts in NLog is very &#8230; <a href="http://www.kongsli.net/nblog/2012/01/05/nlog-writing-log-entries-to-azure-table-storage/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In August last year, I blogged about how to get <a href="http://www.kongsli.net/nblog/2011/08/15/log4net-writing-log-entries-to-azure-table-storage/">Log4Net log entries written to Azure Table Storage</a>. In this article, I will show how the same thing can be easily achieved using <a href="http://nlog-project.org/">NLog</a>.</p>

<p>The concepts in NLog is very similar to Log4Net. More or less, replace the word &#8220;appender&#8221; in Log4Net lingo with &#8220;target&#8221;, and you&#8217;re game.</p>

<p>First, let&#8217;s create a class for log entries:</p>

<p><pre class="c-sharp" name="code">
public class LogEntry : TableServiceEntity
{
    public LogEntry()
    {
        var now = DateTime.UtcNow;
        PartitionKey = string.Format("{0:yyyy-MM}", now);
        RowKey = string.Format("{0:dd HH:mm:ss.fff}-{1}", now, Guid.NewGuid());
    }
    #region Table columns
    public string Message { get; set; }
    public string Level { get; set; }
    public string LoggerName { get; set; }
    public string RoleInstance { get; set; }
    public string DeploymentId { get; set; }
    public string StackTrace { get; set; }
    #endregion
}
</pre></p>

<p>Next, we need to do is to create a class that represents the table storage service. It needs to inherit from <code>TableServiceContext</code>:</p>

<p><pre class="c-sharp" name="code">
public class LogServiceContext : TableServiceContext
{
    public LogServiceContext(string baseAddress, StorageCredentials credentials) : base(baseAddress, credentials) { }
    internal void Log(LogEntry logEntry)
    {
        AddObject("LogEntries", logEntry);
        SaveChanges();
    }
    public IQueryable&lt;LogEntry&gt; LogEntries
    {
        get
        {
            return CreateQuery&lt;LogEntry&gt;("LogEntries");
        }
    }
}
</pre></p>

<p>Finally, as far as code is concerned, a class that is a custom NLog target that gets called when the NLog framework needs to log something:</p>

<p><pre class="c-sharp" name="code">
[Target("AzureStorage")]
public class AzureStorageTarget : Target
{
    private LogServiceContext _ctx;
    private string _tableEndpoint;
    [Required]
    public string TableStorageConnectionStringName { get; set; }
    protected override void InitializeTarget()
    {
        base.InitializeTarget();
        var cloudStorageAccount =
            CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(TableStorageConnectionStringName));
        _tableEndpoint = cloudStorageAccount.TableEndpoint.AbsoluteUri;
        CloudTableClient.CreateTablesFromModel(typeof(LogServiceContext), _tableEndpoint, cloudStorageAccount.Credentials);
        _ctx = new LogServiceContext(cloudStorageAccount.TableEndpoint.AbsoluteUri, cloudStorageAccount.Credentials);
    }
    protected override void Write(LogEventInfo loggingEvent)
    {
        Action doWriteToLog = () =>
        {
            try
            {
                _ctx.Log(new LogEntry
                {
                    RoleInstance = RoleEnvironment.CurrentRoleInstance.Id,
                    DeploymentId = RoleEnvironment.DeploymentId,
                    Timestamp = loggingEvent.TimeStamp,
                    Message = loggingEvent.FormattedMessage,
                    Level = loggingEvent.Level.Name,
                    LoggerName = loggingEvent.LoggerName,
                    StackTrace = loggingEvent.StackTrace != null ? loggingEvent.StackTrace.ToString() : null
                });
            }
            catch (DataServiceRequestException e)
            {
                InternalLogger.Error(string.Format("{0}: Could not write log entry to {1}: {2}",
                    GetType().AssemblyQualifiedName, _tableEndpoint, e.Message), e);
            }
        };
        doWriteToLog.BeginInvoke(null, null);
    }
}
</pre></p>

<p>So, to make it work, we need to register the target with the NLog framework. This is done in the <code>NLog.config</code> file:</p>

<p><pre class="c-sharp" name="code">
&lt;?xml version="1.0"?&gt;
&lt;nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
  &lt;extensions&gt;
    &lt;add assembly="Demo.NLog.Azure" /&gt;
  &lt;/extensions&gt;
  &lt;targets&gt;
    &lt;target name="azure" type="AzureStorage" tableStorageConnectionStringName="Log4Net.ConenctionString" /&gt;
  &lt;/targets&gt;
  &lt;rules&gt;
    &lt;logger name="*" minlevel="Info" writeTo="azure" /&gt;
  &lt;/rules&gt;
&lt;/nlog&gt;
</pre></p>

<p>
For information about how to set your <code>ServiceDefinition.csdef</code> and <code>ServiceConfiguration.cscfg</code> files, see my <a href="http://www.kongsli.net/nblog/2011/08/15/log4net-writing-log-entries-to-azure-table-storage/">previous post</a>.You can find the code for this example on <a href="https://github.com/vidarkongsli/azuretablestoragetarget">GitHub</a>. Suggestions for improvement are very welcome.
</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kongsli.net%2Fnblog%2F2012%2F01%2F05%2Fnlog-writing-log-entries-to-azure-table-storage%2F&amp;title=NLog%3A%20writing%20log%20entries%20to%20Azure%20Table%20Storage" id="wpa2a_16"><img src="http://www.kongsli.net/nblog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kongsli.net/nblog/2012/01/05/nlog-writing-log-entries-to-azure-table-storage/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Getting user information programmatically from Windows Identity Foundation</title>
		<link>http://www.kongsli.net/nblog/2011/08/29/getting-user-information-programmatically-from-windows-identity-foundation/</link>
		<comments>http://www.kongsli.net/nblog/2011/08/29/getting-user-information-programmatically-from-windows-identity-foundation/#comments</comments>
		<pubDate>Mon, 29 Aug 2011 12:54:27 +0000</pubDate>
		<dc:creator>vidarkongsli</dc:creator>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Microsoft technologies]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Software development]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[acs]]></category>
		<category><![CDATA[asp.net]]></category>
		<category><![CDATA[aspdotnet]]></category>
		<category><![CDATA[azure]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[wif]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.kongsli.net/nblog/?p=302</guid>
		<description><![CDATA[You can use the Windows Identity Foundation SDK to replace the authentication scheme of your ASP.NET web application. Most notably, this is useful for making your application claims-aware, which allows it to seamlessly play together with solutions like Active Directory &#8230; <a href="http://www.kongsli.net/nblog/2011/08/29/getting-user-information-programmatically-from-windows-identity-foundation/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>You can use the Windows Identity Foundation SDK to replace the authentication scheme of your ASP.NET web application. Most notably, this is useful for making your application claims-aware, which allows it to seamlessly play together with solutions like Active Directory Federation Services or the Windows Azure AppFabric Access Service. This is useful for a various number of SSO and federated authentication scenarios.</p>

<p>Basically, what you do is that you switch off the built-in authentication in ASP.NET like forms-based authentication, and let WIF act as a proxy in front of your application. WIF uses the authorization settings in <code>web.config</code> (/configuration/system.web/authorization and /configuration/location/system.web/authorization elements) and authenticates the user before the ASP.NET application receives the request. See <a href="http://msdn.microsoft.com/en-us/library/ee517293.aspx" title="MSDN: WS-Federated Authentication Module Overview">WS-Federated Authentication Module Overview</a> for details</p>

<p>So, when the application receives the request, the user is already authenticated, which is fine. However, there are times when the application needs to know who the user is, or getting access to the other claims that were provided from the identity service. Luckily, this is available on the HTTP context. Say, for instance, if you wish to find the email address of the logged-in user, you can do it like so:</p>

<p><pre class="c-sharp" name="code">
protected void Page_Load(object sender, EventArgs e)
{
    var claimsIdentity = Context.User.Identity as IClaimsIdentity;
    foreach (var claim in claimsIdentity.Claims)
    {
        if (claim.ClaimType == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress")
        {
            var email = claim.Value;
        }
    }
}
</pre></p>

<p>If the user was authenticated using claims, <code>Context.User.Identity</code> will be an <code>IClaimsIdentity</code> which will contain a number of claims about the user. We can then iterate over these claims to find the one that we want.</p>

<p>The claim types are denoted using XML namespaces, which are a little bit cumbersome to work with. So, to make it easier to access, we iterate over the list of claims, and make all the claims available on a common object:</p>

<p><pre class="c-sharp" name="code">
public static class IdentityExtension
{
    public static DynamicUser GetUserFromClaims(this HttpContext context)
    {
        var claimsIdentity = context.User.Identity as IClaimsIdentity;
        if (claimsIdentity == null) throw new FailedAuthenticationFaultException();
        return new DynamicUser(claimsIdentity.Claims);
    }
}
public class DynamicUser : DynamicObject
{
    private readonly ClaimCollection _claims;
    public DynamicUser(ClaimCollection claims)
    {
        _claims = claims;
        Id = ClaimsValue("nameidentifier")[0];
    }
    public string Id { get; private set; }
    public bool IsInRole(string role)
    {
        return ClaimsValue("role").Any(c =&gt; c.Equals(role, StringComparison.OrdinalIgnoreCase));
    }
    private string[] ClaimsValue(string claimSuffix)
    {
        return _claims.Where(c =&gt; c.ClaimType.EndsWith(claimSuffix)).Select(c =&gt; c.Value).ToArray();
    }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        var claimValue = ClaimsValue(binder.Name.ToLowerInvariant());
        if (claimValue.Length == 0)
        {
            return base.TryGetMember(binder, out result);
        }
        if (claimValue.Length == 1)
        {
            result = claimValue[0];
        }
        else
        {
            result = claimValue;
        }
        return true;
    }
}
</pre></p>

<p>Then, we can access the claim values using a prefix of the actual XML namespace of the claim type:</p>

<p><pre class="c-sharp" name="code">
protected void Page_Load(object sender, EventArgs e)
{
    var user = Context.GetUserFromClaims();
    var id = user.Id;
    var username = user.Name; // "John Doe"
}
</pre></p>

<p>When hooking up the application to Windows Azure AppFabric Access Control Service (ACS), which claims that the application will receive depends on your <a href="http://msdn.microsoft.com/en-us/library/gg185923.aspx">rule group configuration</a>. Here are some examples:</p>

<table border="1">
<tr><th>Claim type</th><th>Shorthand</th><th>Example value</th></tr>
<tr>
<td>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier</td>
<td><code>user.Id</code></td>
<td>NHsTR1UXFI9xYk1xIRUNfucZ4/a5OWiILHlNyNEXozP=</td>
</tr>
<tr>
<td>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name</td>
<td><code>user.Name</code></td>
<td>John Doe</td>
</tr>
<tr>
<td>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress</td>
<td><code>user.Emailaddress</code></td>
<td>john.doe@hotmail.com</td>
</tr>
</table>

<p>If you set up <a href="http://msdn.microsoft.com/en-us/library/gg185923.aspx">role claim rules</a> in ACS, you can even get information about the user&#8217;s roles so that you can do authorization in the code:</p>

<p><pre class="c-sharp" name="code">
protected void Page_Load(object sender, EventArgs e)
{
    var user = Context.GetUserFromClaims();
    var isAdmin = user.IsInRole("administrator"):
}
</pre></p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kongsli.net%2Fnblog%2F2011%2F08%2F29%2Fgetting-user-information-programmatically-from-windows-identity-foundation%2F&amp;title=Getting%20user%20information%20programmatically%20from%20Windows%20Identity%20Foundation" id="wpa2a_18"><img src="http://www.kongsli.net/nblog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kongsli.net/nblog/2011/08/29/getting-user-information-programmatically-from-windows-identity-foundation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Log4Net: writing log entries to Azure Table Storage</title>
		<link>http://www.kongsli.net/nblog/2011/08/15/log4net-writing-log-entries-to-azure-table-storage/</link>
		<comments>http://www.kongsli.net/nblog/2011/08/15/log4net-writing-log-entries-to-azure-table-storage/#comments</comments>
		<pubDate>Mon, 15 Aug 2011 12:09:38 +0000</pubDate>
		<dc:creator>vidarkongsli</dc:creator>
				<category><![CDATA[Azure]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Microsoft technologies]]></category>
		<category><![CDATA[Software development]]></category>
		<category><![CDATA[azure]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[log4net]]></category>
		<category><![CDATA[tablestorage]]></category>

		<guid isPermaLink="false">http://www.kongsli.net/nblog/?p=318</guid>
		<description><![CDATA[Earlier, I blogged about how one can leverage Azure Diagnostics to easily set up Log4Net for your application running in Azure, and how to customize the log entries for the Azure environment. An alternative to doing this two-step process of &#8230; <a href="http://www.kongsli.net/nblog/2011/08/15/log4net-writing-log-entries-to-azure-table-storage/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Earlier, I blogged about how one can <a href="http://www.kongsli.net/nblog/2011/08/03/using-log4net-in-azure-compute/">leverage Azure Diagnostics</a> to easily set up <a href="http://logging.apache.org/log4net/">Log4Net</a> for your application running in Azure, and <a href="http://www.kongsli.net/nblog/2011/08/08/customizing-log4net-log-entries-on-azure/">how to customize the log entries for the Azure environment</a>.</p>

<p>An alternative to doing this two-step process of first writing to the local disk and then transfer the logs to Azure blob storage, is to write the log entries directly to Azure table storage (or in principal, to Azure blob storage for that matter). This is what I will do here.</p>

<p>Each log entry that the application writes will be a single row in a table in the Azure Table Storage. The log message itself and various meta data about it will be inserted into separate columns in the table. In order to achieve this, we first create a class that represents each entry in the table:</p>

<p><pre class="c-sharp" name="code">
public class LogEntry : TableServiceEntity
{
    public LogEntry()
    {
        var now = DateTime.UtcNow;
        PartitionKey = string.Format("{0:yyyy-MM}", now);
        RowKey = string.Format("{0:dd HH:mm:ss.fff}-{1}", now, Guid.NewGuid());
    }
    #region Table columns
    public string Message { get; set; }
    public string Level { get; set; }
    public string LoggerName { get; set; }
    public string Domain { get; set; }
    public string ThreadName { get; set; }
    public string Identity { get; set; }
    public string RoleInstance { get; set; }
    public string DeploymentId { get; set; }
    #endregion
}
</pre></p>

<p>Note that the <code>PartitionKey</code> is the current year and month, and the <code>RowKey</code> is a combination of the date, time and a GUID. This is done to make the querying of the log entries efficient for our purpose. So, the next thing we need to do is to create a class that represents the table storage service. It needs to inherit from <code>TableServiceContext</code>:</p>

<p><pre class="c-sharp" name="code">
internal class LogServiceContext : TableServiceContext
{
    public LogServiceContext(string baseAddress, StorageCredentials credentials) : base(baseAddress, credentials) {}
    internal void Log(LogEntry logEntry)
    {
        AddObject("LogEntries", logEntry);
        SaveChanges();
    }
    public IQueryable&lt;LogEntry&gt; LogEntries
    {
        get
        {
            return CreateQuery&lt;LogEntry&gt;("LogEntries");
        }
    }
}
</pre></p>

<p>The method that we will actually use in our code is the <code>Log</code> method which takes a <code>LogEntry</code> instance and persists it to table storage. What we need next, is to create a new Appender for Log4Net which interacts with the table store to store the log entries:</p>

<p><pre class="c-sharp" name="code">
public class AzureTableStorageAppender : AppenderSkeleton
{
    public string TableStorageConnectionStringName { get; set; }
    private LogServiceContext _ctx;
    private string _tableEndpoint;
    public override void ActivateOptions()
    {
        base.ActivateOptions();
        var cloudStorageAccount =
            CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(TableStorageConnectionStringName));
        _tableEndpoint = cloudStorageAccount.TableEndpoint.AbsoluteUri;
        CloudTableClient.CreateTablesFromModel(typeof(LogServiceContext), _tableEndpoint, cloudStorageAccount.Credentials);
        _ctx = new LogServiceContext(cloudStorageAccount.TableEndpoint.AbsoluteUri, cloudStorageAccount.Credentials);
    }
    protected override void Append(LoggingEvent loggingEvent)
    {
        Action doWriteToLog = () =&gt; {
            try
            {
                _ctx.Log(new LogEntry
                {
                    RoleInstance = RoleEnvironment.CurrentRoleInstance.Id,
                    DeploymentId = RoleEnvironment.DeploymentId,
                    Timestamp = loggingEvent.TimeStamp,
                    Message = loggingEvent.RenderedMessage,
                    Level = loggingEvent.Level.Name,
                    LoggerName = loggingEvent.LoggerName,
                    Domain = loggingEvent.Domain,
                    ThreadName = loggingEvent.ThreadName,
                    Identity = loggingEvent.Identity
                });
            }
            catch (DataServiceRequestException e)
            {
                ErrorHandler.Error(string.Format("{0}: Could not write log entry to {1}: {2}",
                    GetType().AssemblyQualifiedName, _tableEndpoint, e.Message));
            }
        };
        doWriteToLog.BeginInvoke(null, null);
    }
}
</pre></p>

<p>In the code above, the actually writing to the log is done asynchronically in order to prevent the log write to slow down the request handling. We are now done with all the coding. What is left is to use our new <code>AzureTableStorageAppender</code>. Here is the <code>log4net.config</code>:</p>

<p><pre class="xml" name="code">
&lt;log4net&gt;
  &lt;appender name="AzureTableStoreAppender" type="Demo.Log4Net.Azure.AzureTableStorageAppender, Demo.Log4Net.Azure"&gt;
    &lt;param name="TableStorageConnectionStringName" value="Log4Net.ConenctionString" /&gt;
  &lt;/appender&gt;
  &lt;root&gt;
    &lt;level value="DEBUG" /&gt;
    &lt;appender-ref ref="AzureTableStoreAppender" /&gt;
  &lt;/root&gt;
&lt;/log4net&gt;
</pre></p>

<p>Notice the <code>TableSTorageConnectionStringName</code> attribute of the <code>param</code> element in the configuration. It corresponds to the property of the same name in the <code>AzureTableStorageAppender</code>. Furthermore, take take notice that it&#8217;s value is <code>'Log4Net.ConnectionString'</code>, which corresponds to a custom configuration setting that we will add to <code>ServiceDefinition.csdef</code> file:</p>

<p><pre class="xml" name="code">
&lt;ServiceDefinition ...&gt;
  &lt;WebRole ...&gt;
    &lt;ConfigurationSettings&gt;
      &lt;Setting name="Log4Net.ConenctionString"/&gt;
    &lt;/ConfigurationSettings&gt;
    ...
  &lt;/WebRole&gt;
&lt;/ServiceDefinition&gt;
</pre></p>

<p>We also need to give the <code>Log4Net.ConfigurationString</code> setting a value in the <code>ServiceConfiguration.cscfg</code> file. It should be a connection string that points to the storage account to use for storing the log entries. In this example, let&#8217;s use the development storage:</p>

<p><pre class="xml" name="code">
&lt;ServiceConfiguration ...&gt;
  &lt;Role ...&gt;
    &lt;ConfigurationSettings&gt;
      &lt;Setting name="Log4Net.ConenctionString" value="UseDevelopmentStorage=true"/&gt;
    &lt;/ConfigurationSettings&gt;
  &lt;/Role&gt;
&lt;/ServiceConfiguration&gt;
</pre></p>

<p>&#8230;and that&#8217;s it. You should now find the log entries in the table storage:</p>

<p><a href="http://www.kongsli.net/nblog/wp-content/uploads/2011/08/Skjermbilde-2011-08-03-kl.-12.57.21.png"><img src="http://www.kongsli.net/nblog/wp-content/uploads/2011/08/Skjermbilde-2011-08-03-kl.-12.57.21.png" alt="" title="Log entries in table storage" width="924" height="149" class="alignnone size-full wp-image-324" /></a></p>

<p>You can find the code for this example on <a href="https://github.com/vidarkongsli/azuretablestorageappender">GitHub</a>. Suggestions for improvement are very welcome.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kongsli.net%2Fnblog%2F2011%2F08%2F15%2Flog4net-writing-log-entries-to-azure-table-storage%2F&amp;title=Log4Net%3A%20writing%20log%20entries%20to%20Azure%20Table%20Storage" id="wpa2a_20"><img src="http://www.kongsli.net/nblog/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kongsli.net/nblog/2011/08/15/log4net-writing-log-entries-to-azure-table-storage/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

