<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>vibrantcode</title>
    <link>http://vibrantcode.com/</link>
    <atom:link href="http://vibrantcode.com/blog/rss.xml" rel="self" type="application/rss+xml" />
    <description>Ooh, pretty code!</description>
    <language>en-us</language>
    <pubDate>Mon, 29 Apr 2013 16:16:52 -0700</pubDate>
    <lastBuildDate>Mon, 29 Apr 2013 16:16:52 -0700</lastBuildDate>

    
    <item>
      <title>Full Width Azure Portal for Big Monitors!</title>
      <link>http://vibrantcode.com/2013/04/29/full-width-azure-portal-for-big-monitors</link>
      <pubDate>Mon, 29 Apr 2013 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/2013/04/29/full-width-azure-portal-for-big-monitors</guid>
      <description>&lt;p&gt;&lt;strong&gt;DISCLAIMER:&lt;/strong&gt; I work on the Azure team, but not on the portal. I think the portal is great, I just prefer a full-width layout. Use &lt;strong&gt;at your own risk&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I use the Azure portal A LOT. Since &lt;a href='nuget.org'&gt;nuget.org&lt;/a&gt; is hosted on Azure, that&amp;#8217;s probably not a shock :). One thing I don&amp;#8217;t like (personal preference, I know some people like it) is that it&amp;#8217;s a fixed-width site. I have all this space on my monitor going unused!&lt;/p&gt;
&lt;img src='/assets/2013-04-29-full-width-azure-portal-for-big-monitors/FixedWidthSadness.png' alt='Boo. Fixed Width :(' style='height: 300px;' /&gt;
&lt;p&gt;You know what would look better? A full width layout:&lt;/p&gt;
&lt;img src='/assets/2013-04-29-full-width-azure-portal-for-big-monitors/FullWidthHappiness.png' alt='Yay! Full Width :)' style='height: 300px;' /&gt;
&lt;p&gt;Fortunately, it&amp;#8217;s easy to make it look like that, at least on Chrome. First, download the &lt;a href='https://chrome.google.com/webstore/detail/stylish/fjnbnpbmkenffdnngjfgmeleoegfcffe?hl=en'&gt;Stylish&lt;/a&gt; extension.&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/2013-04-29-full-width-azure-portal-for-big-monitors/DownloadStylish.png' alt='Download Stylish' /&gt;&lt;/p&gt;

&lt;p&gt;Then, click the new Stylish button on your toolbar and choose &amp;#8220;Manage installed styles&amp;#8221;&lt;/p&gt;

&lt;p&gt;&lt;img src='/assets/2013-04-29-full-width-azure-portal-for-big-monitors/StylishButton.png' alt='Click Dat Button!' /&gt;&lt;/p&gt;

&lt;p&gt;Choose &amp;#8220;Write new style&amp;#8221; to go to the style editor. Enter the following CSS and mark it to run for all URLs on the domain &amp;#8220;manage.windowsazure.com&amp;#8221;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#headerbar-wrapper {
	width: 100%;
	margin-left: 0;
	left: 0;
}
#fxshell-navpane {
	left: 0;
	margin-left: 0;
}
#drawer {
	margin-left: 0;
	left: 0;
	width: 100%;
}
#aux-foreground {
	width: 100%;
	left: 0;
	margin-left: 0;
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I also put it on a Gist here: &lt;a href='https://gist.github.com/anurse/5485124'&gt;https://gist.github.com/anurse/5485124&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save the stylesheet, reload the portal and POOF, instant full-width layout! Enjoy!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Lambdas vs. Method Groups</title>
      <link>http://vibrantcode.com/2013/02/19/lambdas-vs-method-groups</link>
      <pubDate>Tue, 19 Feb 2013 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/2013/02/19/lambdas-vs-method-groups</guid>
      <description>&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Due to a glitch in my code I miscalculated the difference. It has been updated. See full history of the code in the &lt;a href='https://gist.github.com/anurse/4992468'&gt;Gist&lt;/a&gt;. The outcome is still essentially the same :)&lt;/p&gt;

&lt;p&gt;I was talking with &lt;a href='https://twitter.com/davidfowl'&gt;David Fowler&lt;/a&gt; when he mentioned something I found surprising: &amp;#8220;Lambdas are more efficient than Method Groups&amp;#8221;. My initial reaction was that he was entirely wrong, but he explained why and then I decided to do some analysis. Here&amp;#8217;s what I found.&lt;/p&gt;

&lt;p&gt;I wrote a simple program that would pass a method group in to a method in a big loop:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;for (int i = 0; i &amp;lt; Iterations; i++)
{
	Call(Dump);
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And later on, it tried the same with a simple lambda&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;for (int i = 0; i &amp;lt; Iterations; i++)
{
	Call(s =&amp;gt; Dump(s));
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Where Call takes an Action&amp;#60;string&amp;#62; and Dump takes a single string argument and just does nothing:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;private static void Call(Action&amp;lt;string&amp;gt; act)
{
	act(&amp;quot;Hi!&amp;quot;);
}

private static void Dump(string str)
{
    
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;See the full code for the program as a &lt;a href='https://gist.github.com/anurse/4992468'&gt;Gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I put in some simple Stopwatch-based timing and Console.ReadLine calls to allow me to advance the app through the steps slowly. The results from the Stopwatch (which timed the whole process and took an average) were interesting on their own. I pre-JIT the methods by calling them outside the loops first, and with 100,000,000 iterations, I got this output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Running Method Group Test
Finished Method Group Test
Elapsed: 1.5171E+006ns
Average: 1.5171E-002ns
High-Precision? Yes
Press Enter to Continue

Running Lambda Test
Finished Lambda Test
Elapsed: 9.9125E+005ns
Average: 9.9125E-003ns
High-Precision? Yes
Press Enter to End&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The lambda case is noticibly faster! Note the difference in exponent (we&amp;#8217;re dealing with tiny numbers). Ok, so not much faster, but still, that&amp;#8217;s a significant result.&lt;/p&gt;

&lt;p&gt;Now, what about memory. So I pulled up perfmon and added the .NET &amp;#8220;Allocated Bytes/sec&amp;#8221; counter. I&amp;#8217;m not sure if that&amp;#8217;s the right one, but it certainly seemed to illustrate the point. This is what I saw:&lt;/p&gt;
&lt;img src='/assets/2013-02-19-lambdas-vs-method-groups/graph.gif' alt='Perfmon' /&gt;
&lt;p&gt;The big spike at the beginning (highlighted in Orange) is the Method Group round. The flat line (highlighted in Green) is the Lambda round. This must be where the problem lies.&lt;/p&gt;

&lt;p&gt;Sure enough, looking at the code, we see something interesting. To simplify, I&amp;#8217;ve made simple instance methods that just perform the call with a method group and a lambda (see the &lt;a href='https://gist.github.com/anurse/4992468'&gt;Gist&lt;/a&gt;). Now to decompile them.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;.method private hidebysig instance void MethodGroup() cil managed
{
    .maxstack 8
    L_0000: nop 
    L_0001: ldnull 
    L_0002: ldftn void Curious.Program::Dump(string)
    L_0008: newobj instance void [mscorlib]System.Action`1&amp;lt;string&amp;gt;::.ctor(object, native int)
    L_000d: call void Curious.Program::Call(class [mscorlib]System.Action`1&amp;lt;string&amp;gt;)
    L_0012: nop 
    L_0013: ret 
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;First the one with the Method Group (above). Hmm&amp;#8230; at L_0008 we see that we&amp;#8217;re creating a new delegate and putting the function pointer to Dump in. Make sense. So why doesn&amp;#8217;t the lambda version create the same amount of memory?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;.method private hidebysig instance void Lambda() cil managed
{
    .maxstack 8
    L_0000: nop 
    L_0001: ldsfld class [mscorlib]System.Action`1&amp;lt;string&amp;gt; Curious.Program::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate5
    L_0006: brtrue.s L_001b
    L_0008: ldnull 
    L_0009: ldftn void Curious.Program::&amp;lt;Lambda&amp;gt;b__4(string)
    L_000f: newobj instance void [mscorlib]System.Action`1&amp;lt;string&amp;gt;::.ctor(object, native int)
    L_0014: stsfld class [mscorlib]System.Action`1&amp;lt;string&amp;gt; Curious.Program::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate5
    L_0019: br.s L_001b
    L_001b: ldsfld class [mscorlib]System.Action`1&amp;lt;string&amp;gt; Curious.Program::CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate5
    L_0020: call void Curious.Program::Call(class [mscorlib]System.Action`1&amp;lt;string&amp;gt;)
    L_0025: nop 
    L_0026: ret 
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Well, it certainly does more. But the key parts start at L_0001. The first thing this code does is check if the &amp;#8220;CS$&amp;lt;&amp;gt;9__CachedAnonymousMethodDelegate5&amp;#8221; member has a value. If not, it fills it in, at L_0014. But if it DOES have a value, the code just invokes that cached value! BINGO! The Method Group version allocates a new object &lt;strong&gt;every single time it is run&lt;/strong&gt; whereas the lambda version uses an instance (or static, as necessary) field to cache the delegate.&lt;/p&gt;

&lt;p&gt;So, what does this mean for you? Well, probably not much. Notice that all these numbers were tiny, so we&amp;#8217;re talking about micro-optimizations. In fact, the most important take-away here is to remember that just because something &lt;strong&gt;seems&lt;/strong&gt; faster, doesn&amp;#8217;t mean it &lt;strong&gt;is&lt;/strong&gt; faster. In David&amp;#8217;s case, he discovered this in SignalR because they have a non-trivial number of lambdas allocated &lt;strong&gt;per connection&lt;/strong&gt;, and there can be a &lt;strong&gt;LOT&lt;/strong&gt; of connections. I know that I&amp;#8217;ll probably switch to using Lambdas, just because it doesn&amp;#8217;t seem to have any ill effects and if it saves us a few bytes, why not.&lt;/p&gt;

&lt;p&gt;Please do note that I&amp;#8217;m no performance expert. If you see a problem in this post, please tell me! It&amp;#8217;s possible I&amp;#8217;ve gotten this completely wrong somehow, so if this kind of performance is crucial to your app, you should definitely do your own profiling! And remember, the only way to make performance gains is to &lt;strong&gt;measure measure measure&lt;/strong&gt;. You can&amp;#8217;t just eyeball perf ;).&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Look Ma! No GAC! Razor IntelliSense without GACing</title>
      <link>http://vibrantcode.com/2012/06/06/look-ma-no-gac</link>
      <pubDate>Wed, 06 Jun 2012 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/2012/06/06/look-ma-no-gac</guid>
      <description>&lt;p&gt;If you&amp;#8217;ve done any work with the open-source ASP.Net Web Stack (on &lt;a href='http://aspnetwebstack.codeplex.com'&gt;Codeplex&lt;/a&gt;!) then you may have encountered one annoying issue: If you install an MVC 4 release, your source code version of MVC stops working. This is because our releases put the assemblies in the Global Assembly Cache, which is basically a special folder which overrides the Bin folder of your application. There are many reasons we do this, for example it is required if you are going to NGen an assembly. But specific reasons aside, the fact is that we install our assemblies in the GAC and that isn&amp;#8217;t likely to change in &amp;#8220;v2&amp;#8221; (MVC4/WebPages2/Razor2). So, how can we start working around this problem?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WARNING&lt;/strong&gt;: This is totally unsupported. I&amp;#8217;m happy to help in the comments but if you call Product Support they won&amp;#8217;t help you with this!&lt;/p&gt;

&lt;h3 id='step_0_capture_binaries'&gt;Step 0: Capture Binaries&lt;/h3&gt;

&lt;p&gt;Before you go uninstalling stuff, you should do one of these two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Grab the assemblies necessary for VS BEFORE uninstalling OR&lt;/li&gt;

&lt;li&gt;Be prepared to build new ones from source&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you aren&amp;#8217;t prepared to do #2, make sure you do #1! The Assemblies are in &lt;code&gt;C:\Program Files (x86)\Microsoft ASP.Net&lt;/code&gt;. Here&amp;#8217;s the full list of the ones you need, collect them and copy them into a separate folder (because Step 1 will delete them):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System.Web.Razor.dll&lt;/li&gt;

&lt;li&gt;System.Web.WebPages.Razor.dll&lt;/li&gt;

&lt;li&gt;System.Web.WebPages.Deployment.dll&lt;/li&gt;

&lt;li&gt;System.Web.WebPages.dll&lt;/li&gt;

&lt;li&gt;System.Web.Mvc.dll&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id='step_1_ungacing'&gt;Step 1: UnGACing&lt;/h3&gt;

&lt;p&gt;The first step is simply to remove the assemblies from the GAC. We only need to remove the &amp;#8220;V2&amp;#8221; Assemblies (&amp;#8220;V4&amp;#8221; for MVC related assemblies) because the GAC&amp;#8217;d copy of v1 (v3 for MVC) won&amp;#8217;t interfere with a version you build from source. NOTE: This will put Razor IntelliSense and other Visual Studio features relating to MVC in a somewhat broken state, but we&amp;#8217;ll fix that in Step 2.&lt;/p&gt;

&lt;p&gt;The first thing you might notice if you try to remove our assemblies from the GAC in the &amp;#8220;usual&amp;#8221; way is that they are locked by Windows Installer:&lt;/p&gt;
&lt;img src='https://s3.amazonaws.com/vibrantcode-res/blogcontent/2012-06-06-look-ma-no-gac/1-ungac.PNG' alt='Razor assemblies are locked by Windows Installer' /&gt;
&lt;p&gt;Ok, that kinda sucks. But fortunately this actually works to our benefit because we can use Windows Installer to remove the assemblies for us! If you installed MVC4/WebPages2 for Visual Studio 2010, this is easy, just go to Add/Remove Programs and uninstall the following two entries: &amp;#8220;Microsoft ASP.Net MVC 4 Runtime&amp;#8221; and &amp;#8220;Microsoft ASP.Net WebPages 2 Runtime&amp;#8221;. &lt;strong&gt;DO NOT&lt;/strong&gt; remove the matching Visual Studio tools entries!&lt;/p&gt;

&lt;p&gt;If you installed Visual Studio 2012, we don&amp;#8217;t actually add our individual components to the Add/Remove Programs list in order to give you just one thing to uninstall (Visual Studio 2012). But, you can still uninstall our components! It just takes a little PowerShell Magic. So, open up an Admin PowerShell prompt (don&amp;#8217;t worry, these are all built-in commands so copy-paste away)&lt;/p&gt;

&lt;p&gt;First, run this command to uninstall ASP.Net MVC 4:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gwmi Win32_Product | where { $_.Name -eq &amp;quot;Microsoft ASP.Net MVC 4 Runtime&amp;quot; } | ForEach { $msi = Convert-Path &amp;quot;$($_.InstallSource)\*.msi&amp;quot;; msiexec /x $msi }&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Click through the prompts and click &amp;#8220;Yes&amp;#8221; when you are asked to confirm even though 1 or more products will stop working (that&amp;#8217;s VS ;)). Then, run a slightly different script to remove ASP.Net Web Pages 2 (which includes Razor):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;gwmi Win32_Product | where { $_.Name -eq &amp;quot;Microsoft ASP.Net Web Pages 2 Runtime&amp;quot; } | ForEach { $msi = Convert-Path &amp;quot;$($_.InstallSource)\*.msi&amp;quot;; msiexec /x $msi }&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id='step_2_fixing_vs'&gt;Step 2: Fixing VS.&lt;/h3&gt;

&lt;p&gt;Now, some of the VS tooling will be broken :(. Pretty much just Razor IntelliSense but that&amp;#8217;s one of the best features! (Though I may be biased ;)). VS tries to load System.Web.Razor (and some other friends) in order to parse Razor documents, but in Step 1, we removed it from the GAC and VS doesn&amp;#8217;t have a local copy, so it doesn&amp;#8217;t know where to find them!&lt;/p&gt;

&lt;p&gt;The fix for this is simple: Give VS a local copy! So, first grab the binaries from Step 0 (if you collected them), or build new binaries from our source code (just follow the steps on our &lt;a href='http://aspnetwebstack.codeplex.com'&gt;CodePlex&lt;/a&gt; site and then grab the binaries from the bin folder). Then, copy them to the following folder:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PrivateAssemblies&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course, replace &amp;#8220;Program Files (x86)&amp;#8221; with &amp;#8220;Program Files&amp;#8221; if you&amp;#8217;re on a 32-bit OS. And replace &amp;#8220;Microsoft Visual Studio 11.0&amp;#8221; with &amp;#8220;Microsoft Visual Studio 2010&amp;#8221; if you&amp;#8217;re using VS 2010. Restart VS and you should have IntelliSense! If you run in to issues, try building your project and restarting VS.&lt;/p&gt;

&lt;h3 id='wrapping_up'&gt;Wrapping up&lt;/h3&gt;

&lt;p&gt;That should be it! Now, please note that this is very unsupported. It works, but if you bork your VS installation, you&amp;#8217;re on your own. Ok, not totally on your own, I&amp;#8217;m happy to try helping in the comments, but don&amp;#8217;t call support because they won&amp;#8217;t help you with this!&lt;/p&gt;

&lt;p&gt;If you get totally screwed, then you can either: repair VS if you&amp;#8217;re using VS 2012, or reinstall MVC 4 if you&amp;#8217;re using VS 2010. That should put you back in a known state.&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>BadImageFormatException - The signature is incorrect</title>
      <link>http://vibrantcode.com/2012/05/18/badimageformatexception-the-signature-is-incorrect</link>
      <pubDate>Fri, 18 May 2012 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/2012/05/18/badimageformatexception-the-signature-is-incorrect</guid>
      <description>&lt;p&gt;Have you ever gotten this exception when running Unit Tests which use Moq?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;System.BadImageFormatException : [D:\Path\To\A.dll] The signature is incorrect.&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It&amp;#8217;s a little strange but it turns out the issue is caused by a missing assembly reference in your Unit Test project. Let&amp;#8217;s say you have three projects: Core, Types and Test. In Types, we define a helper interface for writing to the console:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='csharp'&gt;&lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;interface&lt;/span&gt; &lt;span class='n'&gt;IConsole&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;void&lt;/span&gt; &lt;span class='nf'&gt;WriteLine&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='kt'&gt;string&lt;/span&gt; &lt;span class='n'&gt;line&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In Core, we have code to create and return one:&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='csharp'&gt;&lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;class&lt;/span&gt; &lt;span class='nc'&gt;Thingy&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;virtual&lt;/span&gt; &lt;span class='n'&gt;IConsole&lt;/span&gt; &lt;span class='nf'&gt;MakeConsole&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt; &lt;span class='p'&gt;...&lt;/span&gt; &lt;span class='p'&gt;}&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And in Test, you have a unit test to test that something in Core never even constructs a console. Tests ONLY references Core, not Types (for whatever reason).&lt;/p&gt;
&lt;div class='highlight'&gt;&lt;pre&gt;&lt;code class='csharp'&gt;&lt;span class='na'&gt;[Fact]&lt;/span&gt;
&lt;span class='k'&gt;public&lt;/span&gt; &lt;span class='k'&gt;void&lt;/span&gt; &lt;span class='nf'&gt;DoodadWritesToConsole&lt;/span&gt;&lt;span class='p'&gt;()&lt;/span&gt; &lt;span class='p'&gt;{&lt;/span&gt;
    &lt;span class='c1'&gt;// Arrange&lt;/span&gt;
    &lt;span class='kt'&gt;var&lt;/span&gt; &lt;span class='n'&gt;thingyMock&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;Mock&lt;/span&gt;&lt;span class='p'&gt;&amp;lt;&lt;/span&gt;&lt;span class='n'&gt;Thingy&lt;/span&gt;&lt;span class='p'&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class='kt'&gt;var&lt;/span&gt; &lt;span class='n'&gt;doodad&lt;/span&gt; &lt;span class='p'&gt;=&lt;/span&gt; &lt;span class='k'&gt;new&lt;/span&gt; &lt;span class='n'&gt;Doodad&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;thingyMock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Object&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    
    &lt;span class='c1'&gt;// Act&lt;/span&gt;
    &lt;span class='n'&gt;doodad&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;DoAThing&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;writeToConsole&lt;/span&gt;&lt;span class='p'&gt;:&lt;/span&gt; &lt;span class='k'&gt;false&lt;/span&gt;&lt;span class='p'&gt;);&lt;/span&gt;
    
    &lt;span class='c1'&gt;// Assert&lt;/span&gt;
    &lt;span class='n'&gt;thingyMock&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Verify&lt;/span&gt;&lt;span class='p'&gt;(&lt;/span&gt;&lt;span class='n'&gt;t&lt;/span&gt; &lt;span class='p'&gt;=&amp;gt;&lt;/span&gt; &lt;span class='n'&gt;t&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;MakeConsole&lt;/span&gt;&lt;span class='p'&gt;(),&lt;/span&gt; &lt;span class='n'&gt;Times&lt;/span&gt;&lt;span class='p'&gt;.&lt;/span&gt;&lt;span class='n'&gt;Never&lt;/span&gt;&lt;span class='p'&gt;());&lt;/span&gt;
&lt;span class='p'&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you have this set up, you&amp;#8217;ll get the BadImageFormatException when running the test (or should, I haven&amp;#8217;t verified this particular set of classes but I mocked it up from the code I actually found this in). The problem is that Test doesn&amp;#8217;t reference Types, and Types is what provides the interface used as the return value for MakeConsole. All you need to do is add a reference from Test to Types and you&amp;#8217;re done!&lt;/p&gt;

&lt;p&gt;I basically just wanted to throw up a quick blog post so that I could find it if I encountered this again, but hopefully this also helps a few other folks :)&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Yet another blog update!</title>
      <link>http://vibrantcode.com/2012/05/06/yet-another-blog-update</link>
      <pubDate>Sun, 06 May 2012 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/2012/05/06/yet-another-blog-update</guid>
      <description>&lt;p&gt;Well, I went and updated my blog again. I got tired of paying for SquareSpace when I was only barely using it. Also, I&amp;#8217;m a nerd and nerdy things make me happy. So, I&amp;#8217;m trying out &lt;a href='http://pages.github.com/'&gt;GitHub Pages&lt;/a&gt; and &lt;a href='https://github.com/mojombo/jekyll'&gt;Jekyll&lt;/a&gt;. That means that this entire site is up on GitHub and can be viewed by anyone at any time! The repo is &lt;a href='https://github.com/anurse/anurse.github.com'&gt;here&lt;/a&gt;. It&amp;#8217;s all static html that gets run through Jekyll on GitHub&amp;#8217;s servers. I have a local copy of Jekyll I use to test things out too. The comments are mostly ported across except for one page (which I&amp;#8217;ve contacted Disqus support for). The RSS feed has also moved, but the old one &lt;em&gt;should&lt;/em&gt; continue to work. Please resubscribe to the new one though at: &lt;a href='http://feeds.feedburner.com/Vibrantcode'&gt;http://feeds.feedburner.com/Vibrantcode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As you can see, I&amp;#8217;ve also updated the site layout. It&amp;#8217;s a Responsive design as well, which means that the layout adjusts as the browser window size shrinks. It also means it should look pretty good on mobile devices like phones and tablets!&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll have more posts later on the details behind the new &amp;#8220;engine&amp;#8221; but it&amp;#8217;s bedtime now ;). Enjoy! Let me know what you think of it!&lt;/p&gt;</description>
    </item>
    
    <item>
      <title>Shutting down PS-Get</title>
      <link>http://vibrantcode.com/blog/2012/4/19/shutting-down-ps-get.html</link>
      <pubDate>Thu, 19 Apr 2012 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2012/4/19/shutting-down-psget</guid>
      <description>&lt;p&gt;Hey folks, I wanted to make a quick post to tell you all I'm going to be shutting down work on the PS-Get project. The gallery is being shutdown now and the GitHub Repo will remain open but I do not intend to continue work. There was too much confusion between my project (&lt;a title=&quot;https://github.com/anurse/ps-get&quot; href=&quot;https://github.com/anurse/ps-get&quot;&gt;https://github.com/anurse/ps-get&lt;/a&gt;) and PsGet (&lt;a href=&quot;http://psget.net/&quot;&gt;http://psget.net/&lt;/a&gt;). I got a number of people asking me questions about the other and general confusion arose. Also, I'm moving towards a simpler Git-based mechanism for getting my own PowerShell modules (all of which are available at &lt;a href=&quot;http://github.com/anurse&quot;&gt;http://github.com/anurse&lt;/a&gt;) on to all my machines, so I don't need it anymore.&lt;/p&gt;  &lt;p&gt;Don't hesitate to use/view/fork my code, but for now I'm done with the project. It was fun to write, but I can't really justify maintaining it anymore.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>gitstorecred - Store HTTPS Credentials for Git</title>
      <link>http://vibrantcode.com/blog/2012/4/16/gitstorecred-store-https-credentials-for-git.html</link>
      <pubDate>Mon, 16 Apr 2012 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2012/4/16/gitstorecred--store-https-credentials-for-git</guid>
      <description>&lt;p&gt;UPDATE: Thanks to some help from &lt;a href=&quot;http://paulbetts.org/&quot;&gt;Paul Betts&lt;/a&gt; this has been updated to use some new APIs in Git. Check out the blog post on the &lt;a href=&quot;https://github.com/blog/1104-credential-caching-for-wrist-friendly-git-usage&quot;&gt;GitHub Blog&lt;/a&gt; for more info!&lt;/p&gt;
&lt;p&gt;As you probably know, the ASP.Net team has moved to CodePlex for all of our out-of-band frameworks (MVC, WebPages, WebAPI, etc.). You probably also know that we are using the Git source control system on CodePlex. You may also know that CodePlex only supports the HTTPS transport for Git, which means that a username and password is required every time you push changes to the server:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;lightbox&quot; href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/gitcred1.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px 0px 6px 2px; display: inline; padding-right: 0px; border: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/gitcred1.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;590&quot; height=&quot;75&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can bypass the first prompt by adding your remote with &amp;ldquo;https://username@server.com/path&amp;rdquo;, and can even bypass the second by using &amp;ldquo;https://username:password@server.com/path&amp;rdquo; as the URL, but that&amp;rsquo;s a really Bad Idea&amp;trade;. So, like most modern systems, Git probably has a way to store these credentials, right?&lt;/p&gt;
&lt;p&gt;Nope.&lt;/p&gt;
&lt;p&gt;However, it does have an interesting extension point called &amp;ldquo;AskPass&amp;rdquo;. If you set the &amp;ldquo;core.askpass&amp;rdquo; config setting, or the GIT_ASKPASS environment variable, to the path to an executable, Git will run that executable every time it needs a username or password. It will pass the prompt it would have written to the console as the command line arguments to this program and it expects the program to write the credential it is requesting (username or password) to the standard output stream. We can use this to our advantage!&lt;/p&gt;
&lt;p&gt;GitStoreCred is a small tool I created for doing exactly that. It allows you to replace the Git username and password prompt with a standard Windows credential dialog AND it will store those credentials in the Windows Credential Store (if you check the &amp;ldquo;Remember&amp;rdquo; checkbox). Let&amp;rsquo;s see it in action:&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;lightbox&quot; href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/gitcred2.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px 0px 6px 2px; display: inline; padding-right: 0px; border: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/gitcred2.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;765&quot; height=&quot;644&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Much better! Once we enter our credentials, everything works and Git pushes happily to the server. Let&amp;rsquo;s take a look at the Windows Credential Store now (this is in your Control Panel, go to User Accounts then Credential Manager):&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;lightbox&quot; href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/gitcred3.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/gitcred3.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;593&quot; height=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;See the highlighted entry? That&amp;rsquo;s my credentials for CodePlex (you&amp;rsquo;ll see I&amp;rsquo;ve also got credentials for GitHub there). If I try to push again, git won&amp;rsquo;t prompt me because gitstorecred just found the existing credential and outputted it.&lt;/p&gt;
&lt;h3&gt;Enough talking, gimme gimme gimme!&lt;/h3&gt;
&lt;p&gt;Ok, so you can &lt;a href=&quot;https://github.com/downloads/anurse/git-credential-winstore/gitstorecred.exe&quot;&gt;download&lt;/a&gt; gitstorecred from GitHub and you can &lt;a href=&quot;https://github.com/anurse/git-credential-winstore&quot;&gt;view the code&lt;/a&gt; there too. Just put the exe anywhere and set the GIT_ASKPASS environment variable to it&amp;rsquo;s full path. I use my PowerShell profile script to do it, since I&amp;rsquo;m always in PowerShell.&lt;/p&gt;
&lt;h3&gt;WARNING! HERE BE DRAGONS!&lt;/h3&gt;
&lt;p&gt;This is super hacky, I literally bashed it up over this weekend. It works, but I make no guarantees. The major known issues are the following:&lt;/p&gt;
&lt;p&gt;First, if you type the wrong password, you have to go to Credential Manager (above) and either edit or just remove your credential. Gitstorecred has no way of getting feedback from Git so it doesn&amp;rsquo;t know that your password was wrong (for example) and will just keep sending the wrong password. If you checked &amp;ldquo;Remember&amp;rdquo; then the only way to get it to prompt you again is to remove the credentials.&lt;/p&gt;
&lt;p&gt;Second, it doesn&amp;rsquo;t seem to get in the way of SSH-based pushing, but it might so be careful. If you ever find Git hanging when you run &amp;ldquo;git push&amp;rdquo;, just clear out the GIT_ASKPASS setting and try again. It&amp;rsquo;s entirely possible gitstorecred isn&amp;rsquo;t responding the way Git expects.&lt;/p&gt;
&lt;p&gt;Third, we only store one set of credentials PER SERVER. That means that if you have two user accounts for some reason (say &amp;ldquo;anurse&amp;rdquo; and &amp;ldquo;bnurse&amp;rdquo;) for some server (say &amp;ldquo;github.com&amp;rdquo;), gitstorecred just stores the first one as the credentials for &amp;ldquo;github.com&amp;rdquo; and passes them along. Due to some issues with the Windows Credential API I use, it can&amp;rsquo;t easily key the credential off your user account. For that reason, I &lt;strong&gt;highly&lt;/strong&gt; recommend adding your git remote WITHOUT the user name (i.e. &amp;ldquo;git remote add &lt;a href=&quot;https://git01.codeplex.com/aspnetwebstack&quot;&gt;https://git01.codeplex.com/aspnetwebstack&lt;/a&gt;&amp;rdquo;). That way gitstorecred will handle the username and password and you won&amp;rsquo;t get in to weird issues. Of course, the credential store is per windows user, so if you have two separate users on the same machine, they can have different credentials for the same server.&lt;/p&gt;
&lt;p&gt;Please do try it out though, the worst that should happen is it won&amp;rsquo;t work and you&amp;rsquo;ll have to turn it off. I&amp;rsquo;m happy to take pull requests to try and make it more powerful/robust (for example, there are better Windows Credential APIs I could use but they are harder to access from Managed Code). With a tool like this, and the fact that Git is much smarter about HTTP pushing now, I&amp;rsquo;m switching almost exclusively to HTTPS for my Git pushes.&lt;/p&gt;
&lt;p&gt;Enjoy! Here&amp;rsquo;s the links again: &lt;a href=&quot;https://github.com/downloads/anurse/git-credential-winstore/gitstorecred.exe&quot;&gt;Download EXE&lt;/a&gt;, &lt;a href=&quot;https://github.com/anurse/git-credential-winstore&quot;&gt;Source Code on GitHub&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What else is new in Razor v2?</title>
      <link>http://vibrantcode.com/blog/2012/4/13/what-else-is-new-in-razor-v2.html</link>
      <pubDate>Fri, 13 Apr 2012 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2012/4/13/what-else-is-new-in-razor-v2</guid>
      <description>&lt;p&gt;In my &lt;a href=&quot;http://vibrantcode.com/blog/2012/4/10/whats-new-in-razor-v2.html&quot;&gt;last post&lt;/a&gt; I discusses some of the big new features in Razor v2. In this post I'm going to talk a bit about some of the other (admittedly smaller) new features. So, let's get right to it!&lt;/p&gt;  &lt;h3&gt;Void Elements&lt;/h3&gt;  &lt;p&gt;The HTML spec defines a certain type of element called a &quot;Void Element&quot; as&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;[An] element whose content model never allows it to have contents under any circumstance&lt;/p&gt;   &lt;cite&gt;- &lt;a href=&quot;http://dev.w3.org/html5/markup/syntax.html#syntax-elements&quot;&gt;W3C HTML 5 Spec section 4.3&lt;/a&gt;&lt;/cite&gt;&lt;/blockquote&gt;  &lt;p&gt;Put more simply, a void element is a type of element that can NEVER EVER have contents. It can come in three different forms:&lt;/p&gt;  &lt;pre class=&quot;brush: html&quot;&gt;  &amp;lt;!-- Self-closing --&amp;gt;
  &amp;lt;input name=&amp;quot;foo&amp;quot; /&amp;gt;&amp;lt;p&amp;gt;A different tag&amp;lt;/p&amp;gt;
  &amp;lt;!-- Closed --&amp;gt;
  &amp;lt;input name=&amp;quot;foo&amp;quot;&amp;gt;&amp;lt;/input&amp;gt;&amp;lt;p&amp;gt;A different tag&amp;lt;/p&amp;gt;
  &amp;lt;!-- Unclosed --&amp;gt;
  &amp;lt;input name=&amp;quot;foo&amp;quot;&amp;gt;&amp;lt;p&amp;gt;A different tag&amp;lt;/p&amp;gt;&lt;/pre&gt;

&lt;p&gt;Any of the following is considered valid HTML5. However, in Razor v1, we only allowed the first two, because we had a much simpler parser. In Razor v2, you can now use the third form as well. This works because if a void element's start tag is not self-closed AND is not IMMEDIATELY followed by an end tag (whitespace is allowed) then it is considered closed at the &quot;&amp;gt;&quot; of the start tag. So in Razor, when we parse a void element and reach the &quot;&amp;gt;&quot;, we look ahead and check if we see &quot;&amp;lt;/[tagname]&amp;gt;&quot; (we allow whitespace between the start and end tags). If we do NOT see it, we consider the tag closed. So this means that if you typed the following inside a code block (i.e. @if() {})&lt;/p&gt;

&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;p&amp;gt;&amp;lt;input name=&amp;quot;foo&amp;quot;&amp;gt;Some content&amp;lt;/input&amp;gt;&amp;lt;/p&amp;gt;&lt;/pre&gt;

&lt;p&gt;Razor would end the markup block at the &quot;&amp;lt;/input&amp;gt;&quot; tag. Why? Because the input element was closed by the &quot;&amp;gt;&quot; of it's start tag, so the &quot;&amp;lt;/input&amp;gt;&quot; tag is considered an extraneous end tag. Since it has no matching start tag (remember the &quot;&amp;lt;input&amp;gt;&quot; is already closed), we think that it belongs to a start tag Razor can't see (because it's outside of the code block this markup is within or even in a different document) and we end the block there.&lt;/p&gt;

&lt;p&gt;For the most part, this shouldn't affect you adversely, since syntax like the sample above is invalid HTML, but please let me know if you end up in an edge case where this is occurring in legal HTML.&lt;/p&gt;

&lt;p&gt;Finally, what are the elements HTML5 considers void? The spec lists them off for us and Razor uses this exact same list:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/area.html#area&quot;&gt;area&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/base.html#base&quot;&gt;base&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/br.html#br&quot;&gt;br&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/col.html#col&quot;&gt;col&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/command.html#command&quot;&gt;command&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/embed.html#embed&quot;&gt;embed&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/hr.html#hr&quot;&gt;hr&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/img.html#img&quot;&gt;img&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/input.html#input&quot;&gt;input&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/keygen.html#keygen&quot;&gt;keygen&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/link.html#link&quot;&gt;link&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/meta.html#meta&quot;&gt;meta&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/param.html#param&quot;&gt;param&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/source.html#source&quot;&gt;source&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/track.html#track&quot;&gt;track&lt;/a&gt;&lt;/code&gt; &lt;code&gt;&lt;a href=&quot;http://dev.w3.org/html5/markup/wbr.html#wbr&quot;&gt;wbr&lt;/a&gt;&lt;/code&gt;&lt;/p&gt;
  &lt;cite&gt;- &lt;a href=&quot;http://dev.w3.org/html5/markup/syntax.html#syntax-elements&quot;&gt;W3C HTML 5 Spec section 4.3&lt;/a&gt;&lt;/cite&gt;&lt;/blockquote&gt;

&lt;h3&gt;Syntax Tree and Internals Overhaul&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;NOTE: This part is going to dive in to parser internals a bit. Feel free to skim ;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The last thing I'm going to talk about is a behind-the-scenes change that's mostly relevant to people hosting the Razor parser. In order to support these exciting new features, we had to overhaul our parser internals and syntax tree structure. Razor now uses full HTML, C# and VB tokenizers and the parse tree gives you access to that granularity. For example, given the code:&lt;/p&gt;

&lt;pre class=&quot;brush: csharp&quot;&gt;@foo.bar.baz&lt;/pre&gt;

&lt;p&gt;In Razor v1, this would be two Spans (a type of parse tree node), one for &quot;@&quot; and one for &quot;foo.bar.baz&quot;. Each span would contain the string pulled from the input file. However, in Razor v2, we produce the same two spans, but now each span is a collection of Symbols. In this case, the first Span contains one symbol &quot;@&quot; and the second Span contains 5 symbols (&quot;foo&quot;, &quot;.&quot;, &quot;bar&quot;, &quot;.&quot;, &quot;baz&quot;). This allows us to perform more advanced analysis of the input document without have to reparse strings over and over.&lt;/p&gt;

&lt;p&gt;We also reworked our higher-level Syntax Tree nodes, Span and Block. In Razor v1, we broke the file into chunks called spans and used sub-classes of the Span class to mark their type (for example: MarkupSpan, CodeSpan, HelperHeaderSpan, TransitionSpan). In v2, we removed all of those sub-classes, moving to an &quot;Annotations&quot; model. Going back to our previous example, in Razor v1 we would have produced a TransitionSpan and a ImplicitExpressionSpan (a kind of CodeSpan). In v2, both are concrete instances of Span, however they have various properties which attach annotations to control how they behave. For example, each Span has a CodeGenerator annotation which indicates how we generate C#/VB code from the node. They also have an EditHandler annotation which indicates how the editor should behave around this Span. By doing this, we (and even you if you want!) can add new syntax without having to dramatically overhaul all the various pieces of our infrastructure.&lt;/p&gt;

&lt;p&gt;In future posts, I'm going to use some of this information to show you how to create a new kind of directive that works at runtime AND design-time (i.e. in the Editor).&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Well, that's basically it for Razor v2. It's not a super-long list but believe me it was a lot of work. In many ways, Razor v1 was our &quot;hey, check out this cool language!&quot; release. Razor v2 has primarily been about internal clean-up and future-proofing (not that one can ever be totally future-proof). We added some cool little features, but the work done to the underlying structures should make it easier for us to add even more features and extensibility points in the future.&lt;/p&gt;

&lt;p&gt;Enjoy Razor 2, Web Pags 2 and MVC 4!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>What's new in Razor v2</title>
      <link>http://vibrantcode.com/blog/2012/4/10/whats-new-in-razor-v2.html</link>
      <pubDate>Tue, 10 Apr 2012 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2012/4/10/whats-new-in-razor-v2</guid>
      <description>&lt;p&gt;I know, it&amp;rsquo;s been too long since I blogged, and I won&amp;rsquo;t even bother saying I&amp;rsquo;ll try to blog more (though I will) because hopefully you&amp;rsquo;ll see that for yourself. A lot has happened since I last blogged but the biggest thing is that the ASP.Net Web Stack (which is what we call the out-of-band stuff we ship, like MVC, WebPages, WebAPI and Razor) is now truly an open-source project! We&amp;rsquo;re hosted on CodePlex (&lt;a title=&quot;http://aspnetwebstack.codeplex.com/&quot; href=&quot;http://aspnetwebstack.codeplex.com/&quot;&gt;http://aspnetwebstack.codeplex.com/&lt;/a&gt;) and if you want more details, check out Scott Hanselman&amp;rsquo;s awesome &lt;a href=&quot;http://www.hanselman.com/blog/ASPNETMVC4ASPNETWebAPIAndASPNETWebPagesV2RazorNowAllOpenSourceWithContributions.aspx&quot;&gt;post&lt;/a&gt; about it.&lt;/p&gt;
&lt;p&gt;Now that we&amp;rsquo;re open, I&amp;rsquo;ll be able to start talking a little more directly about what we&amp;rsquo;re doing. It&amp;rsquo;s very exciting for us, and to alleviate your worries that open-source means Microsoft isn&amp;rsquo;t working on it anymore, we&amp;rsquo;re still working full-time on our current release and even starting a bit of planning for v.Next.&lt;/p&gt;
&lt;p&gt;All that aside, we also released a new version of Razor since I&amp;rsquo;ve blogged and I thought I&amp;rsquo;d give you a quick run-through of the features. In later posts, I&amp;rsquo;ll go over the details of what&amp;rsquo;s changed as well as some new information for those hosting Razor outside of ASP.Net on how to take advantage of those features.&lt;/p&gt;
&lt;h3&gt;~/ &amp;ndash; Url resolution made easy, goodbye @Href/@Url.Content!&lt;/h3&gt;
&lt;p&gt;One of the most common patterns in MVC Views is this:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;script src=&amp;rdquo;@Url.Content(&amp;ldquo;~/Scripts/myscript.js&amp;rdquo;)&amp;rdquo;&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;Well, in Razor v2, you can express the same intent with much less code, and it looks much cleaner too:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;script src=&amp;rdquo;~/Scripts/myscript.js&amp;rdquo;&amp;gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;
&lt;p&gt;Note the lack of any code transitions! How does this work? It&amp;rsquo;s quite a simple algorithm: Whenever we see an attribute value that starts &amp;ldquo;~/&amp;rdquo;, we treat it like a URL and replace it with a call to &lt;code&gt;@Href&lt;/code&gt; (in WebPages) or &lt;code&gt;@Url.Content&lt;/code&gt; (in MVC). Note that this is ANY attribute, so if you typed the following:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;div class=&amp;rdquo;~/Foo&amp;rdquo;&amp;gt;&lt;/pre&gt;
&lt;p&gt;We&amp;rsquo;ll treat &amp;ldquo;~/Foo&amp;rdquo; as a URL. We made this choice because we didn&amp;rsquo;t want to limit you to a list of attributes that we think have URLs. Especially when you might want to put URLs in a &lt;code&gt;data-&lt;/code&gt; attribute. Imagine using a &lt;code&gt;data-&lt;/code&gt; attribute to tell your client-side javascript what the root of your application is:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;html data-root=&amp;rdquo;~/&amp;rdquo;&amp;gt;&lt;/pre&gt;
&lt;p&gt;Then you can use jQuery to access this data: &lt;code&gt;$(document).data(&amp;lsquo;root&amp;rsquo;)&lt;/code&gt; and use it when making Ajax calls to make sure your app is portable even if it&amp;rsquo;s in a sub-folder.&lt;/p&gt;
&lt;p&gt;What if you want to inject code snippets in to your URL? Well that&amp;rsquo;s easy, just treat it like you would if you were injecting code in to other attribute values:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;a href=&amp;rdquo;~/MySite/@Foo/Bar/@Baz&amp;rdquo;&amp;gt;Something!&amp;lt;/a&amp;gt;&lt;/pre&gt;
&lt;p&gt;I should note that we&amp;rsquo;re actually not doing much special here, the code above is equivalent to the following MVC code in Razor v1:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;a href=&amp;rdquo;@Url.Content(&amp;ldquo;~/MySite/&amp;rdquo;)@Foo/Bar/@Baz&amp;rdquo;&amp;gt;Something!&amp;lt;/a&amp;gt;&lt;/pre&gt;
&lt;p&gt;So we are just resolving that first portion of the URL and then going back to regular string concatenation for the rest.&lt;/p&gt;
&lt;h3&gt;Conditional Attributes&lt;/h3&gt;
&lt;p&gt;The other major feature (there are a few others I&amp;rsquo;ll go over in later posts but they are smaller) is Conditional Attributes. I&amp;rsquo;ll freely admit we borrowed this feature heavily from the fantastic &lt;a href=&quot;http://sparkviewengine.com/&quot;&gt;Spark View Engine&lt;/a&gt; written by our very own &lt;a href=&quot;http://whereslou.com/&quot;&gt;Louis Dejardins&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Have you ever typed code like this in Razor v1?&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;@{ var cls = GetClass(); }
&amp;lt;div id=&amp;rdquo;foo&amp;rdquo;@if(cls != null) { &amp;lt;text&amp;gt;class = &amp;ldquo;@cls&amp;rdquo;&amp;lt;/text&amp;gt; }&amp;gt;&lt;/pre&gt;
&lt;p&gt;If not, let me explain why you&amp;rsquo;d want to do this. In Razor v1, &lt;code&gt;null&lt;/code&gt; was treated the same as an empty string so if you were to have code like this:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;div id=&amp;rdquo;foo&amp;rdquo; class=&amp;rdquo;@cls&amp;rdquo;&amp;gt;&lt;/pre&gt;
&lt;p&gt;Then if cls was null, we&amp;rsquo;d render&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;div id=&amp;rdquo;foo&amp;rdquo; class=&amp;rdquo;&amp;rdquo;&amp;gt;&lt;/pre&gt;
&lt;p&gt;Eugh! That looks ugly! In Razor v2, the same code would render this:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;div id=&amp;rdquo;foo&amp;rdquo;&amp;gt;&lt;/pre&gt;
&lt;p&gt;Note the missing class attribute? We&amp;rsquo;ve even taken away the leading space! Another feature of this is that we&amp;rsquo;ll also collapse whitespace within the attribute value:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;@{ string foo = null; string bar = &amp;ldquo;bar&amp;rdquo; }
&amp;lt;div id=&amp;rdquo;foo&amp;rdquo; class=&amp;rdquo;@foo @bar&amp;rdquo;&amp;gt;&lt;/pre&gt;
&lt;p&gt;Becomes:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;div id=&amp;rdquo;foo&amp;rdquo; class=&amp;rdquo;bar&amp;rdquo;&amp;gt;&lt;/pre&gt;
&lt;p&gt;We also special case boolean values. If the expression evaluates to &lt;code&gt;false&lt;/code&gt;, we treat it the same as &lt;code&gt;null&lt;/code&gt;. If it evaluates to &lt;code&gt;true&lt;/code&gt;, we render out the attribute name again. This allows you to write code like the following for checkboxes:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;input type=&amp;rdquo;checkbox&amp;rdquo; checked=&amp;rdquo;@isChecked&amp;rdquo;&amp;gt;&lt;/pre&gt;
&lt;p&gt;If &lt;code&gt;isChecked&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;, we render &lt;code&gt;checked=&amp;rdquo;checked&amp;rdquo;&lt;/code&gt;, if it&amp;rsquo;s &lt;code&gt;false&lt;/code&gt;, we don&amp;rsquo;t render the &lt;code&gt;checked&lt;/code&gt; attribute at all.&lt;/p&gt;
&lt;p&gt;Finally, we do NOT treat &lt;code&gt;String.Empty&lt;/code&gt; (&quot;&quot;) like &lt;code&gt;null&lt;/code&gt; in this case. If the expression evaluates to an empty string, we WILL render the attribute:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;@{ var foo = &quot;&quot;; }
&amp;lt;div class=&amp;rdquo;@foo&amp;rdquo;&amp;gt;&lt;/pre&gt;
&lt;p&gt;Renders:&lt;/p&gt;
&lt;pre class=&quot;brush: html&quot;&gt;&amp;lt;div class=&amp;rdquo;&amp;rdquo;&amp;gt;&lt;/pre&gt;
&lt;p&gt;The reason for this lies in the difference between &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;String.Empty&lt;/code&gt;. Null indicates the complete absence of a value, whereas &lt;code&gt;String.Empty&lt;/code&gt; is a value, a string of length 0.&lt;/p&gt;
&lt;p&gt;In the currently released (Beta) version of Razor, we do this for all attributes. However, in the next release (and, in fact, in the live code on CodePlex) we have entirely disabled the conditional attributes feature for &lt;code&gt;data-&lt;/code&gt; attributes. You'll still get the ~/ URL resolution, but we won't remove null values or do fancy tricks with booleans in &lt;code&gt;data-&lt;/code&gt; attributes. This was done because those attributes are usually read from JavaScript, so the semantics are different and we wanted to give you full control.&lt;/p&gt;
&lt;h3&gt;There&amp;rsquo;s much more!&lt;/h3&gt;
&lt;p&gt;That&amp;rsquo;s just a quick summary. I&amp;rsquo;ll be publishing another post soon with even more new features. Then, we&amp;rsquo;ll go in to how Conditional Attributes is implemented and how you can make sure your custom Razor hosts support this feature.&lt;/p&gt;
&lt;p&gt;Please don&amp;rsquo;t hesitate to let me know what you think in the comments!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>PS-Get 0.6 - Now with a Gallery!</title>
      <link>http://vibrantcode.com/blog/2011/12/22/ps-get-06-now-with-a-gallery.html</link>
      <pubDate>Thu, 22 Dec 2011 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2011/12/22/psget-06--now-with-a-gallery</guid>
      <description>&lt;p&gt;I've been hard at work, and not just at my day job! It's been a while but I've finally gotten together and created a proper website for PS-Get including?.(drumroll please)?. a Gallery! &lt;strike&gt;Blatantly ripped off&lt;/strike&gt; Borrowed from the &lt;a href=&quot;http://github.com/nuget/nugetgallery&quot;&gt;NuGet Gallery Code&lt;/a&gt;, the &lt;a href=&quot;http://psget.org&quot;&gt;PS-Get Gallery&lt;/a&gt; is a place to upload PS-Get modules for others to download. It also contains &lt;a href=&quot;http://psget.org/pages/Install&quot;&gt;detailed installation instructions&lt;/a&gt;, but thanks to a new installer script, it's a pretty simple install! To install, just run this command from a PowerShell 3.0 or PowerShell 2.0 (with .NET 4.0 workaround, see below) window:&lt;/p&gt;  &lt;pre class=&quot;brush: powershell&quot;&gt;(new-object Net.WebClient).DownloadString(&amp;quot;http://install.psget.org&amp;quot;)|iex&lt;/pre&gt;

&lt;p&gt;And then you're all set! There's rudimentary support for automatically injecting the proper code into your Profile, but if you want to do it manually, all you need is &lt;code&gt;Import-Module PS-Get.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So, what's new in PS-Get 0.6?&lt;/p&gt;

&lt;h3&gt;Import-Package Cmdlet&lt;/h3&gt;

&lt;p&gt;The Import-Package cmdlet is a one-step cmdlet that takes the name of a module as it's primary argument. It checks if that module is installed, and if not it installs it for you. Once the module is installed, it imports it in to the current environment. For example, consider the following code:&lt;/p&gt;

&lt;pre class=&quot;brush: powershell&quot;&gt;Import-Package PS-Json&lt;/pre&gt;

&lt;p&gt;If PS-Json is already installed, this is identical to Import-Module PS-Json. However, if PS-Json is not installed, it's install first. This means that if you sync your profile across multiple machines, all you need is some code to check for and install PS-Get and a bunch of Import-Package statements to get all your Modules installed and ready! In fact, the PS-Get install script (which you can download &lt;a href=&quot;http://install.psget.org&quot;&gt;here&lt;/a&gt;) takes parameters that let you skip the entire wizard. So you could have code like the following in your profile and have PS-Get and all your favourite packages installed automatically!&lt;/p&gt;

&lt;pre class=&quot;brush: powershell&quot;&gt;if(@(Get-Module PS-Get).Count -eq 0) {
    Write-Host &amp;quot;This is the first time you've run this profile on this machine so we need to install PS-Get first...&amp;quot;
    (new-object Net.WebClient).DownloadString(&amp;quot;http://install.psget.org&amp;quot;)|iex
}
Import-Module PS-Get
Import-Package PS-MagicStuffThatILove&lt;/pre&gt;

&lt;h3&gt;Package Source Management&lt;/h3&gt;

&lt;p&gt;New in PS-Get 0.6 is the ability to manage multiple package sources. Using Add-/Remove-/Get-PackageSource you can manage package sources at three scope levels: Machine (global to all users), User (global to all PowerShell sessions for the current user), Session (specific to just this PowerShell session). These sources will all be searched for packages when Install-Package and Update-Package are used to get new packages. The installer script automatically sets up the PS-Get Gallery as a machine-level source. You can still override the source by using the &quot;-Source&quot; parameter of most cmdlets.&lt;/p&gt;

&lt;h3&gt;Export-Module Cmdlet&lt;/h3&gt;

&lt;p&gt;PS-Get 0.6 adds a new cmdlet &quot;Export-Module&quot; which can be used to take an existing PowerShell Module and export it to a NuPkg file which can then be uploaded to the PS-Get Gallery. If the module directory contains a NuSpec file, we'll use that, otherwise will gather as much data as we can from the PSD1 manifest file (if there is one). Missing data can be filled in using arguments to the Export-Module cmdlet. Eventually, the plan is to make it easier to manage extra PS-Get-related metadata for Modules, either by augmenting the existing PSD1 manifests or by providing tools to manage NuSpec files for modules.&lt;/p&gt;

&lt;p&gt;One thing this is missing right now is dependencies. If your module depends on another module, you'll need to create a NuSpec file for it. Removing this restriction is priority 1 for enhancing the Export-Module cmdlet.&lt;/p&gt;

&lt;h3&gt;Conclusion/The Future&lt;/h3&gt;

&lt;p&gt;I hope you'll try it out and start submitting packages to the gallery. It's ready to go, but I'll be perfectly honest that I'm doing this with no budget so I'm working on free/cheap hosting solutions and the site may go down.&lt;/p&gt;

&lt;p&gt;If you want to help with the future of PS-Get, check out our &lt;a href=&quot;https://github.com/anurse/PS-Get&quot;&gt;GitHub page&lt;/a&gt;. Fork the code, file some issues on our tracker or just read the wiki!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Catharsis and Humanity</title>
      <link>http://vibrantcode.com/blog/2011/5/2/catharsis-and-humanity.html</link>
      <pubDate>Mon, 02 May 2011 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2011/5/2/catharsis-and-humanity</guid>
      <description>&lt;p&gt;This is a rare non-tech-related blog post, and I hope you'll forgive me for it. It's also possible you may find it controversial, so I'd ask your patience in reading the entire thing before jumping to conclusions. There will likely be another non-tech post soon, since the Canadian Federal Election is wrapping up, but I needed to get this post out before then.&lt;/p&gt;
&lt;p&gt;As everyone who isn't living under a rock knows, on Monday, President Obama announced that US Special Forces had located and killed Osama Bin Laden. My girlfriend (who has &lt;a href=&quot;http://ssmary.wordpress.com/2011/05/01/on-war/&quot;&gt;posted&lt;/a&gt; something about this herself) brought up a quotation (attributed to either Mark Twain or Clarence Darrow depending on who you ask) which I think accurately sums up my feelings: &quot;I've never wished a man dead, but I have read some obituaries with great pleasure&quot;. There's no question in my mind that Osama Bin Laden was responsible for terrible things, and his death has brought closure to many people. I certainly don't fault the people in Washington DC and New York City for feeling a sudden urge to celebrate out of catharsis. One of the people I follow on Twitter, &lt;a href=&quot;http://twitter.com/stepto&quot;&gt;Stephen Toulouse&lt;/a&gt;, &lt;a href=&quot;http://twitter.com/#!/Stepto/status/64907379065630720&quot;&gt;tweeted&lt;/a&gt; that &quot;catharsis doesn't choose a time to be appropriate&quot; which really makes a lot of sense to me.&lt;/p&gt;
&lt;p&gt;Despite all that, I feel? uneasy (for a significant lack of a better term)? about the way we are celebrating the death of another human being, as evil as he was (whatever &quot;evil&quot; truly is). I know that on September 11, 2001, there were people cheering in the streets for the death of human beings too, and I think it's important to remember that as we go through this catharsis. Please do NOT get me wrong, I can fully understand the need to celebrate, it is &lt;strong&gt;human&lt;/strong&gt; to have such a strong outpouring of relief and emotion when closure is found. For the people around the world who were directly affected by the events of 9/11, this will most definitely be an almost happy occasion, and I would not fault them for feeling that way. As I noted earlier, I myself am certainly not upset that Bin Laden is dead or even that people are celebrating that fact.&lt;/p&gt;
&lt;p&gt;I think it is entirely natural to feel relieved and to want to express that relief, but now that the catharsis is over, we should rise above our enemies and remember that we respect &lt;strong&gt;all &lt;/strong&gt;life, even those who feel so oppressed as to need to strike out violently. What Osama Bin Laden and al-Qaeda did 10 years ago was WRONG, full stop. However my moral code also tells me that &lt;em&gt;any time a human being is killed by another, it is because of a &lt;strong&gt;failure in our society&lt;/strong&gt;&lt;/em&gt;. I am still struggling to figure out what that means, since I too feel a lot of relief over the closing of this chapter in our history, but I think what's most important is that we recognize this event for what it truly is: A purge of our emotions and frustrations which have been building up since 9/11, not a victory for humanity as a whole. There's nothing wrong with celebrating the former, as long as you keep the latter in mind and reflect on what we need to do in order to achieve true peace.&lt;/p&gt;
&lt;p&gt;Please don't hesitate to post legitimate responses and discussions to this post below. I welcome disagreements. However, I will not hesitate to remove hurtful or hateful comments. Above all else, &lt;strong&gt;RESPECT &lt;/strong&gt;each other, because that is how we rise above.&lt;/p&gt;
&lt;p&gt;P.S. Apparently &quot;catharsis&quot; is my word of the day &lt;img class=&quot;wlEmoticon wlEmoticon-winkingsmile&quot; style=&quot;border-style: none;&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/winky.png&quot; alt=&quot;Winking smile&quot; /&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Meme Helper for ASP.Net WebPages</title>
      <link>http://vibrantcode.com/blog/2011/4/1/meme-helper-for-aspnet-webpages.html</link>
      <pubDate>Fri, 01 Apr 2011 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2011/4/1/meme-helper-for-aspnet-webpages</guid>
      <description>&lt;p&gt;We're working hard on the next versions of ASP.Net WebPages, MVC and Razor, but in the mean time, we wanted to preview some of the work we're doing for the next version. So, I'm releasing one of the new helpers we're working on as an early preview via NuGet.&lt;/p&gt;

&lt;p&gt;Have you ever felt that your site was missing an important aspect of web culture? Like an image of a cat, or an embedded 1980s music video? That's what we're hoping to solve with this new helper for ASP.Net WebPages.&lt;/p&gt;

&lt;p&gt;The Meme Helper is a simple helper which allows you to easily inject pure unfiltered AWESOME into your site with a single line of code. For example, let's say you want to embed a certain newly released music video that's garnered a lot of interest recently. You could go find the video and add a bunch of HTML embed code from your favorite video sharing site. Or you could use HTML5. Or even better, you could use the MemeHelpers and do it in one line:&lt;/p&gt;

&lt;pre class=&quot;brush: csharp&quot;&gt;@Friday.Embed(type: Friday.FridayType.Normal)&lt;/pre&gt;

&lt;p&gt;Or maybe you want to reference a certain weather phenomenon which occurs not once, but TWICE in the sky at the same time:&lt;/p&gt;

&lt;pre class=&quot;brush: csharp&quot;&gt;@Rainbow.Embed(type: Rainbow.RainbowType.Double)&lt;/pre&gt;

&lt;p&gt;Or perhaps you've tired of this whole Meme phenomenon and want to express your exhaustion:&lt;/p&gt;

&lt;pre class=&quot;brush: csharp&quot;&gt;@Facepalm.GetHtml(type: Facepalm.FacepalmType.Picard, height: 200)&lt;/pre&gt;

&lt;p&gt;If there's a meme, there's probably a helper for it. And if not, you can contribute your own by forking the &lt;a href=&quot;https://bitbucket.org/anurse/memehelpers&quot;&gt;BitBucket repository&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;You can get the MemeHelpers using NuGet (PackageId: &lt;a href=&quot;http://nuget.org/List/Packages/FourOne.Memes/1.0&quot;&gt;FourOne.Memes&lt;/a&gt;). Plus, I've attached a &lt;a href=&quot;http://vibrantcode.com/storage/bitz/MemeTestSite.zip&quot;&gt;Sample Website&lt;/a&gt; to this post. Install the package and explore the Memes!!&lt;/p&gt;

&lt;p&gt;Oh and remember: Yesterday was Thursday! Thursday! Today it is Friday! Friday! Fun! Fun! Fun! Fun!&lt;/p&gt;

&lt;p style=&quot;font-size: 4pt&quot;&gt;DISCLAIMER: This is not actually related to Microsoft in any way. Microsoft does not endorse any of these Memes. This is just the idle rambling of a developer who likes Memes and a certain day in April ;)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>New Blog Design and Hoster!</title>
      <link>http://vibrantcode.com/blog/2011/3/12/new-blog-design-and-hoster.html</link>
      <pubDate>Sat, 12 Mar 2011 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2011/3/12/new-blog-design-and-hoster</guid>
      <description>&lt;p&gt;I decided I was tired of running my blog off of my own server, so I've moved to a hosted blog platform, and redesigned by blog a little as well &lt;img style=&quot;border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none&quot; class=&quot;wlEmoticon wlEmoticon-smile&quot; alt=&quot;Smile&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/smily.png&quot; /&gt;. The new blog is, well, right here! It's hosted on &lt;a href=&quot;http://www.squarespace.com&quot;&gt;SquareSpace&lt;/a&gt; which is a high-scale blog hosting platform. You might ask why I'm not using an ASP.Net blog system, well the answer is simple: I'm not in the business of running a blog. I hope you enjoy my blog, but I don't feel a need to invest a lot of time and effort into running a blog myself when I can pay someone else to do it! After some review of the options, this ended up being the best one of those I reviewed. You'll notice there's a new design, which is one of the reasons I chose SquareSpace, they have a bunch of really nice templates but more than that, they provide easy customization tools! With only a little bit of CSS, I converted one of their stock themes into something that suited me a little more. All of my previous post should be here, but there were little content glitches during the transfer process. Everything should be there, but some of the older posts might not look as nice &lt;img style=&quot;border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none&quot; class=&quot;wlEmoticon wlEmoticon-smile&quot; alt=&quot;Smile&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/smily.png&quot; /&gt;&lt;/p&gt;  &lt;p&gt;In the same vein, I ported all of the comments over to &lt;a href=&quot;http://www.disqus.com&quot;&gt;Disqus&lt;/a&gt;, and all future comments will be handled through that service. Again, all the comments should be there, but don't take it personally if your comment has disappeared! If you encounter any content problems in the blog or comments please &lt;a href=&quot;http://vibrantcode.com/contact-me/&quot;&gt;let me know&lt;/a&gt;!&lt;/p&gt;  &lt;p&gt;I've also normalized everything to point at the same domain name: &lt;a href=&quot;http://vibrantcode.com&quot;&gt;http://vibrantcode.com&lt;/a&gt;. All the old links should work, but again, let me know if you encounter one that doesn't.&lt;/p&gt;  &lt;p&gt;The new blog also uses &lt;a href=&quot;http://leandrovieira.com/projects/jquery/lightbox/&quot;&gt;jQuery Lightbox&lt;/a&gt; and the latest version of &lt;a href=&quot;http://alexgorbatchev.com/SyntaxHighlighter/&quot;&gt;SyntaxHighlighter.js&lt;/a&gt; to give it a little more pop. I hope you like it!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>PsGet v0.2 - Now with more awesome! (and fewer version numbers)</title>
      <link>http://vibrantcode.com/blog/2011/2/16/psget-v02now-with-more-awesome-and-fewer-version-numbers.html</link>
      <pubDate>Thu, 17 Feb 2011 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2011/2/16/psget-v02--now-with-more-awesome-and-fewer-version-numbers</guid>
      <description>&lt;p&gt;I've just pushed a new version of PsGet out and it has a number of cool new features!&lt;/p&gt;
&lt;h3&gt;No more version numbers in Module names!&lt;/h3&gt;
&lt;p&gt;Thanks to both a private patched build of NuGet.exe (this is a temporary fix) and a patch to the main version of NuGet (&lt;a href=&quot;http://nuget.codeplex.com/SourceControl/changeset/changes/81c1815fd452&quot;&gt;http://nuget.codeplex.com/SourceControl/changeset/changes/81c1815fd452&lt;/a&gt; - this is the more permanent fix), PsGet's Install-PSPackage script no longer adds the version number to the end of the Module name. So you can name your package files &quot;Foo.psd1&quot; instead of &quot;Foo.0.1.0.0.psd1&quot;.&lt;/p&gt;
&lt;h3&gt;No more nested module path&lt;/h3&gt;
&lt;p&gt;PsGet no longer uses it's own nested module path (the packages folder under the PsGet install path). It now installs modules to the same place PsGet itself was installed. The plan for the future is to make install destination settable via a parameter to Install-PSPackage, but for now this seemed like a better default.&lt;/p&gt;
&lt;h3&gt;Totally Self-Hosted&lt;/h3&gt;
&lt;p&gt;This version of PsGet, unlike the previous version, has no bootstrapper module and is actually a PsGet package itself (it's even on the NuGet gallery: &lt;a href=&quot;http://nuget.org/Packages/Packages/Details/PS-Get-0-2-0-0&quot;&gt;http://nuget.org/Packages/Packages/Details/PS-Get-0-2-0-0&lt;/a&gt;). The install script (see next section) handles install it though, so there should be no need to download it yourself.&lt;/p&gt;
&lt;h3&gt;Install Script&lt;/h3&gt;
&lt;p&gt;PsGet now has a bootstrapper install script. Unfortunately there are &lt;span style=&quot;text-decoration: underline;&quot;&gt;still&lt;/span&gt; more hoops to jump through than I'd like, but it's easier to use than the first version. If you're upgrading from v0.1, go ahead and delete your PsGetBoot folder, it's the easiest way to upgrade. From v0.2 on, upgrades will be handled through PsGet itself!&lt;/p&gt;
&lt;p&gt;Here's how to install PsGet v0.2. First, go to our download site and download Install-PsGet.ps1:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/PsGet-v0.2Now-with-more-awesome_E323/image_2.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/PsGet-v0.2Now-with-more-awesome_E323/image_thumb.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;975&quot; height=&quot;167&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once downloaded, you need to &lt;em&gt;temporarily&lt;/em&gt; allow PowerShell to run unsigned remote scripts. Open an Admin PowerShell prompt and type the following command:&lt;/p&gt;
&lt;pre class=&quot;brush: ps&quot;&gt;Set-ExecutionPolicy Unrestricted&lt;/pre&gt;
&lt;p&gt;Then, run the Install-PsGet.ps1 script you just downloaded. You may get a security prompt, go ahead and accept it. Feel free to skim the contents of the file before you run it. The script will download some files, but it will clean them up when it's finished.' You will be prompted to choose where to install PsGet. The installer scans your PSModulePath environment variable and finds all the possible entries. Pick one of these entries using a number in the list:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/PsGet-v0.2Now-with-more-awesome_E323/image_4.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/PsGet-v0.2Now-with-more-awesome_E323/image_thumb_1.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;1004&quot; height=&quot;326&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The script will download a version of NuGet.exe from my site and then use it to install PS-Get. Since PS-Get includes it's own copy of NuGet.exe, the script will then delete this temporary version when it's finished.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/PsGet-v0.2Now-with-more-awesome_E323/image_6.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/PsGet-v0.2Now-with-more-awesome_E323/image_thumb_2.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;801&quot; height=&quot;161&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When the script completes, unless you really want to walk on the wild side, make sure you set your execution policy &lt;strong&gt;back to the default&lt;/strong&gt;! If you've never modified it before, that means you should run the following command to get it back to normal:&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;brush: ps&quot;&gt;Set-ExecutionPolicy Restricted&lt;/pre&gt;
&lt;p&gt;You've now installed PS-Get 0.2! Now, you still have to add it to your profile, just as before (though it has a slightly different name now):&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/PsGet-v0.2Now-with-more-awesome_E323/image_8.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/PsGet-v0.2Now-with-more-awesome_E323/image_thumb_3.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;793&quot; height=&quot;279&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And you're done! Enjoy and please let me know if you have comments!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>NuGet + PowerShell = (also) Crazy Delicious</title>
      <link>http://vibrantcode.com/blog/2011/2/10/nuget-powershell-also-crazy-delicious.html</link>
      <pubDate>Fri, 11 Feb 2011 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2011/2/10/nuget--powershell--also-crazy-delicious</guid>
      <description>&lt;p&gt;First off, I should note that I'm kinda paraphrasing this title from Scott Hanselman's &lt;a href=&quot;http://www.hanselman.com/blog/PDC10BuildingABlogWithMicrosoftUnnamedPackageOfWebLove.aspx&quot;&gt;excellent PDC 2010 talk&lt;/a&gt;, but I'm sure he's ok with that&lt;img class=&quot;wlEmoticon wlEmoticon-smile&quot; style=&quot;border-style: none;&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/wlEmoticon-smile_2.png&quot; alt=&quot;Smile&quot; /&gt;. By now, if you've been following the news coming out of the Microsoft Web Platform and Tools team, you've probably heard about our latest open-source project: NuGet. I'll let &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2011/01/13/announcing-release-of-asp-net-mvc-3-iis-express-sql-ce-4-web-farm-framework-orchard-webmatrix.aspx&quot;&gt;Scott Guthrie&lt;/a&gt; fill you in if you haven't heard about it already. Well, since shipping Web Pages v1/MVC v3, we've been working on general clean-up of both our code and our processes. For me, part of that entailed wiping all my dev machines and re-installing from scratch (there's a certain level of happiness provided by a nice fresh machine &lt;img class=&quot;wlEmoticon wlEmoticon-smile&quot; style=&quot;border-style: none;&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/wlEmoticon-smile_2.png&quot; alt=&quot;Smile&quot; /&gt;). As part of that, I was organizing my little PowerShell utility scripts into &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dd878324(VS.85).aspx&quot;&gt;Modules&lt;/a&gt;. I've also been thinking of organizing them a bit so that they could be released, but I ran in to a problem: There isn't really a great way to distribute PowerShell Modules!&lt;/p&gt;
&lt;p&gt;In PowerShell, a Module is really just a script within a special folder. When you &quot;Import&quot; the module, the script is run and the functions/variables/etc. it exports are added to the shell environment. There's much more to it, but I'll leave it to MSDN to explain the rest if you're interested.&lt;/p&gt;
&lt;p&gt;Deploying a Module is as simple as dropping a folder in C:\Users\[user name]\Documents\WindowsPowerShell\Modules. But in order to get a Module from the Web, like say the very useful &lt;a href=&quot;http://pscx.codeplex.com/&quot;&gt;PowerShell Community Extensions&lt;/a&gt; package, you have to download a ZIP and extract it to the right place. Earlier this week I had a brainwave: &quot;Isn't this _exactly_ what NuGet is designed to do?&quot;&lt;/p&gt;
&lt;p&gt;So, I spent a bit of spare time working on something I call &quot;PsGet&quot;, which I'm releasing a very early version of &lt;strong&gt;right now&lt;/strong&gt;. PsGet is a PowerShell Module that uses NuGet to deploy other PowerShell Modules. Right now, you do have to manually install PsGet, but I'm hoping to set up a single bootstrapping script that you can download and run to install it automatically. Let's walk through how it works:&lt;/p&gt;
&lt;p&gt;First, download the PsGetBoot module from the &lt;a href=&quot;http://code.andrewnurse.net/psget&quot;&gt;BitBucket site&lt;/a&gt; I've set up. &lt;a href=&quot;http://code.andrewnurse.net/psget/downloads/PsGetBoot-0.1.0.0.zip&quot;&gt;Here's a direct link to the ZIP file&lt;/a&gt;. Then, make sure the ZIP is unblocked in Explorer:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_2.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_thumb.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;380&quot; height=&quot;518&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, open/create your PowerShell Modules folder in Explorer. It needs to go in &quot;C:\Users\[username]\Documents\WindowsPowerShell\Modules&quot;. If you have moved your My Documents folder (like I have, to the D: drive in this case), you should update the path accordingly. Open the ZIP file in Explorer and copy the PsGetBoot folder into your Modules folder:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_4.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_thumb_1.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;922&quot; height=&quot;522&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next, you need to ensure you've enabled the execution of unsigned scripts. If you've already done this, skip this step. Start a PowerShell window as Administrator and run the following command: &quot;Set-ExecutionPolicy RemoteSigned&quot;. Enter &quot;Y&quot; at the confirmation prompt.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_6.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_thumb_2.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;530&quot; height=&quot;106&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ok, if you skipped the last step, open a PowerShell window. Otherwise, you've already got one open &lt;img class=&quot;wlEmoticon wlEmoticon-smile&quot; style=&quot;border-style: none;&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/wlEmoticon-smile_2.png&quot; alt=&quot;Smile&quot; /&gt;. Now we need to open your profile script and add a line to activate PsGet. The profile script is the script that runs every time you open PowerShell. First, let's make sure all the necessary folders exist by running:&lt;/p&gt;
&lt;pre class=&quot;brush: ps&quot;&gt;mkdir (Split-Path -Parent $profile)&lt;/pre&gt;
&lt;p&gt;If you get an error saying the item already exists, don't worry, it just means you didn't need to do this step &lt;img class=&quot;wlEmoticon wlEmoticon-smile&quot; style=&quot;border-style: none;&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/wlEmoticon-smile_2.png&quot; alt=&quot;Smile&quot; /&gt;. Next, open your profile script up in notepad (or your favorite text editor) and make sure to create it if it doesn't already exist:&lt;/p&gt;
&lt;pre class=&quot;ps&quot;&gt;notepad $profile&lt;/pre&gt;
&lt;p&gt;Type the following somewhere in the main body of your profile. It can go at the end, the beginning, or the middle, but &lt;strong&gt;not &lt;/strong&gt;within a function:&lt;/p&gt;
&lt;pre class=&quot;brush: ps&quot;&gt;Import-Module PsGetBoot&lt;/pre&gt;
&lt;p&gt;Then save the file, shutdown your PowerShell windows and open up a new one (Admin privileges are NOT required this time). The line we added to the PowerShell Profile will load in the PsGet &quot;Bootstrapper&quot; module. This is a module which just imports the &quot;PS-Get&quot; module and starts up PsGet. The purpose of this bootstrapper is to allow PsGet to update itself using PsGet &lt;img class=&quot;wlEmoticon wlEmoticon-smile&quot; style=&quot;border-style: none;&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/wlEmoticon-smile_2.png&quot; alt=&quot;Smile&quot; /&gt;.&lt;/p&gt;
&lt;p&gt;Once you've started PowerShell back up, you're all done! You now have two new commands. The first is &quot;Get-PSPackage&quot;. I should warn you that this command is extremely simple right now and just lists every NuGet package from the main &lt;a href=&quot;http://nuget.org&quot;&gt;nuget.org&lt;/a&gt; feed, so be prepared for it to take a few minutes when you run it. PsGet automatically works against the main NuGet feed at &lt;a href=&quot;http://nuget.org&quot;&gt;nuget.org&lt;/a&gt;, but it doesn't really make sense to install packages like Entity Framework in to PowerShell. So, as a convention for now, packages on nuget.org which are PowerShell modules should have names which start &quot;PS-&quot;. For example, I've already posted a very very simple package called PS-Bitz which is a library of useful functions (and by library, I mean a single function, for now &lt;img class=&quot;wlEmoticon wlEmoticon-winkingsmile&quot; style=&quot;border-style: none;&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/wlEmoticon-winkingsmile_2.png&quot; alt=&quot;Winking smile&quot; /&gt;). To find all the PowerShell packages, just go to nuget.org and search for &quot;PS-&quot;, or just click &lt;a href=&quot;http://nuget.org/Packages/Search?packageType=Packages&amp;amp;searchCategory=All+Categories&amp;amp;searchTerm=PS-&quot;&gt;here&lt;/a&gt;. Once you've found a package, just use the &quot;Install-PSPackage&quot; command to install it:&lt;/p&gt;
&lt;pre class=&quot;brush: ps&quot;&gt;Install-PSPackage PS-Bitz&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_8.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_thumb_3.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;406&quot; height=&quot;113&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once the package is installed, you should be able to see it when you get the list of available PowerShell Modules:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_10.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_thumb_4.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;608&quot; height=&quot;261&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(I'm not entirely sure why multiple entries show up, please &lt;a href=&quot;http://scr.im/anurse&quot;&gt;let me know&lt;/a&gt; if you know why &lt;img class=&quot;wlEmoticon wlEmoticon-smile&quot; style=&quot;border-style: none;&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/wlEmoticon-smile_2.png&quot; alt=&quot;Smile&quot; /&gt;).&lt;/p&gt;
&lt;p&gt;Now that it's installed, you can add it to your &lt;strong&gt;CURRENT&lt;/strong&gt; shell by running Import-Module:&lt;/p&gt;
&lt;pre class=&quot;brush: ps&quot;&gt;Import-Module PS-Bitz.0.1.0.0&lt;/pre&gt;
&lt;p&gt;You can then use all the functions provided by it. In this package, there's a single function used to get the path of special folders like MyDocuments:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_12.png&quot;&gt;&lt;img style=&quot;background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;&quot; title=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/46b266822777_DB0A/image_thumb_5.png&quot; border=&quot;0&quot; alt=&quot;image&quot; width=&quot;432&quot; height=&quot;112&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you want to make it available every time you launch PowerShell, just add an &quot;Import-Module&quot; line for it to your Profile, just as we did with PsGetBoot.&lt;/p&gt;
&lt;p&gt;As you can probably see, PsGet is pretty rough around the edges right now, but I'm hoping to improve it over time. I've set up a BitBucket repository &lt;a href=&quot;http://code.andrewnurse.net/psget&quot;&gt;here&lt;/a&gt;, so feel free to fork it and hack away. I'm licensing it under the &lt;a href=&quot;http://www.apache.org/licenses/LICENSE-2.0&quot;&gt;Apache Public License&lt;/a&gt;, which matches NuGet's license. &lt;a href=&quot;http://scr.im/anurse&quot;&gt;Let me know&lt;/a&gt; what you think! And start posting PowerShell module packages to NuGet.org!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Hosting Razor outside of ASP.Net (Revised for MVC3 RC!)</title>
      <link>http://vibrantcode.com/blog/2010/11/16/hosting-razor-outside-of-aspnet-revised-for-mvc3-rc.html</link>
      <pubDate>Tue, 16 Nov 2010 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2010/11/16/hosting-razor-outside-of-aspnet-revised-for-mvc3-rc</guid>
      <description>&lt;p&gt;We recently released the latest preview release of MVC 3, including an updated version of Razor.&amp;nbsp; One of the things we did in this release is simplify the hosting APIs dramatically.&amp;nbsp; I did a demo of these new APIs in a pre-recorded PDC10 talk I did with &lt;a href=&quot;http://blogs.msdn.com/b/scothu/&quot;&gt;Scott Hunter&lt;/a&gt;, which is available to stream here: &lt;a title=&quot;http://bit.ly/ac7B0P&quot; href=&quot;http://bit.ly/ac7B0P&quot;&gt;http://bit.ly/ac7B0P&lt;/a&gt;.&amp;nbsp; As I promised in that talk (and a few others before and after it &lt;img class=&quot;wlEmoticon wlEmoticon-confusedsmile&quot; style=&quot;border-style: none;&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Windows-Live-Writer/7a699e7dfd22_9002/wlEmoticon-confusedsmile_2.png&quot; alt=&quot;Confused smile&quot; /&gt;), I'm finally blogging about the sample I showed in that talk!&lt;/p&gt;
&lt;p&gt;The hosting APIs center around two classes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RazorTemplateEngine: the primary entry point to the Razor engine &lt;/li&gt;
&lt;li&gt;RazorEngineHost: defines the environment in which the generated Razor code will run &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First, let's look at the Host.&amp;nbsp; RazorEngineHost is a class with a number of useful properties on it that can tweak the way the generated code behaves.&amp;nbsp; More interestingly (though also more complicated and a topic for later), it can be subclassed and used to swap out the parser and code generator with your own custom code to add new keywords and features to Razor for your scenario!&amp;nbsp; In the sample I showed at PDC, we just used the properties to configure things, like so:&lt;/p&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;// Set up the hosting environment

// a. Use the C# language (you could detect this based on the file extension if you want to)
RazorEngineHost host = new RazorEngineHost(new CSharpRazorCodeLanguage());

// b. Set the base class
host.DefaultBaseClass = typeof(TemplateBase).FullName;

// c. Set the output namespace and type name
host.DefaultNamespace = &quot;RazorOutput&quot;;
host.DefaultClassName = &quot;Template&quot;;

// d. Add default imports
host.NamespaceImports.Add(&quot;System&quot;);
host.NamespaceImports.Add(&quot;System.IO&quot;);&lt;/pre&gt;
&lt;p&gt;This code is just doing fairly simple (but powerful) stuff.&amp;nbsp; It first sets the base class for the template.&amp;nbsp; Since we are running Razor outside of ASP.Net, you don't have to use our base classes.&amp;nbsp; In fact, you have to provide your own!&amp;nbsp; The sample contains a simple base class which just writes the template content to a StringBuilder we can retrieve later.&lt;/p&gt;
&lt;p&gt;Razor generated code using a certain convention (that can be overridden if necessary).&amp;nbsp; The generated template will contain a public method called &quot;Execute&quot; and that method will contain the users code and calls to one of the following methods:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write() - When a user types &quot;@foo&quot;, we generate Write(foo) in the generated code&lt;/li&gt;
&lt;li&gt;WriteLiteral() - When a user types literal markup, like &quot;&amp;lt;p&amp;gt;Foo&amp;lt;/p&amp;gt;&quot;, we generate WriteLiteral(&quot;&amp;lt;p&amp;gt;Foo&amp;lt;/p&amp;gt;&quot;) in the generated code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The names of these methods can be configured using the GeneratedClassContext property of the host, but we won't go into details on that here.&amp;nbsp; If you want to enable features like Sections, Templates and Helpers in your custom Razor host, you need to set some properties here but we'll cover that another time.&lt;/p&gt;
&lt;p&gt;The host also defines the namespace and class name of the generated C# or VB code, and the list of namespaces to be imported into the template's generated code file.&amp;nbsp; Once we've configured our host, we construct a RazorTemplateEngine and give it this host to use:&lt;/p&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;// Create the template engine using this host
return new RazorTemplateEngine(host);&lt;/pre&gt;
&lt;p&gt;From there, we're set to generate some code!&amp;nbsp; Let's look at what happens when you click the &quot;Load Template&quot; button in the sample.&lt;/p&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;// Generate code for the template
GeneratorResults razorResult = null;
using (TextReader rdr = new StringReader(templateTextBox.Text))
{
    razorResult = _engine.GenerateCode(rdr);
}&lt;/pre&gt;
&lt;p&gt;Now that we have our engine configured, all we need to do is take the template source code (from a text box in this case), open up a TextReader for it, and pass it in to the RazorTemplateEngine we constructed earlier.&amp;nbsp; The result of that call is a structure called GeneratorResults which contains the following properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Success - A boolean indicating if parsing and code generation were successful&lt;/li&gt;
&lt;li&gt;GeneratedCode - A CodeDOM tree representing the code that the Razor engine generated&lt;/li&gt;
&lt;li&gt;ParserErrors - A list of parser errors, if any&lt;/li&gt;
&lt;li&gt;Document - The root node of the Razor parse tree (we'll cover that later)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From this one call, you get all that data!&amp;nbsp; You can party on the parse tree, or use the CodeDOM APIs in the core .Net Framework to generate source code.&amp;nbsp; In the sample, I take the CodeDOM tree, compile an assembly using it, then load the assembly and the generated template type.&amp;nbsp; It takes quite a bit of code, so I'll leave that to the sample rather than posting it all here, but it's easily wrapped up in a helper method if you are going to be doing a lot of compiling!&lt;/p&gt;
&lt;p&gt;It is important to note that Razor is &lt;strong&gt;not&lt;/strong&gt; an interpreted language.&amp;nbsp; It actually follows the same compilation model as ASPX, despite the drastically different syntax.&amp;nbsp; The first time a user requests a Razor page, we generate the C#/VB code for it and compile it into an assembly.&amp;nbsp; All future requests, until the original file is changed, go against that compiled C#/VB code.&amp;nbsp; This means we can't easily do things like implementing &quot;eval&quot; because we aren't actually running the Razor code directly, we're just using it to generate C#/VB code.&lt;/p&gt;
&lt;p&gt;Hopefully that gives you a quick summary of how to get your feet wet hosting Razor outside of ASP.Net.&lt;/p&gt;
&lt;p&gt;Also, in MVC RC, we released Visual Studio support for Razor.&amp;nbsp; It's still an early release, so there might be some issues.&amp;nbsp; We'd like to hear from you if you encounter any issues!&amp;nbsp; Email &lt;a href=&quot;mailto:razorvs@microsoft.com&quot;&gt;razorvs@microsoft.com&lt;/a&gt; with your issues (&lt;strong&gt;related to VS tooling only please)&lt;/strong&gt;.&amp;nbsp; If you have other questions about Razor in general, tweet me at @anurse or email me at andrew AT andrewnurse DOT net!&lt;/p&gt;
&lt;p&gt;Here's the sample: &lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/HtmlGen.zip&quot;&gt;HtmlGen.zip (65.04 KB)&lt;/a&gt; (NOTE: MVC 3 RC is required).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Microsoft.Data - It's not as evil as you think</title>
      <link>http://vibrantcode.com/blog/2010/8/3/microsoftdata-its-not-as-evil-as-you-think.html</link>
      <pubDate>Wed, 04 Aug 2010 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2010/8/3/microsoftdata--its-not-as-evil-as-you-think</guid>
      <description>&lt;p&gt;I wanted to jump in with my $0.02 (Canadian &lt;img class=&quot;wlEmoticon wlEmoticon-winkingsmile&quot; style=&quot;border-style: none;&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/97689d4d0423_D66C/wlEmoticon-winkingsmile_2.png&quot; alt=&quot;Winking smile&quot; /&gt;) on Microsoft.Data.&amp;nbsp; David Fowler, fellow ASP.Net team member, &lt;a href=&quot;http://weblogs.asp.net/davidfowler/archive/2010/08/02/introduction-to-microsoft-data-dll.aspx&quot;&gt;posted about it earlier today&lt;/a&gt;, and the &lt;a href=&quot;http://twitter.com/ayende/status/20161027530&quot;&gt;response&lt;/a&gt; &lt;a href=&quot;http://twitter.com/HumanCompiler/status/20164296473&quot;&gt;has&lt;/a&gt; &lt;a href=&quot;http://ayende.com/Blog/archive/2010/08/03/microsoft.data-because-the-90s-were-so-good-we-want-to.aspx?utm_source=feedburner&amp;amp;utm_medium=feed&amp;amp;utm_campaign=Feed%3A+AyendeRahien+%28Ayende+%40+Rahien%29&quot;&gt;been&lt;/a&gt; ... &lt;a href=&quot;http://twitter.com/jburger/status/20170468880&quot;&gt;active&lt;/a&gt; &lt;img class=&quot;wlEmoticon wlEmoticon-smile&quot; style=&quot;border-style: none;&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/97689d4d0423_D66C/wlEmoticon-smile_2.png&quot; alt=&quot;Smile&quot; /&gt;.&amp;nbsp; The message behind most of these responses has been that it encourages bad practices to novice developers.&amp;nbsp; I think there's an important point that's being missed here: It doesn't matter how hard we work, as professional developers, to create clean architectures and abstractions, there's a whole world of novice developers who just don't care about that.&amp;nbsp; They want to write code now and be done with it.&amp;nbsp; This is the audience targeted by Microsoft.Data, and the WebMatrix product as a whole.&amp;nbsp; If novice developers come to the Microsoft platform and see these complicated architectures (which, don't get me wrong, have massive benefits for professional development), they &lt;strong&gt;simply won't adopt them&lt;/strong&gt;, they'll just head to a different platform which allows them to get their job done quickly.&lt;/p&gt;
&lt;p&gt;Microsoft.Data is, in my opinion, actually a step in the right direction.&amp;nbsp; For example, let's say I'm a novice developer, and I go out and look for samples and documentation in order to piece together a simple product list from my database.&amp;nbsp; As long as we do our work right (and we plan to), the documentation will lead me to write something like this:&lt;/p&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;@{ var products = db.Query(&quot;SELECT * FROM Products WHERE CategoryId = @0&quot;, categoryId); }

@foreach(var product in products) {
    &amp;lt;li&amp;gt;@product.Name&amp;lt;/li&amp;gt;
}&lt;/pre&gt;
&lt;p&gt;It works, and it's SQL Injection safe.&amp;nbsp; Note that although David didn't blog directly about this, Microsoft.Data &lt;strong&gt;fully supports parameterized SQL&lt;/strong&gt; and it actually supports it &lt;span style=&quot;text-decoration: underline;&quot;&gt;better&lt;/span&gt; than traditional ADO.Net (note that I don't have to fiddle with SqlParameter objects).&lt;/p&gt;
&lt;p&gt;Now, I'm learning more about proper architecture, and I decide to switch to an ORM and use Linq for my queries.&amp;nbsp; A quick one-liner change and I'm all set:&lt;/p&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;@{ var products = db.Products.Where(p =&amp;gt; p.CategoryId == categoryId); }

@foreach(var product in products) {
    &amp;lt;li&amp;gt;@product.Name&amp;lt;/li&amp;gt;
}&lt;/pre&gt;
&lt;p&gt;[NOTE: WebMatrix doesn't include a true ORM, as there are plenty of good options out there, this is just a sample of how one could ramp up from Microsoft.Data to more powerful ORMs]&lt;/p&gt;
&lt;p&gt;And if I want to go full-tilt and use ASP.Net MVC, I can move my data access code into a Controller (or even deeper into my architecture) and then a bit of copy-pasting gets me to:&lt;/p&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;public ActionResult Products(int categoryId) {
    var products = db.Products.Where(p =&amp;gt; p.CategoryId == categoryId);
    return View(products);
}&lt;/pre&gt;
&lt;pre class=&quot;brush: csharp&quot;&gt;@foreach(var product in Model) {
    &amp;lt;li&amp;gt;@product.Name&amp;lt;/li&amp;gt;
}&lt;/pre&gt;
&lt;p&gt;From there I'm free to keep refactoring things behind further abstractions (Repository patterns, etc.). I've started simple and refactored as necessary to improve the architecture. In every step, I've been able to take a lot of the existing code with me, which traditional ADO.Net and other platforms (like PHP) don't make quite as easy.&lt;/p&gt;
&lt;p&gt;The simple fact is this: The audience we're targeting is &lt;em&gt;&lt;strong&gt;already using&lt;/strong&gt; &lt;/em&gt;inline SQL, they are &lt;strong&gt;&lt;em&gt;perfectly happy&lt;/em&gt; &lt;/strong&gt;to keep doing so and they are &lt;strong&gt;&lt;em&gt;not interested &lt;/em&gt;&lt;/strong&gt;in clean abstractions (to the point of finding them complex and unnecessary).&amp;nbsp; Microsoft.Data, and the entire ASP.Net Web Pages framework (the inline page model used in WebMatrix), is an attempt to provide a simple model for web development that provides on-ramps to guide users towards best practices.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Inside Razor - Part 3 - Templates</title>
      <link>http://vibrantcode.com/blog/2010/8/2/inside-razor-part-3-templates.html</link>
      <pubDate>Mon, 02 Aug 2010 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2010/8/2/inside-razor--part-3--templates</guid>
      <description>&lt;p&gt;One of the features of Razor which hasn't been discussed a lot is the Inline Template feature.&amp;nbsp; Razor includes the ability to provide an inline Razor template as an argument to a method.&amp;nbsp; At the moment, this is only used by the Grid helper in ASP.Net Web Pages (and Scott Guthrie showed it back in his &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx&quot;&gt;original blog post&lt;/a&gt;).&amp;nbsp; However, we don't have much documentation on how to create your own templated helpers yet, so I figured I'd talk a bit about it.&lt;/p&gt;  &lt;p&gt;First, let's take a look at what code is generated when we use an inline template.&amp;nbsp; I've written a sample templated helper called &quot;Repeat&quot; which just repeats the content of the template a specified number of times (we'll take a look at the implementation later).&amp;nbsp; The page that uses this helper looks something like this:&lt;/p&gt;  &lt;br/&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;br/&gt;&amp;lt;html&amp;gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;head&amp;gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;Repeat Helper Demo&amp;lt;/title&amp;gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/head&amp;gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;body&amp;gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;p&amp;gt;Repeat Helper&amp;lt;/p&amp;gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;ul&amp;gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @Repeat(10, @&amp;lt;li&amp;gt;List Item&amp;lt;/li&amp;gt;);&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/ul&amp;gt;&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/body&amp;gt;&lt;br/&gt;&amp;lt;/html&amp;gt;&lt;/pre&gt;&lt;p&gt;And when we run it, we get the following output:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/InsideRazorPart3Templates_13B11/ss1_2.png&quot;&gt;&lt;img style=&quot;border-width: 0px; display: inline;&quot; title=&quot;Screen shot of rendered HTML.&quot; alt=&quot;Screen shot of rendered HTML.&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/InsideRazorPart3Templates_13B11/ss1_thumb.png&quot; width=&quot;385&quot; border=&quot;0&quot; height=&quot;400&quot;&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Let's take a look at the implementation of &quot;Repeat&quot;.&amp;nbsp; I wrote it inline in the page in this case, but you could just as easily write it in a static class in App_Code and reference it that way.&amp;nbsp; In Razor, the &quot;@functions&quot; block lets you write code that will be injected as-is into the body of the generated class.&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;@using System.Text;&lt;br/&gt;@functions {&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IHtmlString Repeat(int times, Func&amp;lt;int, object&amp;gt; template) {&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; StringBuilder builder = new StringBuilder();&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for(int i = 0; i &amp;lt; times; i++) {&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; builder.Append(template(i));&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return new HtmlString(builder.ToString());&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;So, the template is being passed in as a Func&amp;lt;int, object&amp;gt; and when we invoke it, we get back the result of running the template.&amp;nbsp; But, if you look at line 6, you'll notice we're passing in an argument to the template function.&amp;nbsp; Let's take a look at the C# that is generated when we write a call to Repeat.&amp;nbsp; Here's the generated code to match the Razor code in the first code listing:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;this.Write(Repeat(10,item =&amp;gt; new Microsoft.WebPages.Helpers.HelperResult(__writer =&amp;gt; {&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @__writer.Write(&quot; &quot;);&lt;br/&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; @__writer.Write(&quot;&amp;lt;li&amp;gt;List Item&amp;lt;/li&amp;gt;&quot;);&lt;br/&gt;})));&lt;/pre&gt;&lt;p&gt;It's a little complex looking, but essentially, what's happening is that we're writing out a lambda which accepts a single parameter called &quot;item&quot; (the type of which is determined by the method you're passing it to).&amp;nbsp; When that lambda runs, we construct and return a HelperResult.&amp;nbsp; HelperResult is a class defined in the ASP.Net Web Pages framework, and it's essentially a wrapper around yet another delegate which writes text to a TextWriter.&amp;nbsp; Think of it as a mini Razor template, when you invoke the delegate, it writes the content of the template.&amp;nbsp; The advantage of wrapping the delegate up in the HelperResult class is that we can treat it just like a string in most places since it overrides ToString to return the result of executing the template.&lt;/p&gt;&lt;p&gt;The &quot;item&quot; parameter is used in helpers like the Grid helper to provide the current data item to the template so that it can be used.&amp;nbsp; The Repeat helper passes in the iteration number as this parameter, which we can access from within the template by using &quot;@item&quot;?.&amp;nbsp; For example:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;@Repeat(10, @&amp;lt;li&amp;gt;List Item #@item&amp;lt;/li&amp;gt;);&lt;/pre&gt;&lt;p&gt;Which will render:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/InsideRazorPart3Templates_13B11/ss2_2.png&quot;&gt;&lt;img style=&quot;border: 0px none; display: inline;&quot; title=&quot;ss2&quot; alt=&quot;ss2&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/InsideRazorPart3Templates_13B11/ss2_thumb.png&quot; width=&quot;324&quot; border=&quot;0&quot; height=&quot;373&quot;&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;In summary, if you want to use Razor templates in your helper methods, just add a parameter with the type Func&amp;lt;&lt;em&gt;?&lt;/em&gt;, object&amp;gt; where &lt;em&gt;?&lt;/em&gt; can be &lt;strong&gt;any&lt;/strong&gt; type you want.&amp;nbsp; As an interesting little exercise, try converting the Repeat helper to take an IEnumerable&amp;lt;T&amp;gt; and pass each item of that enumerable to the template, rendering the result.&lt;br&gt;&lt;/p&gt;&lt;p&gt;I've uploaded the Razor file containing my sample helper here: &lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RepeatHelper.cshtml.txt&quot;&gt;RepeatHelper.cshtml.txt (.56 KB)&lt;/a&gt; (Note: To avoid issues with file types on my hoster, it has a .txt extension, just remove that and you're good to go!)&lt;/p&gt;&lt;p&gt;Please feel free to ask questions in the comments, or by emailing me at andrew AT andrewnurse DOT net.&amp;nbsp; I'm also on twitter at @anurse and I keep an eye on the &quot;razor&quot; tag on &lt;a href=&quot;http://www.stackoverflow.com&quot;&gt;StackOverflow&lt;/a&gt; so there's no shortage of ways to ask!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using the Razor parser outside of ASP.Net</title>
      <link>http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of-aspnet.html</link>
      <pubDate>Thu, 22 Jul 2010 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2010/7/22/using-the-razor-parser-outside-of-aspnet</guid>
      <description>&lt;p&gt;When Scott Guthrie originally blogged about Razor, he mentioned that it was fully hostable outside of ASP.Net.&amp;nbsp; The engine itself is not quite as detached from System.Web as we'd like, but it's close and we're going to get it way closer in the next release.&lt;/p&gt;  &lt;p&gt;Having said that, you can still host Razor outside of the ASP.Net pipeline with the current beta! It's a little trickier, and you do technically need to reference System.Web.&amp;nbsp; I've written a sample console app that I'm attaching to this post called &quot;rzrc&quot; which takes in&amp;nbsp; a .cshtml or .vbhtml Razor file and runs it through the parser and code generator to produce a .cs or .vb file.&amp;nbsp; I'll walk through the main logic here and go over what each section does.&lt;/p&gt;  &lt;p&gt;However, I was not the first to do this! Full credit for that goes to &lt;a href=&quot;http://thegsharp.wordpress.com/&quot;&gt;Gustavo Machado&lt;/a&gt;, who wrote &lt;a href=&quot;http://thegsharp.wordpress.com/2010/07/07/using-razor-from-a-console-application/&quot;&gt;an excellent post&lt;/a&gt; in which he used Reflector to work out how to run the Razor parser and code generator.&amp;nbsp; Well done Gustavo!&amp;nbsp; There are a few things that this version does that Gustavo's doesn't, such as cleaning up the Web-related stuff in the generated code and selecting the language based on the Code Language, but he basically hit it spot on!&lt;/p&gt;  &lt;p&gt;The first thing my console app does is get the input file name, extract the extension and look up what Razor Code Language it uses.&amp;nbsp; This is done using the CodeLanguageService class, which is part of the Razor APIs:&lt;/p&gt;  &lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;CodeLanguageService languageService = CodeLanguageService.GetServiceByExtension(extension);&lt;br/&gt;if (languageService == null) {&lt;br/&gt;    Console.WriteLine(&quot;{0} is not a Razor code language&quot;, extension);&lt;br/&gt;    return;&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Then, we fire up the parser and the code generator.&amp;nbsp; A CodeLanguageService is basically a factory for constructing a Code Parser, to parse the code blocks after an &quot;@&quot; and a matching Code Generator to write the final C# or VB class.&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;InlinePageParser parser = new InlinePageParser(languageService.CreateCodeParser(), new HtmlMarkupParser());&lt;br/&gt;CodeGenerator codeGenerator = &lt;br/&gt;    languageService.CreateCodeGeneratorParserListener(className,&lt;br/&gt;                                                        rootNamespaceName: &quot;Template&quot;, &lt;br/&gt;                                                        applicationTypeName: &quot;object&quot;, &lt;br/&gt;                                                        inputFileName, &lt;br/&gt;                                                        baseClass: &quot;System.Object&quot;);&lt;/pre&gt;&lt;p&gt;When you run the Razor Parser, you must provide it with an object implementing IParserConsumer.&amp;nbsp; This interface has callbacks which the parser will call when it encounters various Razor constructs (more details on the Razor parse tree later).&amp;nbsp; CodeGenerator implements this interface and responds to the these callbacks by generating code.&amp;nbsp; However, it does nothing with the errors, so in the console app, I've written a very simple IParserConsumer called CustomParserConsumer which wraps the code generator and outputs errors to the console.&amp;nbsp; I won't put the code here, but it's in the sample, so take a look there if you're interested.&lt;/p&gt;&lt;p&gt;Now that we've got all the objects we need, we can actually run the parser over the input&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;CustomParserConsumer consumer = new CustomParserConsumer() { CodeGenerator = codeGenerator };&lt;br/&gt;using (StreamReader reader = new StreamReader(inputFileName)) {&lt;br/&gt;    parser.Parse(reader, consumer);&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Once Parse returns, the Code Generator will have built a CodeDOM tree representing the generated code during the callbacks, so we know that our code is ready to go.&amp;nbsp; Right now, the Code Generator adds in some web specific things.&amp;nbsp; For example, when we constructed the Code Gneerator above, we gave it an &quot;applicationTypeName&quot; which (in a web context) is the type name of the class defined in Global.asax, if there is one.&amp;nbsp; Since we are trying to generate a template that isn't related to the web, we can get the CodeDOM tree from the Code Generator and remove these things.&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;codeGenerator.GeneratedCode.Namespaces[0].Types[0].Members.RemoveAt(0);&lt;br/&gt;codeGenerator.GeneratedCode.Namespaces[0].Types[0].BaseTypes.Clear();&lt;br/&gt;codeGenerator.GeneratedCode.Namespaces[0].Imports.Clear();&lt;/pre&gt;&lt;p&gt;Finally, we use the CodeDOM to write the code to a C# or VB class file (provider is a CodeDomProvider from System.CodeDom.Compiler):&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;using (StreamWriter writer = new StreamWriter(outputFile)) {&lt;br/&gt;    provider.GenerateCodeFromCompileUnit(codeGenerator.GeneratedCode, writer, new CodeDom.CodeGeneratorOptions());&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;And we're done!&amp;nbsp; This is definitely more complicated than we'd like, but there are plans to simplify this API significantly in future releases.&amp;nbsp; For the most part, all we've done is left the methods our ASP.Net Build Provider uses open and accessible.&amp;nbsp; I wouldn't bet on these APIs staying around too long, but any API changes from here on should be simplifications.&amp;nbsp; For now though, check out the sample I've attached and play around!&amp;nbsp; Note that you must have WebMatrix installed to use the sample.&amp;nbsp; &lt;/p&gt;&lt;p&gt;I've put some comments in which start with &quot;EXT&quot; which contain tips on how to extend this code to your own use.&amp;nbsp; Please feel free to take this code and use it absolutely anywhere you want!&amp;nbsp; Let me know how your using Razor by either tweeting me at @anurse or email me at andrew AT andrewnurse DOT net.&lt;/p&gt;&lt;p&gt;Download the console app here: &lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/rzrc.zip&quot;&gt;rzrc.zip (3.46 KB)&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Inside Razor - Part 2 - Expressions</title>
      <link>http://vibrantcode.com/blog/2010/7/12/inside-razor-part-2-expressions.html</link>
      <pubDate>Mon, 12 Jul 2010 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2010/7/12/inside-razor--part-2--expressions</guid>
      <description>&lt;p&gt;This is part 2 of my Inside Razor series. Read Part 1 &lt;a href=&quot;/2010/07/05/InsideRazorNdashPart1NdashRecursivePingPong.aspx&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;In my previous post, I glossed over one line in my sample:&lt;/p&gt;  &lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;&amp;lt;li&amp;gt;@p.Name ($@p.Price)&amp;lt;/li&amp;gt;&lt;/pre&gt;&lt;p&gt;Well, it's finally time to get in to how this is parsed! So, to recap from last time, when we see the &quot;&amp;lt;li&amp;gt;&quot; here, we know that we are parsing a block of markup which ends at the &quot;&amp;lt;/li&amp;gt;&quot;. The markup parser scans forward until it finds the end tag, but before it reaches it, it sees an &quot;@&quot;. So, just as with &quot;@foreach&quot;, it switches to the code parser.&lt;/p&gt;&lt;p&gt;This is where things get a bit different. The C# code parser looks at that first identifier: &quot;p&quot; and checks its internal list of C# keywords. Of course, &quot;p&quot; is not a C# keyword, so the C# code parser enters &quot;Implicit Expression&quot; mode. The algorithm for parsing implicit expressions is something like the following:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;First, &lt;strong&gt;&lt;em&gt;Read &lt;/em&gt;&lt;/strong&gt;an identifier &lt;/li&gt;&lt;li&gt;Is the next character a &quot;(&quot; or &quot;[&quot;?&lt;ul&gt;&lt;li&gt;Yes - &lt;strong&gt;&lt;em&gt;Read&lt;/em&gt;&lt;/strong&gt; to the matching &quot;)&quot; or &quot;]&quot;, then &lt;strong&gt;&lt;em&gt;Go To&lt;/em&gt; &lt;/strong&gt;2 &lt;/li&gt;&lt;li&gt;No - &lt;strong&gt;&lt;em&gt;Continue&lt;/em&gt;&lt;/strong&gt; to 3 &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Is the next character a &quot;.&quot;?    &lt;ul&gt;&lt;li&gt;Yes - &lt;strong&gt;&lt;em&gt;Continue&lt;/em&gt;&lt;/strong&gt; to 4 &lt;/li&gt;&lt;li&gt;No - &lt;strong&gt;&lt;em&gt;End&lt;/em&gt;&lt;/strong&gt; of Expression &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Is the character AFTER the &quot;.&quot; a valid start character for a C# identifier?&lt;ul&gt;&lt;li&gt;Yes - &lt;strong&gt;&lt;em&gt;Read&lt;/em&gt; &lt;/strong&gt;the &quot;.&quot; and &lt;strong&gt;&lt;em&gt;Go To&lt;/em&gt; &lt;/strong&gt;1 &lt;/li&gt;&lt;li&gt;No - &lt;u&gt;DO NOT Read&lt;/u&gt; the &quot;.&quot;, and &lt;em&gt;&lt;strong&gt;End&lt;/strong&gt;&lt;/em&gt; the Expression &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The high-level overview of this algorithm is that an implicit expression is an identifier, followed by any number of method calls (&quot;()&quot;), indexing expressions (&quot;[]&quot;) and member access expressions (&quot;.&quot;). And, whitespace is &lt;strong&gt;not allowed&lt;/strong&gt; (except for within &quot;()&quot; or &quot;[]&quot;). So for example, these are all valid implicit expressions in Razor:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;@p.Name&lt;br/&gt;@p.Name.ToString()&lt;br/&gt;@p.Name.ToString()[6 - 2]&lt;br/&gt;@p.Name.Replace(&quot;ASPX&quot;, &quot;Razor&quot;)[i++]&lt;/pre&gt;&lt;p&gt;However, the following are not valid, and the second section (after the arrow, &quot;==&amp;gt;&quot;) is the only part that would be considered part of the expression by Razor:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;@1 + 1 ==&amp;gt; @&lt;br/&gt;@p++ ==&amp;gt; @p&lt;br/&gt;@p    .   Name ==&amp;gt; @p&lt;br/&gt;@p.Name.Length - 1 ==&amp;gt; @p.Name.Length&lt;/pre&gt;&lt;p&gt;This is why we have another syntax for expressions: &quot;@(...)&quot;. This syntax allows anything you want within the &quot;()&quot;. So, you can write all of the previous examples using that syntax as an escape-hatch:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;@(1 + 1) &lt;br/&gt;@(p++) &lt;br/&gt;@(p    .   Name) &lt;br/&gt;@(p.Name.Length - 1)&lt;/pre&gt;&lt;p&gt;Once we've identified the expression, we pass it along to our code generator. When generating the code for &quot;@foreach () { ... }&quot;, we just dump that code into the generated C# class as-is, but when we identify an expression (either implicit or explicit) we do something a little different. You probably noticed that unlike ASPX, there is only one control construct: &quot;@&quot;, there is no &quot;@=&quot; to distinguish code that we run vs. expressions that we render the value of. This is where some of the magic of Razor comes in. If we see &quot;@foreach&quot; for example, we know that &quot;foreach&quot; is a C# keyword, so that block is written as a statement to be executed. When we see &quot;@p.Name&quot; or &quot;@(1 + 1)&quot;, we know that they are expressions, so after executing them, we render the result. So basically:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;@if, @switch, @try, @foreach, @for, etc. are equivalent to &quot;&amp;lt;% %&amp;gt;&quot; &lt;/li&gt;&lt;li&gt;@p.Name, @(p++), @(1 + 1), etc. are equivalent to &quot;&amp;lt;%: %&amp;gt;&quot; &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Another side note is that expressions are equivalent to &quot;&amp;lt;%:&quot; and &lt;strong&gt;NOT &lt;/strong&gt;&quot;&amp;lt;%=&quot;. We made a decision in Razor that &lt;strong&gt;HTML encoding should be the default&lt;/strong&gt;, and that if you want to write unencoded strings, you can use the IHtmlString interface that has been &lt;a href=&quot;http://haacked.com/archive/2009/09/25/html-encoding-code-nuggets.aspx&quot;&gt;blogged about&lt;/a&gt; before.&lt;/p&gt;&lt;p&gt;So, with all that background, we can quickly jump back to our initial sample:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;&amp;lt;li&amp;gt;@p.Name ($@p.Price)&amp;lt;/li&amp;gt;&lt;/pre&gt;&lt;p&gt;When we see &quot;@p.Name&quot; we identify that as an expression, but the space before the &quot;(&quot; stops us from interpreting it as a method call. Then &quot; ($&quot; are all markup and when we see the &quot;@&quot;, we interpret &quot;@p.Price&quot; as an expression and stop at the &quot;)&quot;.&lt;/p&gt;&lt;p&gt;So there's a quick overview of how Razor identifies and parses expressions. In my next post I'm going to discuss hosting the Razor parser outside of ASP.Net. As before, please feel free to leave comments if you have questions, or send me a tweet (@anurse) or an email (andrew AT andrewnurse DOT net).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Quick Update - Microsoft WebMatrix Beta released</title>
      <link>http://vibrantcode.com/blog/2010/7/6/quick-update-microsoft-webmatrix-beta-released.html</link>
      <pubDate>Tue, 06 Jul 2010 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2010/7/6/quick-update--microsoft-webmatrix-beta-released</guid>
      <description>Scott Guthrie just announced the first beta release of Microsoft WebMatrix.&amp;nbsp; I'll leave you to check out &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2010/07/06/introducing-webmatrix.aspx&quot;&gt;his blog post&lt;/a&gt; to find out more.&lt;br&gt;&lt;br&gt;This is also your &lt;b&gt;first chance&lt;/b&gt; to try out Razor.&amp;nbsp; We haven't released the MVC View Engine for Razor, but WebMatrix includes ASP.Net Web Pages, a simple page model that uses Razor syntax.&amp;nbsp; After installing WebMatrix, just create a new site, drop a CSHTML file in it, put some code in and go!&lt;br&gt;&lt;br&gt;I'll post more details later, but for now, check out the post and play with the bits!&lt;br&gt;&lt;p&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Inside Razor - Part 1 - Recursive Ping-Pong</title>
      <link>http://vibrantcode.com/blog/2010/7/5/inside-razor-part-1-recursive-ping-pong.html</link>
      <pubDate>Mon, 05 Jul 2010 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2010/7/5/inside-razor--part-1--recursive-pingpong</guid>
      <description>&lt;p&gt;This is the first of my blog posts about the parser for the new &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx&quot;&gt;ASP.Net Razor&lt;/a&gt; syntax.&amp;nbsp; We've been working on this parser for a while now, and I want to share some of how it works with my readers!&lt;/p&gt;  &lt;p&gt;The Razor parser is very different from the existing ASPX parser.&amp;nbsp; In fact, the ASPX parser is implemented almost entirely with Regular Expressions, because it is a very simple language to parse.&amp;nbsp; The Razor parser is actually separated into three components: 1) A Markup parser which has a basic understanding of HTML syntax, 2) A Code parser which has a basic understanding of either C# or VB and 3) A central orchestrator which understands how the two mix together.&amp;nbsp; Note that when I say &quot;basic understanding&quot; I mean basic, we're not talking about full-fledged C# and HTML parsers here.&amp;nbsp; I've joked with people on the team that we should call them &quot;Markup Understander&quot; or &quot;Code Comprehender&quot; instead :).&lt;/p&gt;  &lt;p&gt;So the Razor parser has three &quot;actors&quot;: The Core Parser, the Markup Parser and the Code Parser.&amp;nbsp; All three work together to parse a Razor document.&amp;nbsp; Now, let's take a Razor file and do a full summary of the parsing procedure using these actors.&amp;nbsp; We'll use the sample that I used last time:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;&amp;lt;ul&amp;gt;&lt;br/&gt;    @foreach(var p in Model.Products) {&lt;br/&gt;    &amp;lt;li&amp;gt;@p.Name ($@p.Price)&amp;lt;/li&amp;gt;&lt;br/&gt;    }&lt;br/&gt;&amp;lt;/ul&amp;gt;&lt;br/&gt;&lt;/pre&gt;&lt;p&gt;Ok, now we start at the top. The Razor parser is essentially in one of three states at any time during the parsing: Parsing a Markup Document, Parsing a Markup Block or Parsing a Code Block.&amp;nbsp; The first two are handled by the Markup Parser, and the last is handled by the Code Parser.&amp;nbsp; So, when the Core Parser is fired up for the first time, it calls into the Markup Parser and asks it to parse a Markup Document and return the result.&amp;nbsp; Now the parser is in the Markup Document state.&amp;nbsp; In this state, it simply scans forward to the next &quot;@&quot; character, it doesn't care about tags or other HTML concepts, just &quot;@&quot;.&amp;nbsp; When it reaches an &quot;@&quot;, it makes a decision: &quot;Is this a switch to code, or is it an email address?&quot;&amp;nbsp; This decision is basically done by looking just before and just after the &quot;@&quot; to see if they are valid email characters.&amp;nbsp; This is the default convention, but there are escape sequences to force it to be treated as a switch to code.&lt;/p&gt;&lt;p&gt;In this case, when we see our first &quot;@&quot;, it is preceded by whitespace, which is not valid in an email address.&amp;nbsp; So, we now know we are switching to code.&amp;nbsp; The Markup Parser calls into the Code Parser and asks it to parse a Code Block.&amp;nbsp; A Block, in terms of the Razor Parser, is basically a single chunk of Code or Markup with a clear start and end sequence.&amp;nbsp; So, the 'foreach' statement here is an example of a Code Block.&amp;nbsp; It starts at the &quot;f&quot; character and ends at the &quot;}&quot; character.&amp;nbsp; The Code Parser knows enough about C# to know this, so it starts parsing the code.&amp;nbsp; The Code Parser does some very simple tracking of C# statements, so when it gets to the &quot;&amp;lt;li&amp;gt;&quot; it knows it's at the start of a C# statement.&amp;nbsp; &quot;&amp;lt;li&amp;gt;&quot; is not something you can put at the start of a C# statement, so the Code Parser knows that this is the start of nested Markup Block.&amp;nbsp; So, it calls back into the Markup Parser, to have it parse a block of HTML.&amp;nbsp; This creates a sort of &lt;strong&gt;recursive ping-pong game&lt;/strong&gt; between the Code and Markup parsers.&amp;nbsp; We start in Markup, then call into Code, then call into Markup and so on before finally returning back up this whole chain.&amp;nbsp; At the moment, the call stack in the parser looks something like this:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;HtmlMarkupParser.ParseDocument()&lt;ul&gt;&lt;li&gt;CSharpCodeParser.ParseBlock() &lt;ul&gt;&lt;li&gt;HtmlMarkupParser.ParseBlock() &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;(Obviously, I am leaving out a lot of helper methods :)).&lt;/p&gt;&lt;p&gt;This highlights a fundamental difference between ASPX and Razor.&amp;nbsp; In an ASPX file, you can think of Code and Markup as two parallel streams.&amp;nbsp; You write some Markup, then you jump over and write some code, then you jump back and write some Markup, and so on.&amp;nbsp; A Razor file is like a tree.&amp;nbsp; You write some Markup, and then put some Code &lt;strong&gt;inside&lt;/strong&gt; that Markup, then put some Markup &lt;strong&gt;inside&lt;/strong&gt; that Code, and so on.&lt;/p&gt;&lt;p&gt;So, we've just called into the Markup Parser to parse a block of Markup, this block starts at &quot;&amp;lt;li&amp;gt;&quot; and ends at the matching &quot;&amp;lt;/li&amp;gt;&quot;.&amp;nbsp; Until that matching &quot;&amp;lt;/li&amp;gt;&quot;, we won't consider the Markup Block finished.&amp;nbsp; So even if you had a &quot;}&quot; somewhere inside the &quot;&amp;lt;li&amp;gt;&quot; it wouldn't terminate the &quot;foreach&quot;, because we haven't come far enough up the stack yet.&lt;/p&gt;&lt;p&gt;While parsing the &quot;&amp;lt;li&amp;gt;&quot;, the Markup Parser sees more &quot;@&quot; characters, which means even more calls into the Code Parser. And so the call stack grows:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;HtmlMarkupParser.ParseDocument()&lt;ul&gt;&lt;li&gt;CSharpCodeParser.ParseBlock()&lt;ul&gt;&lt;li&gt;HtmlMarkupParser.ParseBlock()&lt;ul&gt;&lt;li&gt;CSharpCodeParser.ParseBlock() &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I'll go into detail on how these blocks are terminated later, because it is a little complicated, but eventually we finish these code blocks and we're back in the &quot;&amp;lt;li&amp;gt;&quot; block.&amp;nbsp; Then, we see &quot;&amp;lt;/li&amp;gt;&quot; so we finish that block and pop back up to the &quot;foreach&quot; block.&amp;nbsp; The &quot;}&quot; terminates that block, so we back up to the top of our stack again: the Markup Document.&amp;nbsp; Then we read until the end of the file, not finding anymore &quot;@&quot; characters.&amp;nbsp; And we're done!&amp;nbsp; We've parsed the entire file!&lt;/p&gt;&lt;p&gt;I hope that's made the general structure of the parsing algorithm somewhat more clear.&amp;nbsp; The key take-away here is to avoid thinking of Code and Markup as separate streams and think of them as constructs you nest inside each other.&amp;nbsp; Our next topic will be Implicit Expressions, which is the logic that allows us to detect what parts of &quot;@p.Name ($@p.Price)&quot; are code, and what are markup.&amp;nbsp; I'll give you a hint, we took some inspiration from PowerShell here ;).&lt;/p&gt;&lt;p&gt;Please post any questions or comments in the comments section or email me at &quot;andrew AT andrewnurse DOT net&quot;!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Introducing Razor - A New View Engine for ASP.Net</title>
      <link>http://vibrantcode.com/blog/2010/7/3/introducing-razor-a-new-view-engine-for-aspnet.html</link>
      <pubDate>Sat, 03 Jul 2010 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2010/7/3/introducing-razor--a-new-view-engine-for-aspnet</guid>
      <description>&lt;p&gt;UPDATE: Fixed broken examples (I hope :)).&lt;/p&gt;  &lt;p&gt;Earlier this morning, &lt;a href=&quot;http://weblogs.asp.net/scottgu&quot;&gt;Scott Guthrie&lt;/a&gt; &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx&quot;&gt;blogged about a new View Engine we're developing for ASP.Net&lt;/a&gt;. As many of my readers know, I joined the ASP.Net team back in October in 2009, and I'm really excited to finally be able to share what I have been working on for the past 8 months. When I joined Microsoft, I was shown some early prototypes for this new syntax and over the course of the next 8 months, we developed it into the Beta we're going to be releasing very soon.&lt;/p&gt;  &lt;p&gt;Writing the parser for Razor has essentially been my job for the last 8 months, so I'd like to describe a little about some of the design ideas that went in to it as well as some of the interesting ways we implemented things. This is the first in a few blog posts I'll do about the Razor syntax as well as the Parser design.&lt;/p&gt;  &lt;p&gt;Razor syntax is designed around one primary goal: Make code and markup flow together with as little interference from control characters as possible. For example, let's take the following ASPX:&lt;/p&gt;&lt;pre class=&quot;brush: csharp&quot;&gt;&amp;lt;ul&amp;gt;
    &amp;lt;% foreach(var p in Model.Products) { %&amp;gt;
    &amp;lt;li&amp;gt;&amp;lt;%= p.Name %&amp;gt; ($&amp;lt;%= p.Price %&amp;gt;)&amp;lt;/li&amp;gt;
    &amp;lt;% } %&amp;gt;
&amp;lt;/ul&amp;gt;&lt;/pre&gt;&lt;p&gt;Now, let's boil it down to the parts that we actually care about, removing all of the extra ASPX control characters:&lt;/p&gt;&lt;pre class=&quot;brush: csharp&quot;&gt;&amp;lt;ul&amp;gt;
    foreach(var p in Model.Products) {
    &amp;lt;li&amp;gt;p.Name ($p.Price)&amp;lt;/li&amp;gt;
    }
&amp;lt;/ul&amp;gt;&lt;/pre&gt;&lt;p&gt;Obviously there isn't enough data here to unambiguously determine what's code and what's markup. When we were designing Razor, we started from here and added as little as we could to make it absolutely clear what is code and what is markup. We wanted Razor pages to be Code+Markup, with a little extra stuff as possible. We even used that goal as inspiration for the file extension for C# and VB Razor pages: &lt;strong&gt;cshtml&lt;/strong&gt; and &lt;strong&gt;vbhtml&lt;/strong&gt;. &lt;/p&gt;&lt;p&gt;So, using the C# Razor syntax, the above example becomes:&lt;/p&gt;&lt;pre class=&quot;brush: csharp&quot;&gt;&amp;lt;ul&amp;gt;
    @foreach(var p in Model.Products) {
    &amp;lt;li&amp;gt;@p.Name ($@p.Price)&amp;lt;/li&amp;gt;
    }
&amp;lt;/ul&amp;gt;&lt;/pre&gt;&lt;p&gt;If you ask me, that's pretty darn close to the previous example. Razor takes advantage of a deep knowledge of C# (or VB) and HTML syntaxes to infer a lot about what you intended to write. Let's take this sample and break it down chunk by chunk to see how Razor parses this document.&lt;/p&gt;&lt;pre class=&quot;brush: csharp&quot;&gt;&amp;lt;ul&amp;gt;&lt;/pre&gt;&lt;p&gt;When Razor starts parsing a document anything goes until we see an &amp;quot;@&amp;quot;. So this line just gets classified as Markup and we move on to the next&lt;/p&gt;&lt;pre class=&quot;brush: csharp&quot;&gt;@foreach(var p in Model.Products) {&lt;/pre&gt;&lt;p&gt;Here's where things get interesting. Now, Razor has found an &amp;quot;@&amp;quot;. The &amp;quot;@&amp;quot; character is the magic character in Razor. One character, not 5 &quot;&amp;lt;%=%&amp;gt;&quot;, and we let the parser figure out the rest. If you skip ahead a bit, you'll notice that there's nothing that indicates the end of the block of code (like the &amp;quot;%&amp;gt;&amp;quot; sequence in ASPX). Rather than having it's own syntax for delimiting code blocks, Razor tries to add as little as possible and just uses the syntax of the underlying language to determine when the code block is finished. In this case, Razor knows that a C# foreach statement is contained within &amp;quot;{&amp;quot; and &amp;quot;}&amp;quot; characters, so when you reach the end of the foreach block, it will go back to markup&lt;/p&gt;&lt;pre class=&quot;brush: csharp&quot;&gt;&amp;lt;li&amp;gt;@p.Name ($@p.Price)&amp;lt;/li&amp;gt;&lt;/pre&gt;&lt;p&gt;Now, things get even more interesting. Didn't I just say we were in Code until the ending of the foreach? This looks a lot like Markup, and we're still inside the foreach! This is another case where Razor is using the syntax of the underlying language to infer your intent. We know that after the &amp;quot;{&amp;quot; C# is expecting some kind of statement. But, instead of a statement, we see an HTML tag &amp;quot;&amp;lt;li&amp;gt;&amp;quot;, so Razor infers that you intended to switch back to Markup. So we've essentially got a stack of 3 contexts: When we started out we were in Markup, then we saw @foreach so we went to Code, now we've see &amp;lt;li&amp;gt; so were back in Markup. At the closing &amp;lt;/li&amp;gt; tag, we know you've finished the inner Markup block, so we go back to the body of the foreach.&lt;/p&gt;&lt;pre class=&quot;brush: csharp&quot;&gt;}&lt;/pre&gt;&lt;p&gt;Then we see the end of the foreach block, so we go back to the top-level Markup context.&lt;/p&gt;&lt;pre class=&quot;brush: csharp&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/pre&gt;&lt;p&gt;And we continue parsing markup until the next &amp;quot;@&amp;quot;, or the end of the file. You may have noticed I skipped over a bit in the middle of the &amp;lt;li&amp;gt; tag. I'll save the details of that for my next post, but the essential logic is the same: &amp;quot;@&amp;quot; starts code, and we use C# syntax to tell us when that code block is finished.&lt;/p&gt;&lt;p&gt;It's great to finally be able to share the result of our hard work with everyone. We've worked really hard to try to create a really clean syntax for mixing code and markup and I know I'd love to hear your feedback. Post in the comments on my blog, send me a tweet at &amp;quot;@anurse&amp;quot; or send me email at &amp;quot;andrew AT andrewnurse DOT net&amp;quot;.&lt;/p&gt;&lt;p&gt;And I know you're all probably eagerly awaiting a chance to try this out. Don't worry, we'll have a public beta soon that you can try out!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>TechEd North America 2010 - Day 1</title>
      <link>http://vibrantcode.com/blog/2010/6/8/teched-north-america-2010-day-1.html</link>
      <pubDate>Tue, 08 Jun 2010 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2010/6/8/teched-north-america-2010--day-1</guid>
      <description>&lt;p&gt;Day 1 marked the official start of TechEd North America. And while everyone else was in the keynote, I was scrambling slightly as I realized that our demo machine was completely empty, just a clean install of Windows 7 and Office 2010. Fortunately, &lt;a href=&quot;http://bradwilson.typepad.com/&quot;&gt;Brad Wilson&lt;/a&gt; came to the rescue, as he had been given a USB key with Visual Studio 2010, our demos and our rotating PowerPoint deck on it. We snapped it in and got started setting up.&lt;/p&gt;  &lt;p&gt;We took advantage of our large-ish screen and internet connection to stream the keynote live, even though it was happening right next door (though given the size of the exhibition hall, right next door is a long way away :)). At the end of the keynote, the great voice in the sky (aka the announcer) told us the expo was open, and in came the swarms of people! Well, kinda. Of course, there were three &quot;foundational sessions&quot; (like mini-keynotes on more specific topics, like Developer Tools, etc.) going on soon after the keynote, and many people had sessions to attend, so it was pretty quiet in that first shift.&lt;/p&gt;  &lt;p&gt;At 12:30, when my shift ended, Brad and I and a couple of people he knew from Patterns &amp;amp; Practices wandered over to the Meal Hall (Which is no small feat... the New Orleans Convention Center is 1.5 miles long! Granted, we're only using 1 mile of it :)). There we ate &quot;food&quot; (convention food is a close approximation of food in most cases... it was edible and likely had some nutrients in it... close enough) and then I trekked off to my first (and only) session of the day. Don't get too excited, I wasn't speaking, just attending. No talks for me this time around, but I do plan to get into speaking soon. Also, it is notoriously difficult to get speaking slots at TechEd if you haven't given a TechEd talk before.&lt;/p&gt;  &lt;p&gt;I attended a talk on Windows Phone 7, which included a pretty good demo. Aside from the demo it was mostly things I knew about already. By the way, all the talks are going to be posted for FREE viewing by the general public on TechEd Online (&lt;a title=&quot;http://www.msteched.com/&quot; href=&quot;http://www.msteched.com/&quot;&gt;http://www.msteched.com/&lt;/a&gt;), this talk was &quot;WPH201 - Windows Phone 7: A New Kind of Phone&quot;?. It was only slightly ironic that every once and a while, during the talk, I popped open my iPhone to check the latest news from WWDC :). Still, WP7 looks nice, and I'm basically decided that my next phone will likely not be an Apple phone. It may be a Windows Phone or an Android Phone, but even after the iPhone 4 announcement, I'm not really convinced... yet. I'll save that rant for later though :).&lt;/p&gt;  &lt;p&gt;That evening, the exhibition hall was open for a reception at which free food and beverages (read: alcohol) was offered to all attendees, while they wandered around the various booths from Microsoft and third-party Vendors. It was basically all-hands-on-deck for that event, and we were definitely pretty busy. A number of great questions from customers of all knowledge levels, from someone who was just getting back in to Web Development and had no idea what had been going on in ASP.Net, to some folks who used MVC and wanted to know about MVC 2.&lt;/p&gt;  &lt;p&gt;After that, I basically just wandered back to my hotel and crashed. It was a long day, and I had another one ahead of me!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>TechEd North America 2010 - Days 1 and 0</title>
      <link>http://vibrantcode.com/blog/2010/6/7/teched-north-america-2010-days-1-and-0.html</link>
      <pubDate>Mon, 07 Jun 2010 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2010/6/7/teched-north-america-2010--days-1-and-0</guid>
      <description>&lt;p&gt;I know, it's been many many months since I blogged. I wish I could say it was because I was really busy, still getting settled in Seattle, or because I was working on lots of cool stuff I can't talk about yet. While those are all true (*wink*), the real reason is that I just got a bit lazy with the blogging. Anyway, whirlwind update: I've been working on the ASP.Net team full-time for 8 months now, and I'm working on some cool stuff that I'll be able to talk more about soon.&lt;/p&gt;  &lt;p&gt;In the mean time, I can talk about the fact that I'm down in New Orleans right now, working as Staff for the ASP.Net booth at &lt;a href=&quot;http://northamerica.msteched.com/&quot;&gt;TechEd North America&lt;/a&gt;! I'm going to try to blog a bit about the conference, starting with my first three days.&lt;/p&gt;  &lt;p&gt;I left on Saturday, two days before the conference actually started (hence &quot;Day -1&quot;?). After my wonderful girlfriend woke up early to drive me to SeaTac airport at 5am for my 7am flight, I was on my way to New Orleans via Houston. The landing in New Orleans was definitely the roughest landing I've ever been in (second roughest: major cross-winds in a Dash-8 on final approach into Ottawa airport). Upon walking off the plane, I felt like I had just walked into a vat of pea soup. Having never really travelled to this part of the continent before, I was unfamiliar with the intense humidly (though I had been well warned).&lt;/p&gt;  &lt;p&gt;After a short taxi ride, I reached my hotel, The Hotel New Orleans, conveniently located right next to the Convention Center (thus limiting my time in the un-air-conditioned air). It's a nice hotel, with a cool inner atrium design:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0314.jpg&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;IMG_0314&quot; border=&quot;0&quot; alt=&quot;IMG_0314&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0314_thumb.jpg&quot; width=&quot;244&quot; height=&quot;184&quot; /&gt;&lt;/a&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0310.jpg&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;IMG_0310&quot; border=&quot;0&quot; alt=&quot;IMG_0310&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0310_thumb.jpg&quot; width=&quot;244&quot; height=&quot;184&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0311.jpg&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;IMG_0311&quot; border=&quot;0&quot; alt=&quot;IMG_0311&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0311_thumb.jpg&quot; width=&quot;244&quot; height=&quot;184&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;After checking-in, I wandered over to Canal St. and the outskirts of the French Quarter&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0308.jpg&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;IMG_0308&quot; border=&quot;0&quot; alt=&quot;IMG_0308&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0308_thumb.jpg&quot; width=&quot;184&quot; height=&quot;244&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I made my way back to my hotel and decided to eat in the hotel restaurant. I had been given a list of a few things to try while I was here, one of which was Catfish, so I decided to give it a go. After eating that and washing it down with a glass of Sweet Tea (which is a very descriptive name, and a very tasty drink) I basically just crashed early.&lt;/p&gt;  &lt;p&gt;The next day, Sunday, was also pretty relaxed. After a long sleep-in, I wandered over to the Convention Center to register&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0321.jpg&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;IMG_0321&quot; border=&quot;0&quot; alt=&quot;IMG_0321&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0321_thumb.jpg&quot; width=&quot;184&quot; height=&quot;244&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;My only commitment was the staff orientation at 3pm, where we got to check out our booth, located in the Technical Learning Center, which is basically where all the Microsoft teams set up booths. &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0315.jpg&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;IMG_0315&quot; border=&quot;0&quot; alt=&quot;IMG_0315&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0315_thumb.jpg&quot; width=&quot;244&quot; height=&quot;184&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0316.jpg&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;IMG_0316&quot; border=&quot;0&quot; alt=&quot;IMG_0316&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0316_thumb.jpg&quot; width=&quot;244&quot; height=&quot;184&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0317.jpg&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;IMG_0317&quot; border=&quot;0&quot; alt=&quot;IMG_0317&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0317_thumb.jpg&quot; width=&quot;244&quot; height=&quot;184&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Past TechEd attendees may remember that in previous events, this was a separate section from the Partner Expo (where all the third-party vendors set up). In 2010, the TLC and the Partner Expo are all in one big Exhibition Hall. After sizing up our booth and meeting the team, I wandered to a nearby restaurant for a Shrimp Po'boy and Hush Puppies (yet more things on my list of foods to try). I also wandered along the New Orleans Riverwalk and snapped a few pics of the Mississippi (which almost form a panorama!)&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0319.jpg&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;IMG_0319&quot; border=&quot;0&quot; alt=&quot;IMG_0319&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0319_thumb.jpg&quot; width=&quot;244&quot; height=&quot;184&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0320.jpg&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;IMG_0320&quot; border=&quot;0&quot; alt=&quot;IMG_0320&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0320_thumb.jpg&quot; width=&quot;244&quot; height=&quot;184&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0318.jpg&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;IMG_0318&quot; border=&quot;0&quot; alt=&quot;IMG_0318&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TechEdNorthAmerica2010Days1and0_EF33/IMG_0318_thumb.jpg&quot; width=&quot;244&quot; height=&quot;184&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Then, I crashed again, this time setting an alarm so I could be up in plenty of time for my duties the next day.&lt;/p&gt;  &lt;p&gt;Next up: Day 1 - The first actual day of the conference!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>A quick update on MaVeriCk</title>
      <link>http://vibrantcode.com/blog/2009/5/28/a-quick-update-on-maverick.html</link>
      <pubDate>Thu, 28 May 2009 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/5/28/a-quick-update-on-maverick</guid>
      <description>I've been busy with some, paid (and therefore higher priority ;) ), work for the past week or so, which has meant I haven't had time to write up my Module Development in Maverick blog post.&amp;nbsp; I'll try to get that out next week.&amp;nbsp; In the mean time, you can pretty much just take the source (available here: http://github.com/anurse/Maverick) and start playing.&amp;nbsp; Creating a new module is as simple as copying one of the existing folders in the &quot;Source/Web/Maverick.Web/Modules&quot; folder, renaming it, and editing the &quot;Module Application&quot; class inside.&amp;nbsp; There's no registration necessary (thanks to &lt;a href=&quot;http://mef.codeplex.com&quot;&gt;MEF&lt;/a&gt;).&lt;br&gt;&lt;br&gt;Have fun, feel free to post questions, and I'll talk to you next week!&lt;br&gt;&lt;p&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>MaVeriCk - An Open-Source CMS written in ASP.Net MVC</title>
      <link>http://vibrantcode.com/blog/2009/5/19/maverick-an-open-source-cms-written-in-aspnet-mvc.html</link>
      <pubDate>Tue, 19 May 2009 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/5/19/maverick--an-opensource-cms-written-in-aspnet-mvc</guid>
      <description>&lt;p&gt;This is a big post, I know, but I think it'll be worth it. If you don't have time to read it all, I organized it by importance, so the important stuff is at the top anyway :).&lt;/p&gt;  &lt;p&gt;I've been hinting for a while that I've been working on a secret side project using ASP.Net MVC that was sort-of related to DotNetNuke. Well, it's finally time for me to put some code out there :). Today, I published a source code package containing version 0.1 of MaVeriCk, a Content Management System written in ASP.Net MVC. I'll explain what it is and how to get started in this blog post.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Warning&lt;/u&gt;&lt;/strong&gt;: MaVeriCk is &lt;strong&gt;nowhere near finished&lt;/strong&gt;, and very much an &lt;strong&gt;&lt;u&gt;&lt;em&gt;alpha&lt;/em&gt;&lt;/u&gt;&lt;/strong&gt; (maybe even a pre-alpha ;). Major features are completely missing (such as user management, and any useful modules, see below for details)&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;u&gt;Disclaimer&lt;/u&gt;&lt;/strong&gt;: This project has &lt;strong&gt;NO RELATION&lt;/strong&gt; to the DotNetNuke project. While I am a DNN Core Team member, this is purely a personal side-project. DotNetNuke has inspired some of the things I've done in MaVeriCk, but that's the extent of the connection between the two.&lt;/p&gt;  &lt;h3&gt;What is MaVeriCk?&lt;/h3&gt;  &lt;p&gt;Maverick is an open-source Content Management System in the style of *Nuke applications such as &lt;a href=&quot;http://www.dotnetnuke.com&quot;&gt;DotNetNuke&lt;/a&gt;. For the rest of this post, I'm going to assume you're fairly familiar with that style of application. Basically, users create pages and drop little widgets (or &quot;Modules&quot;?) onto those pages to provide features like a Blog, Message Board, or even just a block of HTML.&lt;/p&gt;  &lt;h3&gt;Where (and how) do I get it?&lt;/h3&gt;  &lt;p&gt;The project is hosted on GitHub (&lt;a title=&quot;http://github.com/anurse/MaVeriCk/&quot; href=&quot;http://github.com/anurse/MaVeriCk/&quot;&gt;http://github.com/anurse/MaVeriCk/&lt;/a&gt;) so you can feel free to clone the repository and hack away there. Alternatively, if you either don't have Git or don't want to bother with getting the whole repository, you can download version 0.1.0, from the downloads section: &lt;a title=&quot;http://github.com/anurse/MaVeriCk/downloads&quot; href=&quot;http://github.com/anurse/MaVeriCk/downloads&quot;&gt;http://github.com/anurse/MaVeriCk/downloads&lt;/a&gt;. Also on the downloads page are the release notes for this version which include a full installation guide. Unfortunately, there is no automated installation system, but the steps are quite straightforward if you're familiar with ASP.Net.&lt;/p&gt;  &lt;p&gt;Feel free to post comments on this blog, or send me email at: andrew AT andrewnurse DOT net &lt;/p&gt;  &lt;p&gt;(After all, I'm just a junior programmer just out of college and don't purport to be an expert in the various development patterns and architectures, so if you think something doesn't look right, please let me know!)&lt;/p&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;h3&gt;How does it work?&lt;/h3&gt;  &lt;p&gt;The rest of this post will be a, very short, introduction to the Module Framework provided by Maverick. I'll be posting much more detailed information about the guts of Maverick later on, this is just a taste. Feel free to send me email (see above) if you have questions about the rest of the architecture, and don't be afraid to dive into the code!&lt;/p&gt;  &lt;p&gt;Let's start by taking a look at a MaVeriCk page:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/MaVeriCkAnOpenSourceCMSwritteninA.NetMVC_C828/image_2.png&quot;&gt;&lt;img style=&quot;border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/MaVeriCkAnOpenSourceCMSwritteninA.NetMVC_C828/image_thumb.png&quot; width=&quot;621&quot; height=&quot;323&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here, we see a page with two modules. The first module is an instance of the &quot;Current Time&quot; Module Application, the second is an instance of the &quot;Claim Dumper&quot; Module Application. A Module Application is an MVC Application, with its own Controllers and Views, which handles requests for a particular type of module. If you're familiar with DNN, the &quot;Module Application&quot; is analogous to the &quot;Module Definition&quot; concept in DNN.&lt;/p&gt;  &lt;p&gt;Here's a look at the code for the Current Time Module Application:&lt;/p&gt;  &lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;[Export(typeof(ModuleApplication))]&lt;br/&gt;[ModuleApplication(ApplicationId, ApplicationName, &amp;quot;1.0.0.0&amp;quot;, &amp;quot;Displays the Current Time&amp;quot;, &amp;quot;Maverick&amp;quot;, &amp;quot;~/Modules/CurrentTime/Content/Images/Icon.png&amp;quot;)]&lt;br/&gt;public class CurrentTimeModuleApplication : ModuleApplication {&lt;br/&gt;    private const string ApplicationId = &amp;quot;A1FE2A31-0BC9-4B12-9B81-3B75C098EB33&amp;quot;;&lt;br/&gt;    private const string ApplicationName = &amp;quot;Current Time&amp;quot;;&lt;br/&gt;    protected override string FolderPath {&lt;br/&gt;        get { return &amp;quot;CurrentTime&amp;quot;; }&lt;br/&gt;    }&lt;br/&gt;    protected internal override void Init(MaverickApplication application) {&lt;br/&gt;        base.Init(application);&lt;br/&gt;        RegisterRoutes(Routes);&lt;br/&gt;    }&lt;br/&gt;    private static void RegisterRoutes(RouteCollection routes) {&lt;br/&gt;        routes.RegisterDefaultRoute(&amp;quot;Maverick.Web.Modules.CurrentTime.Controllers&amp;quot;);&lt;br/&gt;    }&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Compare this with the Global.asax file with an MVC app, and you'll find it's very similar. The &quot;Init&quot; method is equivalent to &quot;Application_Start&quot; and is called the first time the Module Application is run during the current ASP.Net Application's lifetime. Just as you would in an MVC 'Application_Start' method, the Current Time Application registers routes into a route table for this module application. In this case, the module is using a helper that Maverick provides to register the default route, but if we take a look at that helper, the only difference between the standard MVC route and this route is that we require that the namespace containing the Controllers is specified:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;public static void RegisterDefaultRoute(this RouteCollection routes, string routeName, string defaultController, string defaultAction, string defaultId, string[] namespaces) {&lt;br/&gt;    routes.MapRoute(&lt;br/&gt;        routeName,&lt;br/&gt;        &amp;quot;{controller}/{action}/{id}&amp;quot;,&lt;br/&gt;        new {controller = defaultController, action = defaultAction, id = defaultId},&lt;br/&gt;        namespaces&lt;br/&gt;        );&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;(&lt;strong&gt;Note&lt;/strong&gt;: there are various overrides to this method, including the one you see used by the CurrentTimeModuleApplication class above)&lt;/p&gt;&lt;p&gt;Routing in Maverick is a little more complex than in standard MVC applications. I'll go into more details on it later, but the gist of it is that a portion of the URL for a request is handled by Maverick, and the rest (if any) goes to one of the modules on the page (called the &quot;Active&quot; or &quot;Selected&quot; module). All the other modules (referred to as &quot;Passive&quot; modules) get an empty URL, and their default route is run.&lt;/p&gt;&lt;p&gt;From there on, a module is surprisingly similar to an MVC application. It has Controllers and Views, just like an MVC app. The big difference is that, in most cases, the ActionResult returned by a Controller does not represent the whole page, just a fragment of it. Maverick collects all the ActionResults for a page and then renders them out one-by-one in the correct location. Of course there are exceptions (for example, if a Module returns a FileResult or a RedirectResult), but that's the core of it.&lt;/p&gt;&lt;h3&gt;&lt;/h3&gt;&lt;br/&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;Missing Features&lt;/h3&gt;&lt;br/&gt;&lt;p&gt;Maverick is in an early preview state at the moment. There is a powerful authentication model available (or &quot;Identity&quot; model, as I call it), but at the moment, there's only a very simple &quot;Debug&quot; implementation of it (which just automatically logs you in as an Administrator). I have a prototype system which uses the Azure Access Control Service in the code, but it is not active by default (I'll post more about that later).&lt;/p&gt;&lt;p&gt;Maverick does not really include any useful modules, so you're on your own there. Module development is relatively simple, and will be the focus of another blog post. Feel free to check out the other modules for more info. The only major component of Module Development not covered in the provided sample modules is data storage. Maverick does have a system for modules to store data in the Maverick Database, but none of the built in modules do that.&lt;/p&gt;&lt;p&gt;There is a very rudimentary Theming system in place to allow you to create your own templates for the site (similar to DNN Skins).&lt;/p&gt;&lt;p&gt;Despite being touted as a Content Management System, Maverick doesn't actually contain any Content Management features :), no Workflow, no Versioning, no Content Approval. However, those features are planned for the future.&lt;/p&gt;&lt;p&gt;If you have any other suggestions, please let me know!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>DotNetNuke Reports Module 5.1 enters the Release Tracker</title>
      <link>http://vibrantcode.com/blog/2009/5/2/dotnetnuke-reports-module-51-enters-the-release-tracker.html</link>
      <pubDate>Sat, 02 May 2009 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/5/2/dotnetnuke-reports-module-51-enters-the-release-tracker</guid>
      <description>&lt;p&gt;It took almost a week longer than I said it would, but it's finally done. Version 5.1 of the DotNetNuke Reports Module is in the DotNetNuke Project Release Tracker. I'll post some more info over the next week, but for now, here are the release notes:&lt;/p&gt;  &lt;h3&gt;Reports Module 5.1 for DotNetNuke 5.0.1&lt;/h3&gt;  &lt;p&gt;Required DotNetNuke Version: 5.0.1 or above&lt;/p&gt;  &lt;p&gt;The following issues have been resolved in this release of the Reports Module&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href=&quot;http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=9801&amp;amp;PROJID=36&quot;&gt;RPT-9810: Simple URL Parameter system&lt;/a&gt; - A simple URL parameter system has been added which allows users to provide a list of QueryString parameters which will be added to the query. The parameter names are in the following format: @url_[QueryString Parameter Name]. Only the parameters specified in the &amp;quot;Allowed URL Parameters&amp;quot; section will be added. &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=5953&amp;amp;PROJID=36&quot;&gt;RPT-5953: XSLT Extension Objects&lt;/a&gt; - CLR objects can now be provided to the XSLT Visualizer to use as XSLT Extension Objects. These objects must have a parameter-less constructor and MAY (but are not required to) implement the IXsltExtensionObject interface (found in DotNetNuke.Modules.Reports.dll) in order to receive additional context information. &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=7025&amp;amp;PROJID=36&quot;&gt;RPT-7025: Search Indexing fails due to an exception&lt;/a&gt; - When there is an error in a Data Source, that exception is also thrown by the Search Indexer. Since Reports Module Exceptions were localized, through the Message property, when the Scheduler caught the exception thrown by the module, it would attempt to localize the text and fail (since there is no HttpContext). This has been corrected so that Data Source errors are no longer masked. &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=9543&amp;amp;PROJID=36&quot;&gt;RPT-9543: Exception thrown when opening &amp;quot;Manage Add-Ins&amp;quot; page on DNN 5.0&lt;/a&gt; - The DotNetNuke Extensions Installer API was moved to a different namespace in 5.0. The Reports module has been updated to reflect this change. &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=8145&amp;amp;PROJID=36&quot;&gt;RPT-8145: Reports Module does not release file handle&lt;/a&gt; - The HTML Visualizer was opening a StreamReader and using ReadToEnd to load the contents, but not closing the StreamReader. It has been corrected to use System.IO.File.ReadAllText. A similar issue in the XSLT Visualizer was discovered and resolved the same way &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=7237&amp;amp;PROJID=36&quot;&gt;RPT-7237: Show Info Pane working incorrectly&lt;/a&gt; - The &amp;quot;Show Info Pane&amp;quot;, &amp;quot;Show Controls&amp;quot;, and &amp;quot;Auto Run Report&amp;quot; settings were not being updated if the user is not a Super User, despite the fact that these settings are visible to non-Super Users. This has been corrected in the 5.1 release. &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=7236&amp;amp;PROJID=36&quot;&gt;RPT-7236: Critical error when no file name entered for HTML Template Visualizer setting&lt;/a&gt; - The HTML Visualizer allowed users to leave the Template file field empty, causing a Critical Error on the view page. The view page has been corrected to avoid causing this error. A similar issue with the XSLT Visualizer has also been corrected &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=7238&amp;amp;PROJID=36&quot;&gt;RPT-7238: Show Header field cannot be unchecked&lt;/a&gt; - A bug prevented the ShowHeader option from being deselected in the Grid Visualizer. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Also included is an update for the UDT Data Source for the Reports Module, here are the release notes:&lt;/p&gt;  &lt;h3&gt;Forms and Lists Data Source for DotNetNuke Reports 1.1.0 - Release Notes&lt;/h3&gt; This is a minor update to the User Defined Table Data Source for the DotNetNuke Reports Module. It has been renamed to the Forms and List Data Source, to match the new project name. Only one minor change is included: The stored procedure used to retrieve the list of Forms and List modules has been removed and replaced with (safe) dynamic SQL to reduce installation overhead. &lt;strong&gt;Requires DotNetNuke Reports 5.0 or above.&lt;/strong&gt;   &lt;p&gt;Track the progress of the module through the DotNetNuke Release process here: &lt;a title=&quot;http://www.dotnetnuke.com/Development/ReleaseManagement/ProjectReleaseTracking/tabid/997/ctl/History/mid/3337/ItemID/394/Default.aspx&quot; href=&quot;http://www.dotnetnuke.com/Development/ReleaseManagement/ProjectReleaseTracking/tabid/997/ctl/History/mid/3337/ItemID/394/Default.aspx&quot;&gt;http://www.dotnetnuke.com/Development/ReleaseManagement/ProjectReleaseTracking/tabid/997/ctl/History/mid/3337/ItemID/394/Default.aspx&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>School is done!  On to Reports, and something else ;)</title>
      <link>http://vibrantcode.com/blog/2009/4/21/school-is-done-on-to-reports-and-something-else.html</link>
      <pubDate>Tue, 21 Apr 2009 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/4/21/school-is-done--on-to-reports-and-something-else-</guid>
      <description>Well, it's official.&amp;nbsp; Assuming I pass the two courses I haven't received grades from, I completed my final day of continuous education (well, except for the summer breaks/internships) for 18 straight years (K-12 + 5 years of post-secondary) today.&amp;nbsp; I've already got marks for 3 of the 5 courses I took this year, and they were pretty good (couple of A's and a B).&amp;nbsp; This semester has been a bit of a strange one, since I had only one computing science course and it was a &quot;Writing for Computer Scientists&quot; course which involved no programming! (Despite that, it was one of my favorite courses this semester :D).&amp;nbsp; I took introductory courses in Communications, Linguistics and Nutrition as well as a intro to the Physics of Sound and Music entitled &quot;Logarithm and Blues&quot; taught by a two-man team of a musician and a physicist (sorry &quot;Writing for Computing Scientists&quot;, this one takes the top slot this semester :)).&lt;br&gt;&lt;br&gt;Now that I'm finished school, probably for a while (still eying a part-time masters at University of Washington when I've been at Microsoft for a while), I can settle down and finish up a few side-projects and some DNN Reports work.&amp;nbsp; Reports Module version 5.1 is finished from a code perspective and contains a number of bugfixes (details to come) as well as two new features:&lt;br&gt;&lt;ul&gt;&lt;li&gt;XSLT Extension Objects - The XSLT Visualizer now allows you to provide a list of .Net Types which are constructed at runtime and mapped into the XSLT file as XML namespaces.&lt;/li&gt;&lt;li&gt;Experimental and mostly hacky support for QueryString parameters in Report Queries - A number of people have been asking for this, and it's a relatively simple feature in the Reports Module architecture.&amp;nbsp; On the settings page, you can provide a comma-separated list of QueryString parameters which will be passed to the Report Query.&amp;nbsp; The parameters are prefixed with &quot;url_&quot; in the query to distinguish them from the existing parameters.&amp;nbsp; NOTE: Don't forget that many Databases use still another prefix, such as SQL Server (&quot;@&quot;), so for example, the full name of the SQL Server parameter mapped to &quot;foobar&quot; QueryString parameter is &quot;@url_foobar&quot;.&amp;nbsp; This is only a stopgap solution to allow for some linking into Reports with parameters, so expect the next version to include a more detailed system (&lt;b&gt;which &lt;i&gt;&lt;u&gt;may&lt;/u&gt;&lt;/i&gt; include breaking changes which &lt;u&gt;&lt;i&gt;will &lt;/i&gt;&lt;/u&gt;require that you update your queries&lt;/b&gt;). I'll do my best to support an upgrade path, but no promises, so &lt;i&gt;&lt;u&gt;&lt;b&gt;use at your own risk&lt;/b&gt;&lt;/u&gt;&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;I just need to do some testing and then I'll put 5.1 into the release process.&amp;nbsp; I expect to do that this week, so depending on how long it takes the diligent reviewers in the release process to make sure that the new version won't obliterate your existing site (and believe me, you don't want to rush that!), it should be out very soon!&lt;br&gt;&lt;br&gt;Moving on to a new project...&amp;nbsp; I've been hinting to some of the people in the internal project forums at DotNetNuke that I've been working on a top-secret project involving MVC.&amp;nbsp; (This is a pure side-project, not part of the DNN Project at all).&amp;nbsp; I'm very close to releasing something which, I think, is pretty cool.&amp;nbsp; I'll keep the secret for now, but let's say this: I've been working on/with DotNetNuke for a few years, and I've a huge fan of ASP.Net MVC.&amp;nbsp; I've learned a lot from DNN and I think MVC users can benefit from some of that experience ;).&amp;nbsp; I'm &lt;i&gt;hoping&lt;/i&gt; to have something ready on this secret project, which I call &quot;MaVeriCk&quot;, in the next week or two (but Reports 5.1 is my priority at the moment).&lt;br&gt;&lt;br&gt;Hope that teased you just enough to stay tuned :P&lt;br&gt;&lt;p&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>I'm still here! Just cramming... and working</title>
      <link>http://vibrantcode.com/blog/2009/4/10/im-still-here-just-cramming-and-working.html</link>
      <pubDate>Fri, 10 Apr 2009 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/4/10/im-still-here-just-cramming-and-working</guid>
      <description>&lt;p&gt;Hello avid readers! It's been over a week since I blogged, I know, but I've been cramming for exams. The CMPT 376 assignment I mentioned a while ago has finished, so I'm no longer required to blog for grades. Having said that, after exams, I plan to keep blogging, so keep watching the feed :).&lt;/p&gt;  &lt;p&gt;Just to tease you a bit: I've got a cool little ASP.Net MVC side-project well underway that I'm just dying to show off on the blog, so stick around :P&lt;/p&gt;  &lt;p&gt;Also, to the Reports Module users out there, 5.1 is very close to being finished. There may be a surprise new feature in there too. Details to follow later :D.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Quantum Computing in .Net "Looflirpa"</title>
      <link>http://vibrantcode.com/blog/2009/4/1/quantum-computing-in-net-looflirpa.html</link>
      <pubDate>Wed, 01 Apr 2009 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/4/1/quantum-computing-in-net-looflirpa</guid>
      <description>&lt;p&gt;Microsoft is really taking major strides in terms of improving the programming experience for developers on all current and &lt;strong&gt;future&lt;/strong&gt; computing platforms. That's why, earlier today, Microsoft released a beta of the new &quot;System.QuantumEntanglement&quot; library. This library, being considered for integration with .Net 4.1 (which, my sources say, is codenamed &quot;Looflirpa&quot;?), provides features for developers working on quantum computers. I won't go in to too much detail, but this essentially means working in an environment where objects can be in many different states (possibly an infinite number) and where observation may change the state of an object. Microsoft has proposed a few options, but I have some additional ideas.&lt;/p&gt;  &lt;h3&gt;Microsoft's Proposal&lt;/h3&gt;  &lt;p&gt;&lt;a href=&quot;http://weblogs.asp.net/leftslipper/&quot; target=&quot;_blank&quot;&gt;Eilon Lipton&lt;/a&gt;, of the ASP.Net MVC team, &lt;a href=&quot;http://weblogs.asp.net/leftslipper/archive/2009/04/01/the-string-or-the-cat-a-new-net-framework-library.aspx&quot; target=&quot;_blank&quot;&gt;is proposing a number of new additions to the .Net BCL in 4.1&lt;/a&gt;. The first, is a class called &quot;StringOr&amp;lt;T&amp;gt;&quot; which has the following API:&lt;/p&gt;  &lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;namespace System.QuantumEntanglement {&lt;br/&gt;    public class StringOr&amp;lt;TOther&amp;gt; {&lt;br/&gt;        public StringOr(string stringValue, TOther otherValue);&lt;br/&gt;        public string StringValue { get; }&lt;br/&gt;        public TOther OtherValue { get; }&lt;br/&gt;    }&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;This class is used to encapsulate a value which may be a string, but may be another value. This is a common user-input scenario, since almost all user input arrives as strings, but will usually be converted to another data type. He also proposes a more general class called &quot;SchrodingOr&amp;lt;TDead, TAlive&amp;gt;&quot;?&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;namespace System.QuantumEntanglement {&lt;br/&gt;    public class SchrodingOr&amp;lt;TDead, TAlive&amp;gt; {&lt;br/&gt;        public SchrodingOr(TDead dead, TAlive alive);&lt;br/&gt;        public TAlive Alive { get; }&lt;br/&gt;        public TDead Dead { get; }&lt;br/&gt;    }&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;This generalizes StringOr&amp;lt;T&amp;gt; to support any two types. &lt;/p&gt;&lt;p&gt;Eilon's not the only one talking about this, &lt;a href=&quot;http://www.hanselman.com/blog/NET41PreviewNewBaseClassLibraryBCLExtensionMethodsRFC.aspx&quot; target=&quot;_blank&quot;&gt;Scott Hanselman&lt;/a&gt; (well known Microsoft blogger), and &lt;a href=&quot;http://blog.wekeroad.com/blog/cool-extension-methods-for-new-stringor/&quot; target=&quot;_blank&quot;&gt;Rob Conery&lt;/a&gt; (Author of the .Net Object-Relational Mapper: SubSonic) have also posted on this topic. So I figured I'd add my comments to the blogosphere.&lt;/p&gt;&lt;p&gt;StringOr and SchrodingOr are great starts, but what if we need to represent objects which may be in 2 states? What about 3 states? Infinite states? That's where my proposals come in. I propose the following additions to Eilon's library:&lt;/p&gt;&lt;h3&gt;Generalizing SchrodingOr&lt;/h3&gt;&lt;p&gt;The first is SchrodingOr&amp;lt;T1, T2, T3, T4, T5, ... , T&lt;em&gt;n&lt;/em&gt;&amp;gt; (for infinite &lt;em&gt;n&lt;/em&gt;). This allows the developer to represent objects in as many states as they want. &lt;/p&gt;&lt;h3&gt;C# 5.0 Compiler Support&lt;/h3&gt;&lt;p&gt;I'm also proposing the following language syntax to help developers work with these types. Similar to the way the C# compiler converts &quot;int?&quot; to &quot;Nullable&amp;lt;int&amp;gt;&quot; (which would now be replaced with &quot;SchrodingOr&amp;lt;int, Void&amp;gt;&quot; as it more accurately represents the concept of a type which may or may not have a value), the new syntax takes the following:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;int?string?bool?DateTime? foo = GetUserInput(...);&lt;/pre&gt;&lt;p&gt;And produces output code which looks like this:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;SchrodingOr&amp;lt;int, DateTime, bool, string&amp;gt; foo = GetUserInput(...);&lt;/pre&gt;&lt;p&gt;Then, we can defer observation until a later time, using the AsA&amp;lt;T&amp;gt;/AsAn&amp;lt;T&amp;gt; method (since Eilon's Alive and Dead properties no longer work in an infinite state environment). If we just want to observe the type and then make a decision, we can use IsA&amp;lt;T&amp;gt;/IsAn&amp;lt;T&amp;gt; methods (of course, both are required, just in case the type starts with a vowel), which returns a boolean indicating if the object is of the type &lt;em&gt;T&lt;/em&gt;. For example:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;if(foo.IsA&amp;lt;string&amp;gt;()) { return foo.AsA&amp;lt;string;&amp;gt;; }&lt;/pre&gt;&lt;h3&gt;Probabilistic Observation&lt;/h3&gt;&lt;p&gt;Sometimes, we may want to observe an object only if there is a high probability of it being in the right state, to avoid additional quantum variations. To do this, we can use the CouldBeA&amp;lt;T&amp;gt;/CouldBeA&amp;lt;T&amp;gt; methods. These can, optionally, accept a probability threshold beyond which a object is considered in the right state.&lt;/p&gt;&lt;h3&gt;Quantum Snapshots&lt;/h3&gt;&lt;p&gt;Unfortunately, in between a call to IsA/An/CouldBeA/An and AsA/An, the state of the object may change. So, we may wish to observe an object and record the state of the object at the time of observation. Since in observing the object we may change its state, our observations must be recorded in &quot;Snapshots&quot;?. The snapshot is an instance of QuantumSnapshotOf&amp;lt;TSchrodingOr&amp;gt; (where &lt;em&gt;TSchrodingOr&lt;/em&gt; must be one of the SchrodingOr&amp;lt;T1, ..., T&lt;em&gt;n&lt;/em&gt;&amp;gt; types), and has a property &amp;quot;Taken&amp;quot;, which is a DateTimeOffset (after all, we need precise timing here) containing the exact time that the snapshot was taken. &lt;/p&gt;&lt;p&gt;Here's an example combining Probabilistic Observation and Snapshots:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;if(foo.CouldBeA&amp;lt;string&amp;gt;()) {&lt;br/&gt;	QuantumSnapshotOf&amp;lt;SchrodingOr&amp;lt;int, string&amp;gt;&amp;gt; snapshot = foo.Observe();&lt;br/&gt;	if(snapshot.Taken.Day == 1 &amp;amp;&amp;amp; snapshot.Taken.Month == 4) {&lt;br/&gt;		throw new UnreliableObservationException(snapshot, &amp;quot;The data is unreliable&amp;quot;);&lt;br/&gt;	}&lt;br/&gt;	return snapshot.AsA&amp;lt;string&amp;gt;();&lt;br/&gt;}&lt;/pre&gt;&lt;h3&gt;Summary&lt;/h3&gt;&lt;p&gt;I think this is really interesting, forward-thinking, stuff from Microsoft. Eilon has done some fantastic work getting the ball rolling, and its up to us to give our feedback! Microsoft has created a section on MSDN for discussion on these new features: &lt;a href=&quot;http://en.wikipedia.org/wiki/April_Fool%27s_Day&quot; target=&quot;_blank&quot;&gt;http://msdn.microsoft.com/en-US/QuantumEntanglement/Default.aspx&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>DotNetNuke on IgniteIT</title>
      <link>http://vibrantcode.com/blog/2009/3/30/dotnetnuke-on-igniteit.html</link>
      <pubDate>Mon, 30 Mar 2009 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/3/30/dotnetnuke-on-igniteit</guid>
      <description>&lt;p&gt;Did you know that the largest open-source project on the Microsoft platform was started in Vancouver, Canada? It's true! DotNetNuke is the largest Open-Source community in the .Net by downloads (at least). Since moving to CodePlex (Microsoft's Open-Source hosting platform) in January 2009, DNN has been downloaded over 180,000 times (at time of writing). This makes it second only to a World Of Warcraft Add-On development studio which has been on CodePlex since Sept 2007 (at least that was the earliest check-in I could find). Adding that to the all-time download score on SourceForge (the project's previous host) of &lt;strong&gt;4.3 Million downloads&lt;/strong&gt;, and you've got the the largest .Net open-source project (and one which I am proud to &lt;a href=&quot;http://www.dotnetnuke.com/Products/Development/Forge/ModuleReports/tabid/970/Default.aspx&quot; target=&quot;_blank&quot;&gt;contribute to&lt;/a&gt;)!&lt;/p&gt;  &lt;p&gt;And here's the great part for us Canucks, DotNetNuke was created right here (by &quot;here&quot;?, I mean where I live :P) in Vancouver!&lt;/p&gt;  &lt;p&gt;Microsoft Canada is running a contest called the &quot;Ignite It&quot; award to honour Canadian developers and IT professionals. DotNetNuke is nominated in the Developer category, and we're looking for your votes! There's only 2 days left, and we're in the top 5 (which will go on to be judged). Still, we'd like to be up at number one before voting ends, so here comes the shameless plug :P. Here's the deal: You can vote once per Windows Live account per day (though there aren't many days left :( ). It only takes a second to vote, and I've even created a TinyURL to share with your friends: &lt;a href=&quot;http://tinyurl.com/dnnigniteit&quot;&gt;http://tinyurl.com/dnnigniteit&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Let's push DNN into the top spot!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Windows Live Writer - After 2 Months</title>
      <link>http://vibrantcode.com/blog/2009/3/27/windows-live-writer-after-2-months.html</link>
      <pubDate>Fri, 27 Mar 2009 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/3/27/windows-live-writer--after-2-months</guid>
      <description>&lt;p&gt;Back in January, I started &lt;a href=&quot;/2009/01/08/WritingABlogForFunAndProfithellipIMeanGrades.aspx&quot; target=&quot;_blank&quot;&gt;blogging more frequently due to a course I was taking&lt;/a&gt;. As part of that, I started using Windows Live Writer to write all my blog posts. I use the &lt;a href=&quot;http://www.dasblog.info/&quot; target=&quot;_blank&quot;&gt;DasBlog&lt;/a&gt; engine to power my blog, and it supports one of the many blogging APIs that Windows Live Writer uses (I believe it's MetaWeblog). So, I hooked it up to my blog, and everything just worked!&lt;/p&gt;  &lt;p&gt;My favorite feature is the ability to create and save drafts and then publish them on demand. I have inspiration at the strangest times, and often in large batches, so I end up with a couple ideas of things to blog in a day, and no ideas the next day. So, I just create a bunch of drafts, get them ready to publish and then publish them over a longer period of time (like say... a day :P). For example, I wrote this post 5 minutes after the previous post, but I thought it might overload my readers to post it immediately :). So, I save a draft and post it a bit later (when I don't have anything to blog about :D).&lt;/p&gt;  &lt;p&gt;If you have a blog, and it supports one of the blogging APIs, and you're running on Windows, you really should try Windows Live Writer!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Virtually "Attending"?? MIX09</title>
      <link>http://vibrantcode.com/blog/2009/3/24/virtually-attending-mix09.html</link>
      <pubDate>Tue, 24 Mar 2009 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/3/24/virtually-attending-mix09</guid>
      <description>&lt;p&gt;Microsoft's MIX Web Development conference was held in Las Vegas last week and while I would have loved to go, the cost and scheduling just made it impossible :(. Despite that, I've been spending the past few days &quot;attending&quot; MIX virtually! Microsoft posts high quality WMV versions of the talks on the &lt;a href=&quot;https://content.visitmix.com/2009/Sessions/&quot; target=&quot;_blank&quot;&gt;MIX website&lt;/a&gt;, perfect for catching up on the sessions. With my Media Center PC hooked up through my Xbox 360, I can browse through my rapidly growing collection of talks and watch them at my leisure. It's almost like being there! A couple of my recommendations are below:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href=&quot;http://videos.visitmix.com/MIX09/KEY01&quot; target=&quot;_blank&quot;&gt;Day One Keynote&lt;/a&gt; - I haven't had a chance to watch this yet, but it already has two things going for it. Bill Buxton talking about User Experiences and a live &lt;a href=&quot;http://www.dotnetnuke.com/&quot; target=&quot;_blank&quot;&gt;DotNetNuke&lt;/a&gt; installation using the &lt;a href=&quot;http://www.microsoft.com/web&quot; target=&quot;_blank&quot;&gt;Microsoft Web Platform Installer 2.0 Beta&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://videos.visitmix.com/MIX09/T50F&quot; target=&quot;_blank&quot;&gt;ASP.Net MVC: America's Next Top Model View Controller Framework&lt;/a&gt; - I love ASP.Net MVC, and this is a great intro. Of course, I may be biased since I worked on the team last summer. BTW, version 1.0 was released last Wednesday, and a large chunk of the AJAX stuff is my code (my code is actually in a released Microsoft product! w00t!) &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://videos.visitmix.com/MIX09/T44F&quot; target=&quot;_blank&quot;&gt;Microsoft ASP.NET Model View Controller (MVC): Ninja on Fire Black Belt Tips&lt;/a&gt; - If the previous talk was MVC 101, this is MVC 201 :P. Though I have to be honest, I haven't actually watched this one yet. I'm sure its chock full of useful MVC tricks though! &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://videos.visitmix.com/MIX09/T49F&quot; target=&quot;_blank&quot;&gt;File|New -&amp;gt; Company: Creating NerdDinner.com with Microsoft ASP.NET Model View Controller (MVC)&lt;/a&gt; - I know, yet another MVC talk, but if you're more of a &quot;get to the code&quot; type of programmer, this may be your style. Plus, Scott Hanselman is an excellent presenter. &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://videos.visitmix.com/MIX09/T79M&quot; target=&quot;_blank&quot;&gt;How'd they do it? Real App. Real Code. Two Weeks. Nothing but .NET&lt;/a&gt; - Another Scott Hanselman talk, this one only 20mins long. You hear people talk about &quot;Rapid Application Development&quot; but in this talk Scott shows off a concrete example of a 2 week project that forms part of the Adidas Motorsports portal. &lt;/li&gt;    &lt;li&gt;&lt;a href=&quot;http://videos.visitmix.com/MIX09/T45F&quot; target=&quot;_blank&quot;&gt;Building Out of Browser Experiences with Microsoft Silverlight 3&lt;/a&gt; - This is another one I haven't actually watched yet but intrigued me. With Silverlight 3, Microsoft is positioning itself to take on both Adobe Flash and AIR. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;That's by no means a complete list of great talks, just my first impressions based on the first few I've watched and the abstracts that interested me on the list. Feel free to post your own favourites in the comments!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Final Few Weeks of School!</title>
      <link>http://vibrantcode.com/blog/2009/3/18/final-few-weeks-of-school.html</link>
      <pubDate>Wed, 18 Mar 2009 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/3/18/final-few-weeks-of-school</guid>
      <description>&lt;p&gt;I was taking a look at a calendar on Monday and realized something... I only have a few more weeks of school left! I don't graduate until June, but classes finish on April 6th. As a result, my workload has been growing exponentially :P, so I'm putting my side-projects on hold. The only exception is my work on version 5.1 of the DotNetNuke Reports Module, which is coming along quickly and should be finished soon.&lt;/p&gt;  &lt;p&gt;I went straight from high-school to university, so its been a non-stop 16 years of school. So, it's going to be a little bit strange when I graduate and actually enter the workforce full-time :). Still, I've got an awesome job to go to, so I'm still pretty excited.&lt;/p&gt;  &lt;p&gt;I have to keep blogging for my CMPT 376 (Writing) course, so I'll keep doing that, but I'm putting pretty much everything else (including &quot;Duh,&quot; my toy programming language) on hold for a couple of weeks. I'll have a bit more time after classes end :).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Are all CS departments this slow to adopt new tech?</title>
      <link>http://vibrantcode.com/blog/2009/3/11/are-all-cs-departments-this-slow-to-adopt-new-tech.html</link>
      <pubDate>Wed, 11 Mar 2009 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/3/11/are-all-cs-departments-this-slow-to-adopt-new-tech</guid>
      <description>&lt;p&gt;Having spent 5 years taking courses in the Computing Science department at Simon Fraser University, I've become pretty familiar with the various web applications used to track course projects, submit assignments, etc. Over the same five years, I've seen numerous technological changes, both in the &quot;outside world&quot; and within the University. For example, not too long ago, SFU switched to a central authentication service aptly named &quot;Central Authentication Service&quot; (or &lt;a href=&quot;http://www.jasig.org/cas&quot; target=&quot;_blank&quot;&gt;CAS&lt;/a&gt;). It's a pretty nice service, with a snazzy login screen (below).&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/AreallCSdepartmentsthisslowtoadoptnewtec_9F8F/image_6.png&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;SFU CAS Login Page&quot; border=&quot;0&quot; alt=&quot;SFU CAS Login Page&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/AreallCSdepartmentsthisslowtoadoptnewtec_9F8F/image_thumb_2.png&quot; width=&quot;644&quot; height=&quot;437&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;It's not only snazzy, but a pretty useful system. I even integrated one of my school projects (an online grade tracking application) with it without any external support. Let's contrast that with the &lt;strong&gt;current&lt;/strong&gt; login screen for &quot;Gradebook&quot;?, an application developed by the CS department and used in most CS courses to track grades&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/AreallCSdepartmentsthisslowtoadoptnewtec_9F8F/image_8.png&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;Gradebook Login Page&quot; border=&quot;0&quot; alt=&quot;Gradebook Login Page&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/AreallCSdepartmentsthisslowtoadoptnewtec_9F8F/image_thumb_3.png&quot; width=&quot;644&quot; height=&quot;297&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Ok, not as snazzy, but here's the really frustrating thing: My account here is NOT the same as my SFU computing account!&lt;/p&gt;  &lt;p&gt;The &quot;Gradebook&quot; system also includes an electronic assignment submission server&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/AreallCSdepartmentsthisslowtoadoptnewtec_9F8F/image_10.png&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;CS Submission Server&quot; border=&quot;0&quot; alt=&quot;CS Submission Server&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/AreallCSdepartmentsthisslowtoadoptnewtec_9F8F/image_thumb_4.png&quot; width=&quot;644&quot; height=&quot;133&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;(BTW: This is only a small snapshot of the page)&lt;/p&gt;  &lt;p&gt;Sure, it isn't snazzy looking, but it's simple and to the point (+10 points). However, it comes with a few caveats: I have to use my &quot;Gradebook&quot; account, not my (so-called) &quot;universal&quot; SFU account (-25 points), and ALL submissions must be in ZIP, GZIP or RAR format (-25 points)! For many of my courses, the electronic submission has been a single file, and the instructor often has to email the students to remind them that they have to wrap their single PDF file (or Word Doc, etc.) in a ZIP file to upload it. I can understand the benefits as far as storage space, and bandwidth consumption, but wouldn't that be better achieved by simply placing a size restriction and allowing any file to be uploaded? Plus, when I do login, I get a page with a drop-down list of courses. Here's the contents:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/AreallCSdepartmentsthisslowtoadoptnewtec_9F8F/image_12.png&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/AreallCSdepartmentsthisslowtoadoptnewtec_9F8F/image_thumb_5.png&quot; width=&quot;90&quot; height=&quot;244&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;See that scrollbar? Yeah... I'm not registered in anywhere near that many courses (the &lt;strong&gt;&lt;em&gt;&lt;u&gt;one&lt;/u&gt;&lt;/em&gt;&lt;/strong&gt; course I'm registered in is a few scrolls away), but it would appear the submission server doesn't know that.&lt;/p&gt;  &lt;p&gt;It doesn't end with the student interface. In a course on &quot;Web Information Systems,&quot; we were required to develop a web-based application of some sort, and my group chose to build a grade tracking system (partly out of frustration with the current system). Before starting the project, we organized a meeting with our instructor to find out what his frustrations were with the existing &quot;Gradebook&quot; system used by the department. He mentioned that instructors had to rebuild the structure of assignments, exams and their relative contributions to the final grade every time they created a course. He continued to show us a tool he developed which allowed him to create more detailed marks, give comments, and build an email to send off to the student. He had to build a custom tool to perform tasks which I would consider essential to a modern grade tracking system. In a few weeks, we hammered out a &quot;school project quality&quot; system running on Ruby on Rails (ASP.Net MVC wasn't out yet :P) which supported all the features we discussed in our meeting with the prof.&lt;/p&gt;  &lt;p&gt;Granted, I know it's not as simple to fix as it is to complain. But, with the tools out there, and the number of open-source and commercial courseware products, I still don't really understand why we're using a system with so many annoying issues...&lt;/p&gt;  &lt;p&gt;For the CS students (or recent grads) who read my blog, is my experience atypical? Or are your school services as out of date as these?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Tips and Tricks: Installing Programs to a USB Key</title>
      <link>http://vibrantcode.com/blog/2009/3/4/tips-and-tricks-installing-programs-to-a-usb-key.html</link>
      <pubDate>Wed, 04 Mar 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/3/4/tips-and-tricks-installing-programs-to-a-usb-key</guid>
      <description>&lt;p&gt;My laptop is rapidly becoming obsolete, particularly when it comes to disk space :(. I want to install my games on it, so I have something to do &lt;strike&gt;in class &lt;/strike&gt;between classes, but I'm running out space. So, I came up with an idea: Buy a 16GB USB Key, and put a bunch of games on that! I keep my USB keys in my backpack, so they're never too far away. It sounded like the perfect solution, until I noticed that many programs can't be installed on Removable Drives!&lt;/p&gt;  &lt;p&gt;So, I came up with a simple workaround, once again using an awesome tool from Sysinternals :). I used &lt;a href=&quot;http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx&quot; target=&quot;_blank&quot;&gt;Junction&lt;/a&gt; to create a junction folder called &quot;C:Program FilesGames&quot; which points to a &quot;Games&quot; folder on my USB Key. The following command line does the trick (assuming F:Games is the folder on the USB key, and &lt;strong&gt;it already exists&lt;/strong&gt;):&lt;/p&gt;  &lt;p&gt;junction.exe &quot;C:Program FilesGames&quot; &quot;F:Games&quot;?&lt;/p&gt;  &lt;p&gt;Seems to be working so far! I just install the game into that folder, and all the files go to the USB Key. Of course, its not quite the same as a &lt;a href=&quot;http://portableapps.com/&quot; target=&quot;_blank&quot;&gt;portable app&lt;/a&gt;, since it will only run on the machine it was installed on, but it takes some of the burden off of my hard drive. If my laptop supported SDHC, I'd probably use a 16GB SD card and just leave it plugged in to my laptop, but unfortunately, that's not an option.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Quake Live - Fun? Sure. Interesting? Meh.</title>
      <link>http://vibrantcode.com/blog/2009/3/2/quake-live-fun-sure-interesting-meh.html</link>
      <pubDate>Mon, 02 Mar 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/3/2/quake-live--fun-sure-interesting-meh</guid>
      <description>&lt;p&gt;There's been a lot of buzz around the Internet about Quake Live. I decided to succumb to the hype and try it out and I must say it is pretty cool. However, a lot of people have heralded this as a unique new way of distributing games, and I have to disagree with that. Quake Live is no different than any other downloadable game, it just happens to use the browser as a host. When you go to &lt;a href=&quot;http://www.quakelive.com&quot;&gt;http://www.quakelive.com&lt;/a&gt; for the first time, you log in and wait in a queue. When you reach the front of the queue, you are prompted to download a plugin (in the form of a Windows Installer MSI file) for your browser. If the queuing thing sounds very &lt;a href=&quot;http://www.fileplanet.com/&quot; target=&quot;_blank&quot;&gt;FilePlanet&lt;/a&gt;-esque to you, it certainly does to me. Then you download the &lt;strike&gt;game&lt;/strike&gt; plugin installer and run it (as an Admin). When it finishes, you have to restart your browser and go back to the website. After waiting in the queue some more, the game loads up and runs in the browser.&lt;/p&gt;  &lt;p&gt;How is this process different from installing a regular desktop game? You download the installer, run it as Admin, and then start the game. The only different here is that the game code is running in-process (AFAIK) with the web browser. It really isn't that different! Developing a game like this using an existing plugin like Flash or Silverlight (especially since &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2008/11/16/update-on-silverlight-2-and-a-glimpse-of-silverlight-3.aspx&quot; target=&quot;_blank&quot;&gt;Silverlight 3 is supposed to include 3D Acceleration support&lt;/a&gt;) would be, IMHO, much more innovative.&lt;/p&gt;  &lt;p&gt;About the only thing in Quake Live that differs from a regular desktop game is the use of a streaming installer, which downloads a (relatively) small bootstrapper and then downloads the rest as you play a 10minute training level. Even that isn't really unique, as &lt;a href=&quot;http://www.hanselman.com&quot; target=&quot;_blank&quot;&gt;Scott Hanselman&lt;/a&gt; &lt;a href=&quot;http://www.hanselman.com/blog/QuakeLiveReviewAndRantWhyIsThisInteresting.aspx&quot; target=&quot;_blank&quot;&gt;points out&lt;/a&gt;, Guild Wars has included that feature for a while.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Announcing Reports Module Version 5.1 and "Saltspring"</title>
      <link>http://vibrantcode.com/blog/2009/3/2/announcing-reports-module-version-51-and-saltspring.html</link>
      <pubDate>Mon, 02 Mar 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/3/2/announcing-reports-module-version-51-and-saltspring</guid>
      <description>&lt;p&gt;I've been pretty busy with school, and unfortunately have not been able to get going on the many new features I want to implement in the Reports Module. However, there are a number of bugs in the current version that prevent it from being used with DotNetNuke 5.0. For this reason, as well as a few other bugs that aren't quite as major, I'm going to be preparing a minor bug-fix release: Version 5.1.&lt;/p&gt;  &lt;p&gt;This version will fix the following major issues:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Errors when accessing the Extensions page using the module with DNN 5.0 &lt;/li&gt;    &lt;li&gt;Many Exceptions are written to the DNN Event Log when the Search Indexer runs over the Reports Module &lt;/li&gt;    &lt;li&gt;Duplicate Search Items are added by the Reports Module, causing exceptions to occur when multi-row Reports are indexed &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;I will also be making minor tweaks and clean-ups. However, no new features will be included in this release. I'm afraid I just don't have the time at the moment (being a full-time student sucks up a lot of time). Please let me know if there are any bugs you feel are urgent and need to be fixed in 5.1 by posting in the &lt;a href=&quot;http://www.dotnetnuke.com/Community/Forums/tabid/795/forumid/136/scope/threads/Default.aspx&quot; target=&quot;_blank&quot;&gt;Reports Module Forums&lt;/a&gt;. (On a side note, I want to remind my readers that the blog comments aren't really the best place to post questions about the Reports Module. I try to keep an eye out for them, but he forums are the best place to do that!)&lt;/p&gt;  &lt;p&gt;Despite my time constraints, I have been doing a little thinking about new features for the Reports Module. Since it seems to be the &quot;in&quot; thing now-a-days, I've given the next major update to the Reports Module a codename: &quot;Saltspring&quot; and I've been building a small feature list:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Minor architecture changes to the Extensions (Data Sources and Visualizers) to improve testability &lt;/li&gt;    &lt;li&gt;Major architecture overhaul to the main module to improve testability, and thus quality, of the core module &lt;/li&gt;    &lt;li&gt;Investigate replacing the ZedGraph Chart component used by the Chart Visualizer with the new &lt;a href=&quot;http://www.asp.net/community/control-gallery/Item.aspx?i=3110&quot; target=&quot;_blank&quot;&gt;Microsoft Chart Control&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Introducing a new Parameters framework which allows users to define custom SQL Parameters for their queries, which pull their value from various different sources (DNN Objects, Query String, Text Fields, etc.)      &lt;ul&gt;       &lt;li&gt;This framework would be extensible, so that new &quot;Parameter Sources&quot; can be installed, just as Data Sources and Visualizers are &lt;/li&gt;     &lt;/ul&gt;   &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Again, if you have any more ideas, please let me know!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Campus Printing: A Tale of Panic and Frustration</title>
      <link>http://vibrantcode.com/blog/2009/2/27/campus-printing-a-tale-of-panic-and-frustration.html</link>
      <pubDate>Fri, 27 Feb 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/2/27/campus-printing-a-tale-of-panic-and-frustration</guid>
      <description>&lt;p&gt;11:00AM - I look in my backpack to check that the Project Proposal that is due at my PHYS 192 class at 11:30 is still in there&lt;/p&gt;  &lt;p&gt;11:01AM - I realize it isn't there, I left it at home&lt;/p&gt;  &lt;p&gt;11:02AM - I decide to just reprint it on campus, and relax&lt;/p&gt;  &lt;p&gt;11:05AM - I fire up Word and open up the Print Dialog&lt;/p&gt;  &lt;p&gt;11:06AM - I discover that the campus print server isn't in my printers list&lt;/p&gt;  &lt;p&gt;11:08AM - I locate the campus printing instructions and start setting up the printer&lt;/p&gt;  &lt;p&gt;11:10AM - I discover that the printer driver I need isn't included in Windows&lt;/p&gt;  &lt;p&gt;11:12AM - I locate the printer driver online and start downloading it&lt;/p&gt;  &lt;p&gt;11:15AM - Printer driver installed, I configure the campus printer&lt;/p&gt;  &lt;p&gt;11:17AM - Still reasonably calm, I fire up Word again and send my document to the print queue.&lt;/p&gt;  &lt;p&gt;11:20AM - After packing up my machine, I walk over to the printing station in the Laptop Lab&lt;/p&gt;  &lt;p&gt;11:21AM - I discover a &quot;Out of Order - Sorry for the inconvenience&quot; sign :(&lt;/p&gt;  &lt;p&gt;11:25AM - I walk to the other side of the building to another lab and put my printer card in the reader&lt;/p&gt;  &lt;p&gt;11:26AM - Spending the last $0.11 on my card, I print my document&lt;/p&gt;  &lt;p&gt;11:27AM - Calmly, I grab the printed document and see the following text:&lt;/p&gt;  &lt;pre&gt;Error: PCL Protocol Error&lt;/pre&gt;&lt;p&gt;11:28AM - Scramble to a PC in the computer lab and log in to the machine&lt;/p&gt;&lt;p&gt;11:30AM - Machine finally logs in, and I fire up Internet Explorer, navigating to my Live Mesh Desktop&lt;/p&gt;&lt;p&gt;11:31AM - Open up the document from Live Mesh and print it&lt;/p&gt;&lt;p&gt;11:33AM - Go back to the printer station, and discover that my printer card is empty!&lt;/p&gt;&lt;p&gt;11:34AM - Walk to the nearby printer card top-up machine and see: &quot;Out of Order - Sorry for the inconvenience&quot;&lt;/p&gt;&lt;p&gt;11:35AM - After discovering I had no cash, walk to the nearby ATM and withdraw some&lt;/p&gt;&lt;p&gt;11:37AM - Head to the nearest cafeteria and buy a bottle of water, getting a twoonie ($2 coin, for my non-Canadian readers) in change :)&lt;/p&gt;&lt;p&gt;11:37AM - Head off to the library on the other side of campus (where the only other printer card top-up machine is, AFAIK)&lt;/p&gt;&lt;p&gt;11:40AM - Reach the library and stick my card in the machine, pop my twoonie in the slot and top-up my card&lt;/p&gt;&lt;p&gt;11:41AM - Go over to the library printer and release the printer job&lt;/p&gt;&lt;p&gt;11:42AM - Pick up the paper and dash over to the lecture hall with my printed proposal in hand&lt;/p&gt;&lt;p&gt;11:45AM - Arrive, late, and take the only remaining seat, at the front of the class, right next to the pile of proposals from the other students&lt;/p&gt;&lt;p&gt;11:46AM - Drop my proposal on the pile and sigh in relief&lt;/p&gt;&lt;p&gt;Seriously, we need a way better campus printing system. Only two top-up machines on campus? Why can't I just add funds to my student account online and submit PDFs and DOCs to be printed if I don't want the hassle of configuring the print server?&lt;/p&gt;&lt;p&gt;Arg...&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Tips and Tricks: Remotely Enable Remote Desktop</title>
      <link>http://vibrantcode.com/blog/2009/2/23/tips-and-tricks-remotely-enable-remote-desktop.html</link>
      <pubDate>Mon, 23 Feb 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/2/23/tips-and-tricks-remotely-enable-remote-desktop</guid>
      <description>&lt;p&gt;Before I start this post, I need to say one thing: &lt;a href=&quot;http://blogs.technet.com/markrussinovich/&quot; target=&quot;_blank&quot;&gt;Mark Russinovich&lt;/a&gt; (as well as anyone else who works on the &lt;a href=&quot;http://technet.microsoft.com/en-ca/sysinternals/default.aspx&quot; target=&quot;_blank&quot;&gt;Sysinternals&lt;/a&gt; stuff) is a Windows Magician. The stuff these tools can do is just plan magic :).&lt;/p&gt;  &lt;p&gt;Last week, my &lt;a href=&quot;http://charlesnurse.com/&quot; target=&quot;_blank&quot;&gt;Dad&lt;/a&gt;'s Dell XPS laptop decided it was tired of rendering graphics and the video card just stopped working (apparently this is a known issue). Dell support was fairly helpful and on Friday we received a box to sent the computer in for a motherboard replacement. Now, I'm paranoid when it comes to data, I don't trust anyone. So, I suggested we try and wipe the hard drive of all the sensitive data on the machine, and change the password so that we wouldn't have to give Dell the actual password. Now, only the graphics card was damaged, the computer ran just fine and even the graphics were intermittent (at first). We tried to get the graphics card working long enough to enable remote desktop, so we could connect from his screaming new Dell desktop (Quad Core i7 with 12GB of RAM... I'm jealous). Unfortunately, by that time, the graphics card was done... no dice :(&lt;/p&gt;  &lt;p&gt;After a little searching, I came across some tips for enabling remote desktop... remotely. It turns out, there are a number of ways to connect to a machine and make changes remotely! The first tip I found was to use the remote registry to enable it: &lt;a title=&quot;http://www.windowsdevcenter.com/pub/a/windows/2004/05/04/serverhacks_remote.html&quot; href=&quot;http://www.windowsdevcenter.com/pub/a/windows/2004/05/04/serverhacks_remote.html&quot;&gt;http://www.windowsdevcenter.com/pub/a/windows/2004/05/04/serverhacks_remote.html&lt;/a&gt;. Unfortunately, the Remote Registry service wasn't running on the laptop! That's when I found Sysinternals &quot;&lt;a href=&quot;http://technet.microsoft.com/en-us/sysinternals/bb897542.aspx&quot; target=&quot;_blank&quot;&gt;PsService&lt;/a&gt;&quot; tool. The tool allows you, as long as you have the Admin account password, to enable/disable and change the start mode of services on a remote machine. So, first I enabled to remote registry service&lt;/p&gt;  &lt;pre&gt;psservice &lt;a href=&quot;file://bilbo&quot;&gt;bilbo&lt;/a&gt; -u [UserName] start RemoteRegistry&lt;/pre&gt;&lt;p&gt;Then, just for good measure, I set the Remote Desktop service to autostart&lt;/p&gt;&lt;pre&gt;psservice &lt;a href=&quot;file://bilbo&quot;&gt;bilbo&lt;/a&gt; -u [UserName] setconfig TermService auto&lt;/pre&gt;&lt;p&gt;Finally, rather than fight with creating a firewall rule remotely, I just disabled the Windows Firewall service (don't do this unless you absolutely have to :D)&lt;/p&gt;&lt;pre&gt;psservice &lt;a href=&quot;file://bilbo&quot;&gt;bilbo&lt;/a&gt; -u [UserName] setconfig MpsSvc disabled&lt;/pre&gt;&lt;p&gt;(Btw, I got all these service names using the Services console on another machine)&lt;/p&gt;&lt;p&gt;Finally, I followed the instructions I mentioned earlier to set the right registry flags to allow Remote Desktop. I killed the power to the PC (I actually tried Sysinternals &quot;&lt;a href=&quot;http://technet.microsoft.com/en-us/sysinternals/bb897541.aspx&quot; target=&quot;_blank&quot;&gt;PsShutdown&lt;/a&gt;&quot; tool first, but had less luck getting that working :D) and restarted it. When I heard the Windows start up sound (as I said, the rest of the components worked just fine :), I fired up remote desktop connection and... bam! I had a remote desktop screen. After a quick pass over the data drive with yet another Sysinternals tool: &quot;&lt;a href=&quot;http://technet.microsoft.com/en-us/sysinternals/bb897443.aspx&quot; target=&quot;_blank&quot;&gt;SDelete&lt;/a&gt;&quot; and a password change, we shut the computer down, packed it up and sent it off to Dell, confident that the important data was scrubbed clean.&lt;/p&gt;&lt;p&gt;Like I said... black magic :). But seriously, the Sysinternals tools rock! If you don't have them, &lt;a href=&quot;http://technet.microsoft.com/en-us/sysinternals/0e18b180-9b7a-4c49-8120-c47c5a693683.aspx&quot; target=&quot;_blank&quot;&gt;get them now&lt;/a&gt;!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Compiler Project - Part 4: ASTs and switching to MGrammar</title>
      <link>http://vibrantcode.com/blog/2009/2/18/compiler-project-part-4-asts-and-switching-to-mgrammar.html</link>
      <pubDate>Wed, 18 Feb 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/2/18/compiler-project--part-4-asts-and-switching-to-mgrammar</guid>
      <description>&lt;p&gt;Here's part 4 of my infinite part series on developing a compiler from scratch. See all the posts &lt;a href=&quot;/ct.ashx?id=cbb29a9a-f33f-45e9-8836-47c73a0fd1a0&amp;amp;url=http%3a%2f%2fblog.andrewnurse.net%2fCategoryView%2ccategory%2cCompiler%252BProject.aspx&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;I've decided to change things up a bit on the compiler project. Instead of writing the tokenizer and parser from scratch, I'm going to check out a new language that's part of Microsoft's &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/cc709420.aspx&quot; target=&quot;_blank&quot;&gt;&quot;Oslo&quot;?&lt;/a&gt; Project. Oslo includes a language called M, which is primarily designed for developing data models. M is actually three languages, MGraph, MSchema and MGrammar. MGraph is a language for defining abstract graphs, for example:&lt;/p&gt;  &lt;pre class=&quot;m&quot; name=&quot;code&quot;&gt;Universities {&lt;br/&gt;    Canada {&lt;br/&gt;        BritishColumbia {&lt;br/&gt;            SFU { &lt;br/&gt;                Name { &amp;quot;Simon Fraser University&amp;quot; }, &lt;br/&gt;                Location { &amp;quot;Burnaby, BC&amp;quot; } &lt;br/&gt;            },&lt;br/&gt;            UBC { &lt;br/&gt;                Name { &amp;quot;University of British Columbia&amp;quot; }, &lt;br/&gt;                Location { &amp;quot;Vancouver, BC&amp;quot; } &lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;MSchema is a language for defining the schema for these graphs, for example&lt;/p&gt;&lt;pre class=&quot;m&quot; name=&quot;code&quot;&gt;module Universities {&lt;br/&gt;    type University {&lt;br/&gt;        Name : Text#100,&lt;br/&gt;        Location : Text#100&lt;br/&gt;    }&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Finally, MGrammar is a language for defining custom Domain-Specific Languages (DSLs) which map to MGraph graphs. This is the language that is most useful to this project. After all, a general-purpose programming language is just a DSL where the &amp;quot;Domain&amp;quot; is very broad :). So, I've spent a few hours this week whipping up an MGrammar grammar for Duh, and the results are promising. I'll be posting some details on that in the next post, but first we need to explore a key concept in compilers, Abstract Syntax Trees.&lt;/p&gt;&lt;p&gt;The end goal of the tokenization and parsing phases of a compiler is to produce an Abstract Syntax Tree (or AST) representing the source code. This is probably best illustrated by an example, so consider this expression:&lt;/p&gt;&lt;pre&gt;5+6&lt;/pre&gt;&lt;p&gt;This is an addition operation, using 5 and 6 as the arguments, which we represent in an AST like this (using the MGraph syntax above):&lt;/p&gt;&lt;pre&gt;Add { 5, 6 }&lt;/pre&gt;&lt;p&gt;Similarly, more complex expressions can be translated to trees:&lt;/p&gt;&lt;pre&gt;5+6*(3+4)&lt;/pre&gt;&lt;p&gt;Becomes:&lt;/p&gt;&lt;pre&gt;Add { 5, Multiply { 6, Add { 3, 4 } } }&lt;/pre&gt;&lt;p&gt;Which represents the following instructions:&lt;/p&gt;&lt;ul&gt;&lt;br/&gt;  &lt;li&gt;Add 3 and 4 &lt;/li&gt;&lt;br/&gt;  &lt;li&gt;Multiply that result by 6 &lt;/li&gt;&lt;br/&gt;  &lt;li&gt;Add 5 to that result &lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;p&gt;Essentially, we are building up the expression from the bottom of the tree up. This makes it much easier to convert the expression into code.&lt;/p&gt;&lt;p&gt;I'll post the MGrammar file for the language when I finish it up in a day or so, then its on to writing the code to do the parsing.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Get-PowerKit: A PowerShell Packaging System</title>
      <link>http://vibrantcode.com/blog/2009/2/9/get-powerkit-a-powershell-packaging-system.html</link>
      <pubDate>Mon, 09 Feb 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/2/9/getpowerkit-a-powershell-packaging-system</guid>
      <description>&lt;p&gt;&lt;strong&gt;UPDATE 2: PowerKits requires PowerShell 2.0. If you're seeing errors regarding the &quot;try-catch&quot; keywords, its because those keywords were added in PowerShell 2.0 and I use them in PowerKits. Sorry!&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;UPDATE: It turns out PowerShell 2.0 already contains a feature like this: &quot;Modules.&quot;? See &lt;/strong&gt;&lt;a href=&quot;http://huddledmasses.org/powershell-modules/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt; for more info. Since it seems to be far superior to PowerKit (which I just hacked together for my own needs), I guess that just leaves this as an interesting exercise :).&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I've been a huge fan of Windows PowerShell since it first came out as &quot;Monad&quot; (aka &quot;MSH&quot;?). Now that its entering version 2.0, which will be built-in to Windows 7 and Windows Server 2008, I'm getting even more into it. I've written a Podcast Receiver (PowerCast) and an automated process for converting videos for use on my Xbox 360 (PowerCode).&lt;/p&gt;  &lt;p&gt;[The following paragraph is a short intro to PowerShell, feel free to skip it if you're familiar with PoSH]&lt;/p&gt;  &lt;p&gt;What is PowerShell? PowerShell is an object-oriented shell which, IMHO, kicks the pants off of BASH and Perl. PowerShell is a dynamically-typed scripting language written on the .Net Framework, which gives you full access to every class, method, and property in the framework. You could write a GUI, Server, heck even a 3D Game in PowerShell (it just might not perform as well as another language). PowerShell is also an interactive &quot;Read-Eval-Print&quot; loop application which gives you a prompt into which you type commands which are then evaluated and their results printed to the screen (i.e. a standard &quot;Shell&quot; similar to cmd.exe or BASH). Finally, PowerShell is an embeddable scripting environment which lets any .Net-based application embed the PowerShell scripting language. However, most people (myself included) are referring to the Shell itself when they talk about PowerShell&lt;/p&gt;  &lt;p&gt;Anyway, on to the main purpose of this post. I started to get frustrated with trying to manage all my scripts and keep them organized. I was also downloading a lot of useful scripts off of the web, but had to manually place them somewhere in my file-system (let alone managing all the dependencies). Other scripting environments, such as Ruby, have packaging systems, such as RubyGems, to manage libraries of functionality and publish them for others to download. So, I thought, why doesn't PowerShell have something like this?&lt;/p&gt;  &lt;p&gt;Thus, PowerKits were born. The concept is simple. A PowerKit is a directory on your file-system which contains a manifest file &quot;Kit.xml&quot;?. This file specifies some information such as the paths to various script files, aliases to create, .Net assemblies to load and (in a future version) PowerShell &quot;snap-ins&quot; to load. After installing a kit (by placing it in one of many, configurable, pre-defined folders), it can simply be enabled using a single PowerShell Command. For example, to enable the &quot;MyCompany.MyKit&quot; PowerKit:&lt;/p&gt;  &lt;pre class=&quot;code&quot;&gt;Enable-Kit MyCompany.MyKit&lt;/pre&gt;&lt;p&gt;Enabling a kit loads all the assemblies, script files, etc. into your PowerShell environment, making them available for use. A Kit can then be disabled similarly using the &quot;?Disable-Kit&quot; command. Disabling the kit removes all the script files, etc. from the environment (NOTE: .Net assemblies cannot be unloaded without restarting PowerShell, due to a limitation of the .Net Framework).&lt;/p&gt;&lt;p&gt;PowerKit also supports packaging kits into a ZIP-like format, specifically the &lt;a href=&quot;http://en.wikipedia.org/wiki/Open_Packaging_Convention&quot; target=&quot;_blank&quot;&gt;Open Packaging Convention&lt;/a&gt; developed by Microsoft for Office 2007 (since the .Net framework has built-in support for that format). These &quot;Kit Archives&quot; can be downloaded and installed using a single command. Eventually, I plan to add support for installing a kit directly from the web, so you could use a command like this:&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;Install-Kit &lt;a href=&quot;http://www.mycompany.com/MyCompany.MyKit.kit&quot;&gt;http://www.mycompany.com/MyCompany.MyKit.kit&lt;/a&gt;&lt;/pre&gt;&lt;p&gt;Or even this:&lt;/p&gt;&lt;pre class=&quot;code&quot;&gt;Install-Kit MyCompany.MyKit&lt;/pre&gt;&lt;p&gt;And the framework would go out and download the kit and install it, giving PowerShell a true &quot;gems-esque&quot; packaging system.&lt;/p&gt;&lt;p&gt;To install PowerKit, download the Install-PowerKit.ps1 script from the &lt;a href=&quot;http://www.codeplex.com/powerkits&quot; target=&quot;_blank&quot;&gt;CodePlex site&lt;/a&gt;, more installation details are in the release notes on that page.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Argument check gotcha with "yield" keyword in C#</title>
      <link>http://vibrantcode.com/blog/2009/2/2/argument-check-gotcha-with-yield-keyword-in-c.html</link>
      <pubDate>Mon, 02 Feb 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/2/2/argument-check-gotcha-with-yield-keyword-in-c</guid>
      <description>&lt;p&gt;I recently used the 'yield' keyword in a C# method and ran into a strange issue when trying to verify arguments. I always try to verify the arguments provided to my methods so that I can throw &lt;code&gt;ArgumentException&lt;/code&gt; or &lt;code&gt;ArgumentNullException&lt;/code&gt; as necessary. However, when you use the 'yield' keyword to create an enumerator in C#, you can run into issues&lt;/p&gt;  &lt;p&gt;The 'yield' keyword lets you easily create a method which returns an enumerator (which can then be used in a &lt;code&gt;foreach&lt;/code&gt; loop). For example, if I wanted to make a method that took a &lt;code&gt;DirectoryInfo&lt;/code&gt; (representing a directory on disk) and returned file names of all the .txt files in it, I would write this:&lt;/p&gt;  &lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;public IEnumerable&amp;lt;string&amp;gt; GetTextFiles(DirectoryInfo dir) {&lt;br/&gt;    if (dir == null) {&lt;br/&gt;        throw new ArgumentNullException(&amp;quot;dir&amp;quot;);&lt;br/&gt;    }&lt;br/&gt;    foreach (FileInfo file in dir.GetFiles(&amp;quot;*.txt&amp;quot;)) {&lt;br/&gt;        yield return file.Name;&lt;br/&gt;    }&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;However, the C# compiler will do something tricky with this method, because of the 'yield' keyword. It will create a custom implementation of &lt;code&gt;IEnumerable&amp;lt;string&amp;gt;&lt;/code&gt; class that uses &amp;quot;magic&amp;quot; (I'm not going to go into detail as to how it works :P) to jump in and out of the code you wrote. Then, it compiles our method to the following (as decompiled with &lt;a href=&quot;http://www.red-gate.com/products/reflector/&quot; target=&quot;_blank&quot;&gt;RedGate's .Net Reflector&lt;/a&gt;, a free tool every .Net developer &lt;strong&gt;must&lt;/strong&gt; have :D):&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;public IEnumerable&amp;lt;string&amp;gt; GetTextFiles(DirectoryInfo dir)&lt;br/&gt;{&lt;br/&gt;    &amp;lt;GetTextFiles&amp;gt;d__0 d__ = new &amp;lt;GetTextFiles&amp;lt;d__0(-2);&lt;br/&gt;    d__.&amp;lt;&amp;gt;4__this = this;&lt;br/&gt;    d__.&amp;lt;&amp;gt;3__dir = dir;&lt;br/&gt;    return d__;&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Wait a sec, where'd our code go? It looks like it's gone into this &lt;code&gt;&amp;lt;GetTextFiles&amp;gt;d__0&lt;/code&gt; class. If you think that name sounds compiler-generated, you're right! It's the custom implementation of &lt;code&gt;IEnumerable&amp;lt;string&amp;gt;&lt;/code&gt; that was created by the compiler. Cool, eh? However, there's a side effect here. Where did our argument checking code go? Unless there's something in the &lt;code&gt;&amp;lt;GetTextFiles&amp;gt;d__0&lt;/code&gt; constructor, the user could pass &lt;code&gt;null&lt;/code&gt; in for the &lt;code&gt;dir&lt;/code&gt; parameter and no exception would be thrown! So, let's take a look at the &lt;code&gt;&amp;lt;GetTextFiles&amp;gt;d__0&lt;/code&gt; constructor (using Reflector again):&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;[DebuggerHidden]&lt;br/&gt;public &amp;lt;GetTextFiles&amp;gt;d__0(int &amp;lt;&amp;gt;1__state)&lt;br/&gt;{&lt;br/&gt;    this.&amp;lt;&amp;gt;1__state = &amp;lt;&amp;gt;1__state;&lt;br/&gt;    this.&amp;lt;&amp;gt;l__initialThreadId = Thread.CurrentThread.ManagedThreadId;&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Nope, nothing there. If you keep checking around the &lt;code&gt;&amp;lt;GetTextFiles&amp;gt;d__0&lt;/code&gt; class, you'll find it in the &lt;code&gt;MoveNext&lt;/code&gt; method on that class. That means that instead of checking the argument when you call the method, the argument won't be checked until the first time &lt;code&gt;MoveNext&lt;/code&gt; is called (i.e. the first iteration of a foreach loop). If, instead, we wrap the actual &quot;yield&quot; code in it's own method, and call it from our original method (after argument checks), we'll get the desired result:&lt;/p&gt;&lt;pre&gt;public IEnumerable&amp;lt;string&amp;gt; GetTextFiles(DirectoryInfo dir) {&lt;br/&gt;    if (dir == null) {&lt;br/&gt;        throw new ArgumentNullException(&amp;quot;dir&amp;quot;);&lt;br/&gt;    }&lt;br/&gt;    return InternalGetTextFiles(dir);&lt;br/&gt;}&lt;br/&gt;private IEnumerable&amp;lt;string&amp;gt; InternalGetTextFiles(DirectoryInfor dir) {&lt;br/&gt;    foreach (FileInfo file in dir.GetFiles(&amp;quot;*.txt&amp;quot;)) {&lt;br/&gt;        yield return file.Name;&lt;br/&gt;    }&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Now, the &amp;quot;magic&amp;quot; is occurring in &lt;code&gt;InternalGetTextFiles&lt;/code&gt; and &lt;code&gt;GetTextFiles&lt;/code&gt; is compiled without modification and our argument checking works just fine.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Wild Ideas - Using lambdas to check arguments in C#</title>
      <link>http://vibrantcode.com/blog/2009/1/30/wild-ideas-using-lambdas-to-check-arguments-in-c.html</link>
      <pubDate>Fri, 30 Jan 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/1/30/wild-ideas--using-lambdas-to-check-arguments-in-c</guid>
      <description>&lt;p&gt;One of the most common checks I do is a simple null check on arguments being passed in to the methods I write.&amp;nbsp; I usually create a static class called &quot;Arg&quot; with the following methods (to help out):&lt;/p&gt;  &lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;public static class Arg {&lt;br/&gt;    public static void NotNull(object value, string paramName) {&lt;br/&gt;        if (value == null) {&lt;br/&gt;            throw new ArgumentNullException(paramName);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;    public static void NotNullOrEmpty(string value, string paramName) {&lt;br/&gt;        if (String.IsNullOrEmpty(value)) {&lt;br/&gt;            // ED: Error_StringArgumentNullOrEmpty is a key in my Visual Studio&lt;br/&gt;            //  project's default string resources file (Properties/Resources.resx)&lt;br/&gt;            throw new ArgumentException(&lt;br/&gt;                String.Format(CultureInfo.CurrentCulture, &lt;br/&gt;                              Resources.Error_StringArgumentNullOrEmpty, &lt;br/&gt;                              paramName), &lt;br/&gt;                paramName);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Then, I can use it like this&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;public void Foo(string arg, object reallyLongArgumentName) {&lt;br/&gt;    Arg.NotNullOrEmpty(arg, &quot;arg&quot;);&lt;br/&gt;    Arg.NotNull(reallyLongArgumentName, &quot;reallyLongArgumentName&quot;);&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;I was recently playing with &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/bb397687.aspx&quot; target=&quot;_blank&quot;&gt;lambda expressions&lt;/a&gt; in C# and thought of a way to make this a little cooler.&amp;nbsp; The result is, I can rewrite the lines above like this:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;public void Foo(string arg, object reallyLongArgumentName) {&lt;br/&gt;    Arg.NotNullOrEmpty(() =&amp;gt; arg);&lt;br/&gt;    Arg.NotNull(() =&amp;gt; reallyLongArgumentName);&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;The first obvious advantage is that for longer argument names, its more concise.&amp;nbsp; The second, is that I no longer have to worry about updating the strings representing the parameter names when I rename arguments, the Visual Studio Refactoring engine will take care of it for me.&lt;/p&gt;&lt;p&gt;Obviously, this is slower than the previous method since I'm diving into the lambda expression at runtime, but its cool.&amp;nbsp; But if I need the performance, I have a little Regular Expression I can run in Visual Studio to convert the lambda calls back to the string versions (and vice-versa)&lt;/p&gt;&lt;p&gt;How does it work? Well, the core of the code is a static helper in the &lt;code&gt;Arg&lt;/code&gt; class&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;private static string GetParameterName&amp;lt;T&amp;gt;(Expression&amp;lt;Func&amp;lt;T&amp;gt;&amp;gt; paramExpr) {&lt;br/&gt;    LambdaExpression lambda = paramExpr as LambdaExpression;&lt;br/&gt;    Debug.Assert(lambda != null);&lt;br/&gt;    MemberExpression paramRef = lambda.Body as MemberExpression;&lt;br/&gt;    Debug.Assert(paramRef != null);&lt;br/&gt;    // Get the parameter name&lt;br/&gt;    string paramName = paramRef.Member.Name;&lt;br/&gt;    return paramName;&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Lines 2-5 dive through the Expression tree to find the &lt;code&gt;MemberExpression&lt;/code&gt; that represents the parameter (i.e. &quot;foo&quot; in &lt;code&gt;() =&amp;gt; foo&lt;/code&gt;). Then, we pull out the &lt;code&gt;MemberInfo&lt;/code&gt; for the parameter and check the name. With that method, the actual checker is easy:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;public static void NotNull(Expression&amp;lt;Func&amp;lt;object&amp;gt;&amp;gt; paramExpr) {&lt;br/&gt;    string paramName = GetParameterName(paramExpr);&lt;br/&gt;    // Compile the lambda (to get the value)&lt;br/&gt;    Func&amp;lt;object&amp;gt; compiledLambda = paramExpr.Compile();&lt;br/&gt;    &lt;br/&gt;    // Run the contract check&lt;br/&gt;    NotNull(compiledLambda(), paramName);&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Line 2 extracts the parameter name. Line 5 compiles the lambda into an actual function that will return the value of the parameter. Finally, Line 8 uses the value and the parameter name to call my original &lt;code&gt;object/string&lt;/code&gt; version. The code for &lt;code&gt;NotNullOrEmpty&lt;/code&gt; is nearly identical.&lt;/p&gt;&lt;p&gt;Anyway, if you're concerned about performance, stick to the overloads which take the parameter name directly. I've attached the code as a TXT file, just rename to C#, change the namespace as appropriate and enjoy&lt;/p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/Arg.txt&quot;&gt;Arg.txt (3.93 KB)&lt;/a&gt;
</description>
    </item>
    
    <item>
      <title>Compiler from Scratch - Part 3: Tokenization Overview</title>
      <link>http://vibrantcode.com/blog/2009/1/28/compiler-from-scratch-part-3-tokenization-overview.html</link>
      <pubDate>Wed, 28 Jan 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/1/28/compiler-from-scratch--part-3-tokenization-overview</guid>
      <description>&lt;p&gt;Here comes part 3 of my infinite part series on developing a compiler from scratch. See all the posts &lt;a href=&quot;/CategoryView,category,Compiler%2BProject.aspx&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The first phase of compilation is called Tokenization. Tokenization is the process of taking individual characters in the source code file and grouping them into more conceptual &quot;Tokens.&quot; We're not parsing the language, or checking syntax, we're just grouping related characters together. Why do we do this? If we skipped this step, we'd be passing characters directly to our parser. The parser doesn't care that the text contains the characters 'f' 'o' 'o', it cares that the source file contains an Identifier called &quot;foo&quot;. There's also a separation of concerns issue. In theory, if you wanted to allow accented Unicode characters like ?, ?, ?, etc. (you may see blocks or '?' characters instead of the real characters, if so just pretend they're there :D) as valid characters in identifiers, you should only have to change the Tokenizer (to accept those characters and use them, along with the regular alphanumeric characters, to build identifier tokens). The formal name for Tokenization is actually &quot;Lexical Analysis,&quot; and sometimes the Tokens are called &quot;Atoms.&quot;&lt;/p&gt;  &lt;p&gt;So, how do we Tokenize text? There are lots of tools out there, most of which let you define your tokens using Regular Expressions (so an identifier would be: &quot;[_A-Za-z][_0-9A-Za-z]*&quot;, one letter or underscore followed by zero or more letters, numbers or underscores). These tools build state machines (aka &quot;&lt;a href=&quot;http://en.wikipedia.org/wiki/Finite_state_machine&quot; target=&quot;_blank&quot;&gt;Finite Automata&lt;/a&gt;&quot;) that basically walk through all the Regular Expressions until exactly one of them matches the current text buffer. Tools like &quot;&lt;a href=&quot;http://en.wikipedia.org/wiki/Lex_programming_tool&quot; target=&quot;_blank&quot;&gt;lex&lt;/a&gt;&quot; basically allow you to build a full-featured, efficient, Tokenizer by simply writing Regular Expressions.&lt;/p&gt;  &lt;p&gt;However, that would be too easy for this series :). Instead, I'm using a very simple, hand-coded, Tokenizer which walks through the characters, using &quot;if&quot; and &quot;switch&quot; statements to decide what tokens to output. However, we can't just simply iterate through the characters. Consider the &quot;-&amp;gt;&quot; operator in Duh (see &lt;a href=&quot;/2009/01/19/WritingACompilerFromScratchNdashPart1.aspx&quot; target=&quot;_blank&quot;&gt;Part 1&lt;/a&gt;). Duh supports the simple arithmetic operators, specifically &quot;-&quot;, and I plan to support inequality operators (i.e &quot;&amp;lt;&quot;, &quot;&amp;gt;&quot;, etc.), so in theory, the &quot;-&amp;gt;&quot; operator could be outputted as a pair of tokens: MINUS and GREATERTHAN (I'll use ALLCAPS to denote the names of tokens). However, this would be putting a larger burden on the parser to detect the MINUS GREATERTHAN pattern. Instead, we can take advantage of &quot;lookahead&quot;&lt;/p&gt;  &lt;p&gt;The Tokenizer uses the .Net TextReader class, which lets us walk, one character at a time, through the characters in a body of text. However, once we've called the &lt;code&gt;Read&lt;/code&gt; method, the TextReader moves on to the next character and the next time we call it, we'll get the next character. So, in order to properly parse the &quot;-&amp;gt;&quot; operator, we need a way to look at the next character, without moving the reader. Fortunately, the TextReader also has the &lt;code&gt;Peek&lt;/code&gt; method, which does exactly that.&lt;/p&gt;  &lt;p&gt;So now, when we encounter a &quot;-&quot; symbol, we look at the next character. If it is a &quot;&amp;gt;&quot;, we output an ARROW token, and move to the next character. Otherwise, we output a MINUS token and leave the reader at the &quot;&amp;gt;&quot; character. Then, in the next iteration, we read the &quot;&amp;gt;&quot; and output a GREATERTHAN token.&lt;/p&gt;  &lt;p&gt;Phew, that was a bit long, and more theoretical than I like, but I'll post some code in the next part. Next time, we'll look at the actual code for the Tokenizer.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>ASP.Net MVC 1.0 Release Candidate released</title>
      <link>http://vibrantcode.com/blog/2009/1/28/aspnet-mvc-10-release-candidate-released.html</link>
      <pubDate>Wed, 28 Jan 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/1/28/aspnet-mvc-10-release-candidate-released</guid>
      <description>&lt;p&gt;&lt;a href=&quot;http://www.haacked.com&quot; target=&quot;_blank&quot;&gt;Phil Haack&lt;/a&gt; (program manager on the ASP.Net MVC team) just posted a &lt;a href=&quot;http://haacked.com/archive/2009/01/27/aspnetmvc-release-candidate.aspx&quot; target=&quot;_blank&quot;&gt;blog post&lt;/a&gt; about the new Release Candidate of the MVC framework. Since I got a chance to work on the MVC framework team as an intern this summer (and I'm going back full-time this summer), I'm pretty excited about the news. When this goes RTM, it'll be the first time code that I wrote will be part of a full shipping Microsoft product! &lt;/p&gt;  &lt;p&gt;So download the binaries from &lt;a href=&quot;http://www.asp.net/mvc/&quot; target=&quot;_blank&quot;&gt;ASP.Net&lt;/a&gt; or check out the source code on &lt;a href=&quot;http://www.codeplex.com/aspnet/Wiki/View.aspx?title=MVC&amp;amp;referringTitle=Home&quot; target=&quot;_blank&quot;&gt;CodePlex&lt;/a&gt; and have some fun!&lt;/p&gt;  &lt;p&gt;Also, check out &lt;a href=&quot;http://weblogs.asp.net/scottgu/archive/2009/01/27/asp-net-mvc-1-0-release-candidate-now-available.aspx&quot; target=&quot;_blank&quot;&gt;Scott Guthrie's post on the new features&lt;/a&gt;. He shows off one of the features that, I think, makes ASP.Net MVC more compelling than Ruby on Rails: Powerful first-party tooling support.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Compiler from Scratch - Part 2: Normalizing Newlines</title>
      <link>http://vibrantcode.com/blog/2009/1/25/compiler-from-scratch-part-2-normalizing-newlines.html</link>
      <pubDate>Sun, 25 Jan 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/1/25/compiler-from-scratch--part-2-normalizing-newlines</guid>
      <description>&lt;p&gt;Well, this is a good sign, I'm posting part 2 :). As I said in &lt;a href=&quot;/2009/01/19/WritingACompilerFromScratchNdashPart1.aspx&quot; target=&quot;_blank&quot;&gt;Part 1&lt;/a&gt;, there are no promises here. This series may not go anywhere, I may have to drop it due to my other commitments (school, work, etc.).&lt;/p&gt;  &lt;p&gt;In the next few posts, I'm going to talk about the Tokenization phase of the compiler. Before I go into too much detail on that though, I want to talk about newlines.&lt;/p&gt;  &lt;p&gt;In Windows, a new line in a text file is indicated by a pair of characters: A Carriage Return (commonly referred to as &quot;\r&quot;, as that is the C/C++ string escape sequence for it) followed by a Line Feed (&quot;\?n&quot;?). However, in Unix-based operating systems, a new line is often indicated by a Line Feed character alone. To add even more confusion, the Mac OS uses a Carriage Return character alone. &lt;/p&gt;  &lt;p&gt;A compiler needs to track line numbers accurately, in order to report errors, so we need be extra careful around newlines. We could simply use the current operating system's default newline characters, but that makes it difficult for multi-platform development. Instead, we'll normalize the newlines so that all three different types are properly understood by our compiler.&lt;/p&gt;  &lt;p&gt;To do this, I've written a &quot;Decorator&quot; class which inherits from the abstract &lt;code&gt;TextReader&lt;/code&gt; class provided in the .Net framework. This &quot;Newline Normalizing&quot; decorator wraps an existing &lt;code&gt;TextReader&lt;/code&gt; and does all the work of normalizing new line characters TextReader provides two methods that need to be implemented, &lt;code&gt;Read&lt;/code&gt; and &lt;code&gt;Peek&lt;/code&gt;. &lt;code&gt;Read&lt;/code&gt; returns the current character from the text and moves the reader one character forwards (so that the next call to Read will return the next character). &lt;code&gt;Peek&lt;/code&gt; also returns the current character from the text but &lt;strong&gt;does not&lt;/strong&gt; move the reader forward. The &quot;Newline Normalizing&quot; reader implements these two methods using the following code&lt;/p&gt;  &lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;public override int Peek() {&lt;br/&gt;    // Get the next character&lt;br/&gt;    int i = Adaptee.Peek();&lt;br/&gt;    &lt;br/&gt;    // If the character is a 'r' newline, just return 'n'.  &lt;br/&gt;    // Unlike Read, we aren't going to read ahead to check for rn&lt;br/&gt;    // because that will happen when the user calls Read()&lt;br/&gt;    if (i == (int)'r') {&lt;br/&gt;        i =  (int)'n';&lt;br/&gt;    }&lt;br/&gt;    return i;&lt;br/&gt;}&lt;br/&gt;public override int Read() {&lt;br/&gt;    // Get the next character&lt;br/&gt;    int i = Adaptee.Read();&lt;br/&gt;    // If the character is a 'r' newline, we're going to normalize it to 'n'&lt;br/&gt;    // However, if the newline is 'rn', we need to return it as one character, so&lt;br/&gt;    // we check ahead for that&lt;br/&gt;    if (i == (int)'r') {&lt;br/&gt;        if (Adaptee.Peek() == (int)'n') {&lt;br/&gt;            Adaptee.Read(); // Skip the 'n'&lt;br/&gt;        }&lt;br/&gt;        i = (int)'n';&lt;br/&gt;    }&lt;br/&gt;    return i;&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Essentially, if the character we read from the source (the &quot;Adaptee&quot; as I call it) is a '\n', we just pass it along. If the character is a '\r', we are going to return '\n', but first we first check to see if it is immediately followed by a '\n'. If it is, we skip the extra character. The result is that no matter which newline sequence is used, this &lt;code&gt;TextReader&lt;/code&gt; will return it as a single '\n' character.&lt;/p&gt;&lt;p&gt;Next post, I'll start talking about the Tokenization process.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Writing a Compiler from Scratch - Part 1</title>
      <link>http://vibrantcode.com/blog/2009/1/19/writing-a-compiler-from-scratch-part-1.html</link>
      <pubDate>Mon, 19 Jan 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/1/19/writing-a-compiler-from-scratch--part-1</guid>
      <description>&lt;p&gt;EDIT: Whoops, wrote the wrong course number (CMPT 376), corrected below. I'm taking CMPT 376, Writing for Computer Scientists, this semester, must have gotten myself mixed up :)&lt;/p&gt;  &lt;p&gt;Ok, I'm going to try something here, and I don't know if I'll manage to finish it. My all-time favorite class in my school career (so far) has been CMPT 379 - Compiler Design. The class basically consisted of me writing a compiler in Visual C++, with weekly lectures and code reviews from the professor (it was a small class). Since then, I've been trying to think of a reason to write a compiler (i.e. a language that can be ported to .Net, or a useful domain-specific language, etc.). Then, this morning, as I walked back to the Computing Science common room from the Gym (after my morning workout), I found a reason. I think compilers are some of the most interesting pieces of software, and I thought that if I wrote a series of blog posts in which I developed a compiler, maybe I could share that passion with others. &lt;/p&gt;  &lt;p&gt;So, here's the plan: I've designed an, extremely simple, language that I'm going to walk through writing a compiler for. The initial version will target .Net IL code (since it's a stack machine system, which is much easier to generate code for). Once I've implemented the simple language, I think it'd be awesome if my readers could jump in and propose some ideas for new language features, and I'll try to blog about implementing them.&lt;/p&gt;  &lt;p&gt;To be honest, this project may well fall flat on its face. Writing a compiler is not a simple task, no matter how simple the language. However, I do think it will be fun (while it lasts), so let's give it a try!&lt;/p&gt;  &lt;p&gt;So, step one is: Define your language! The most essential part of compiler design is having a very clear idea of the purpose of your language. The language I'm going to design is called &quot;Duh&quot;?, because it's probably about as simple as it gets (maybe a little more complex than &lt;a href=&quot;http://en.wikipedia.org/wiki/Brainf**k&quot; target=&quot;_blank&quot;&gt;Brainf**k&lt;/a&gt; (NOTE: link target does include a few four-letter words :D)). Here's a sample Duh program&lt;/p&gt;  &lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;print &amp;quot;Enter your age: &amp;quot;;&lt;br/&gt;ageInput : string;&lt;br/&gt;age : int;&lt;br/&gt;ageInput = readline;&lt;br/&gt;age = ageInput -&amp;gt; int;&lt;br/&gt;print &amp;quot;In 10 years you will be &amp;quot; + (age + 10) -&amp;gt; string + &amp;quot;. Wow, that's old&amp;quot;&lt;/pre&gt;&lt;p&gt;Pretty simple, eh? Line 1 is a simple print statement, which accepts a string and write it to the console. Lines 2 and 3 declare variables of string and 32-bit integer types (decided to use a more Pascal-esque variable declaration format, just for fun). Lines 4 and 5 assign values to those variables. Line 4 uses another built-in function, readline, which reads a line of text from the console. Note that we don't even support initializing variables in the declaration! That's ok though, this is just a toy language, we can add initializations later. Line 5 introduces the &quot;-&amp;gt;&quot; conversion operator, which takes the value on the left and converts it to the type on the right. It's not quite the same as a cast, because it will try to convert the value, if it can. Finally, we add 10 to the value the user entered and convert it to a string, then we place that string into a large message and print it to the console.&lt;/p&gt;&lt;p&gt;Well, here goes nothing! Feel free to post your initial comments. I hope you'll follow along! I'll be posting full source code with every post&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>My First Windows 7 Blue-Screen - But it was my fault :P</title>
      <link>http://vibrantcode.com/blog/2009/1/15/my-first-windows-7-blue-screen-but-it-was-my-fault-p.html</link>
      <pubDate>Thu, 15 Jan 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/1/15/my-first-windows-7-bluescreen--but-it-was-my-fault-p</guid>
      <description>&lt;p&gt;I just had my first Windows 7 Blue Screen of Death :(. However, it was my own fault for trying to use an unsupported driver :P. I had just listened to an episode of &lt;a href=&quot;http://twit.tv/sn&quot; target=&quot;_blank&quot;&gt;Security Now&lt;/a&gt; on a tool called &lt;a href=&quot;http://www.sandboxie.com&quot; target=&quot;_blank&quot;&gt;Sandboxie&lt;/a&gt;. Sandboxie is a tool which intercepts Windows API calls made by programs to read/write files and registry keys. Once intercepted, Sandboxie redirects them to files and registry keys in a special &quot;Sandbox&quot;?, so that changes made by programs are isolated from each other. It's a cool security solution, and very similar in spirit to Microsoft's &lt;a href=&quot;http://www.microsoft.com/systemcenter/appv/default.mspx&quot; target=&quot;_blank&quot;&gt;App-V&lt;/a&gt; platform (only cheaper, and aimed at consumers rather than enterprises :D).&lt;/p&gt;  &lt;p&gt;In order to intercept the Windows API calls, however, Sandboxie has to install a kernel-mode driver and patch the kernel. In 64-bit versions of Windows, a system called PatchGuard prevents this from happening, thus Sandboxie is not compatible with those operating systems. However, my laptop is running a 32-bit version of Windows 7, so I decided to try it out.&lt;/p&gt;  &lt;p&gt;At first, I got a compatibility message from the Sandboxie installer, telling me that my OS is not supported. That should have been my first clue :). I decided to take a gamble and try it out anyway, so I tweaked the compatibility settings for the installer so that it ran in &quot;Windows Vista&quot; compatibility mode. The installer ran fine, and installed the software. However, when I tried to run it, BAM, BSOD :(. &lt;/p&gt;  &lt;p&gt;Resigning myself to the fact that it just wasn't ready for Windows 7, I booted up in Safe Mode. However, I was unable to run the installer again to remove it. I tried &quot;Add/Remove Programs&quot; and running the installer I downloaded again (in Vista compatibility mode). Still nothing. Fortunately, I was just about to restart for Windows Update when I installed Sandboxie, and Windows Update automatically creates a System Restore point before installing updates. I fired up System Restore, picked the Windows Update restore point and let it do its thing. The machine rebooted, and I was back in action, with Sandboxie (and my BSODs) gone. I had lost the updates that WU installed, but that's a minor inconvenience.&lt;/p&gt;  &lt;p&gt;Anyway, all is well now, and I was able to boot up again (in order to write this post in fact :D). So, two lessons here:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Use System Restore! Just remember to make restore points before installing software that you are concerned about. (Though that will NOT protect you from malicious software, just incompatible software)&lt;/li&gt;    &lt;li&gt;Check out Sandboxie, just not on Windows 7 :(. My theory is that the PatchGuard technology from the 64-bit OS may have been brought into the 32-bit OS.&lt;/li&gt; &lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Windows 7 First Impressions</title>
      <link>http://vibrantcode.com/blog/2009/1/13/windows-7-first-impressions.html</link>
      <pubDate>Tue, 13 Jan 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/1/13/windows-7-first-impressions</guid>
      <description>&lt;p&gt;So, as an MSDN subscriber (no, I'm not made of money, Microsoft Interns get a free year-long subscription to MSDN for personal use :P), I had access to the Windows 7 public beta a day early. I decided to go crazy, since I've been hearing its really stable, and put the latest OS on both my laptop &lt;strong&gt;and &lt;/strong&gt;my desktop. (Well, I actually put Windows 7 Server, aka Windows Server 2008 R2 on my desktop). So, I figured I'd post my first impressions.&lt;/p&gt;  &lt;h3&gt;Installation&lt;/h3&gt;  &lt;p&gt;There's not much to say here, Installation is exactly like Windows Vista, only a little faster. The only new feature is that Windows 7 Setup prompts you to create a HomeGroup, if you want. HomeGroups are the new networking construct introduced in Windows 7 designed to make it easier to share files and devices between networked computers. I haven't had a change to check that out yet, so I'll come back to it later.&lt;/p&gt;  &lt;h3&gt;Initial Impression&lt;/h3&gt;  &lt;p&gt;Besides a stylish new boot screen, in which four coloured dots dance around before combining to form the Windows logo, the boot process is also identical to Windows Vista. I did find that it booted up much faster than Vista (though I can't make an accurate comparison, since my laptop was getting a bit overloaded). The new taskbar is very cool, and while it is a bit of a knock-off of the OSX Dock, I think Microsoft has (in typical Microsoft fashion) gone above and beyond the OSX experience. For example, by hovering the mouse over an icon, a list of all the windows belonging to that application appears. Even better, applications which directly support Windows 7 can add their own &quot;windows&quot; to this list. For example, even though I only have one IE8 window open, each tab in that window appears as a separate item in the windows list.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/Windows7FirstImpressions_CD0A/image_2.png&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;Taskbar Windows List&quot; border=&quot;0&quot; alt=&quot;Taskbar Windows List&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/Windows7FirstImpressions_CD0A/image_thumb.png&quot; width=&quot;716&quot; height=&quot;264&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;By hovering over each thumbnail, that window is brought to focus on the screen, and the rest of the windows become &quot;glass&quot;?.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/Windows7FirstImpressions_CD0A/image_4.png&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;Peeking at a Window&quot; border=&quot;0&quot; alt=&quot;Peeking at a Window&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/Windows7FirstImpressions_CD0A/image_thumb_1.png&quot; width=&quot;644&quot; height=&quot;337&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;(And yes, I did blank out my Windows Messenger buddies list :P).&lt;/p&gt;  &lt;p&gt;Jump lists are another cool feature, but I haven't had a chance to explore it much. Essentially, when you right click, or click and drag up on one of these taskbar icons, a jump list appears.&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/Windows7FirstImpressions_CD0A/image_6.png&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;IE8 Jumplist&quot; border=&quot;0&quot; alt=&quot;IE8 Jumplist&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/Windows7FirstImpressions_CD0A/image_thumb_2.png&quot; width=&quot;287&quot; height=&quot;599&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;In this case (Internet Explorer 8), my history is displayed. Applications designed for Windows 7, get a lot of control over this list, but applications which are not designed to support it (PowerShell 2.0 for example) just get a simple default list&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/Windows7FirstImpressions_CD0A/image_8.png&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px&quot; title=&quot;PowerShell 2.0 Jumplist&quot; border=&quot;0&quot; alt=&quot;PowerShell 2.0 Jumplist&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/Windows7FirstImpressions_CD0A/image_thumb_3.png&quot; width=&quot;298&quot; height=&quot;131&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;I haven't had much of a chance to explore the rest of the new stuff, so I'll post more later, but my initial impression is that Windows 7 is just plain awesome :).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Redirecting your Zune Library to another folder/drive</title>
      <link>http://vibrantcode.com/blog/2009/1/11/redirecting-your-zune-library-to-another-folderdrive.html</link>
      <pubDate>Sun, 11 Jan 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/1/11/redirecting-your-zune-library-to-another-folderdrive</guid>
      <description>&lt;p&gt;As I mentioned in an earlier post about backing up a Zune Library (&lt;a href=&quot;/2008/12/11/BackingUpAZuneLibraryForWhenYouReinstallWindows.aspx&quot; target=&quot;_blank&quot;&gt;Backup a Zune Library...&lt;/a&gt;), I wanted to find a way to be able to actually store the Zune library database on a different drive. I played with the Microsoft Sysinternals &quot;&lt;a href=&quot;http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx&quot; target=&quot;_blank&quot;&gt;Junction&lt;/a&gt;&quot; tool, which lets you create &lt;em&gt;hardlinks&lt;/em&gt; (&lt;a href=&quot;http://en.wikipedia.org/wiki/Hard_Link&quot; target=&quot;_blank&quot;&gt;Wikipedia on Hardlinks&lt;/a&gt;) and managed to get it to work. Here's the process to do it yourself. Replace &lt;em&gt;UserName&lt;/em&gt; with your Windows user name and &lt;em&gt;D:MusicZuneLibrary&lt;/em&gt; with the path to the folder you want to store the database in.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Download Junction.exe from here: &lt;a title=&quot;http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx&quot; href=&quot;http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx&quot;&gt;http://technet.microsoft.com/en-us/sysinternals/bb896768.aspx&lt;/a&gt; (replace &lt;em&gt;D:UtilsSysinternalsjunction.exe&lt;/em&gt; below with the path you downloaded junction.exe to) &lt;/li&gt;    &lt;li&gt;Shut down the Zune software if it is running. &lt;/li&gt;    &lt;li&gt;Rename the folder C:\Users\&lt;em&gt;UserName&lt;/em&gt;\AppData\Local\Microsoft\Zune to Zune_backup (just to be safe). You may encounter a file locking issue, but I found that if I waited a few minutes it worked. &lt;/li&gt;    &lt;li&gt;Copy the Zune_backup folder to &lt;em&gt;D:MusicZune&lt;/em&gt; and rename it to &lt;em&gt;Library&lt;/em&gt;&lt;/li&gt;    &lt;li&gt;Run the following command:      &lt;pre&gt;D:UtilsSysinternalsjunction.exe Zune D:MusicZuneLibrary&lt;/pre&gt;  &lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;p&gt;That should do it! Start Zune up again and your library should be up and running. Now you should be able to reinstall the OS without having to back up the Zune library. I might try to whip up a PowerShell or Batch file to do this, but don't get too hopeful :).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Mappr: Projecting Geographical Points on the Screen</title>
      <link>http://vibrantcode.com/blog/2009/1/9/mappr-projecting-geographical-points-on-the-screen.html</link>
      <pubDate>Fri, 09 Jan 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/1/9/mappr-projecting-geographical-points-on-the-screen</guid>
      <description>&lt;p&gt;One of the courses I took last semester (Fall 2008), was &quot;Software Engineering II&quot;. In this class, we were required to work in groups to implement a project that the professor specified. We had to go through the whole process, design, implementation, testing (though we could choose any software process model we wanted: Waterfall, XP, Agile, etc.). Our group's project was an application called &quot;Mappr&quot; that would allow users to browse a map. Well, it was a little more than that, but that's all the background required by this post, I'll post more background in future posts.&lt;/p&gt;  &lt;p&gt;One of the necessary components in mapping software is called a &quot;Projection&quot;. The Earth is round, and Latitude and Longitude co-ordinates are spherical measurements representing points on the Earth. In order to convert those co-ordinates to (x, y) co-ordinates for displaying on a (flat) computer screen, you must &lt;em&gt;project&lt;/em&gt; the geographical co-ordinates into screen co-ordinates. One well-known technique for doing this is called the &lt;a href=&quot;http://en.wikipedia.org/wiki/Mercator_projection&quot;&gt;Mercator Projection&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;A quick aside: The Mercator Projection is widely known (in geography circles) for being highly inaccurate. However, it is the projection used by most road maps, atlases, etc., both physical and digital.&lt;/p&gt;  &lt;p&gt;In Mappr, projection is handled by a component called a &quot;Projection Strategy&quot;?. A Projection Strategy is a C# class (Mappr was written in C#) with two methods: GeoToScreen and ScreenToGeo.&amp;#160; Here are the signatures of those methods:&lt;/p&gt;  &lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;public interface IProjectionStrategy {&lt;br/&gt;    Point GeoToScreen(Point geographicalPoint, int zoomLevel, int tileSize);&lt;br/&gt;    Point ScreenToGeo(Point screenPoint, int zoomLevel, int tileSize);&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;The purpose of each method is straight forward: To take in either Geographical (Latitude, Longitude) co-ordinates or Screen (X, Y) co-ordinates, and convert them to the other. In order to do this, we must know the Zoom Level, which is an integer &lt;em&gt;N&lt;/em&gt; indicating that there are &lt;em&gt;2&lt;sup&gt;N&lt;/sup&gt;&lt;/em&gt; tiles on the screen. We also need the size, in pixels, of each map tile image. This means that the size of the map, in pixels, is given by: &lt;em&gt;2&lt;sup&gt;zoomLevel&lt;/sup&gt; * tileSize&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;The code to &lt;em&gt;project&lt;/em&gt; a geographical point on to the screen is shown below:&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;public Point GeoToScreen(Point geographicalPoint, int zoomLevel, int tileSize) {&lt;br/&gt;    // Convert to normalized mercator&lt;br/&gt;    double lon = geographicalPoint.X;&lt;br/&gt;    double lat = geographicalPoint.Y;&lt;br/&gt;    if (lon &amp;gt; 180) {&lt;br/&gt;        lon -= 360;&lt;br/&gt;    }&lt;br/&gt;    lon /= 360;&lt;br/&gt;    lon += 0.5;&lt;br/&gt;    lat = 0.5 - ((Math.Log(Math.Tan((Math.PI / 4) + &lt;br/&gt;                 ((0.5 * Math.PI * lat) / 180))) / Math.PI) / 2.0);&lt;br/&gt;    double scale = (1 &amp;lt;&amp;lt; zoomLevel) * tileSize;&lt;br/&gt;    return new Point(lon * scale, lat * scale);&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;This code first normalizes the longitude (X direction) so that it is in the range 0.0 to 1.0 (where 0.0 is the left of the map and 1.0 is the right). Then it does what I like to call &quot;mathy stuff&quot; (the calculations are taken from &lt;a href=&quot;http://mapki.com/wiki/Tile_utility_code_in_Java&quot;&gt;similar code written in Java&lt;/a&gt;) with the latitude to put it in the same range (0.0 is the top, 1.0 is the bottom). Finally, we calculate the scale of the map (height/width in pixels, since the map is technically a square) and then we can use the normalized longitude and latitude as ratios of that scale.&lt;/p&gt;&lt;p&gt;The ScreenToGeo method is similar, the code is below. I won't describe this, but just provide it for reference.&lt;/p&gt;&lt;pre class=&quot;csharp&quot; name=&quot;code&quot;&gt;public Point ScreenToGeo(Point screenPoint, int zoomLevel, int tileSize) {&lt;br/&gt;    int pixelSpan = (1 &amp;lt;&amp;lt; zoomLevel) * tileSize;&lt;br/&gt;    double lngWidth = 360.0 / pixelSpan; // width in degrees longitude&lt;br/&gt;    double lng = -180 + (screenPoint.X * lngWidth); // left edge in degrees longitude&lt;br/&gt;    double latHeightMerc = 1.0 / pixelSpan; // height in &amp;quot;normalized&amp;quot; mercator 0,0 top left&lt;br/&gt;    double latMerc = screenPoint.Y * latHeightMerc; // top edge in &amp;quot;normalized&amp;quot; mercator 0,0 top left&lt;br/&gt;    &lt;br/&gt;    // convert top and bottom lat in mercator to degrees&lt;br/&gt;    // note that in fact the coordinates go from about -85 to +85 not -90 to 90!&lt;br/&gt;    double lat = (180 / Math.PI) * ((2 * Math.Atan(Math.Exp(Math.PI * (1 - (2 * latMerc)))))&lt;br/&gt;                       - (Math.PI / 2));&lt;br/&gt;    return new Point(lng, lat);&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;By the way, feel free to use any of the code in this post in your own application. Consider it &amp;quot;Public Domain&amp;quot;. However, I would appreciate (but not require) if you would place a comment near it indicating that this blog is the source of the original code.&lt;/p&gt;&lt;p&gt;Hopefully this helps those of you writing mapping applications in C#! Please post any questions or comments in the comments section!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Writing a blog for fun and profit... I mean grades</title>
      <link>http://vibrantcode.com/blog/2009/1/8/writing-a-blog-for-fun-and-profit-i-mean-grades.html</link>
      <pubDate>Thu, 08 Jan 2009 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2009/1/8/writing-a-blog-for-fun-and-profit-i-mean-grades</guid>
      <description>&lt;p&gt;The Spring semester at SFU is off to a running start (after a day lost to the snow), and I've already got some homework to do!&amp;nbsp; One of the classes I'm taking is a course titled &quot;Writing for Computer Scientists&quot;. The goal is to develop writing skills through practice. Lots and lots of practice :).&lt;/p&gt;  &lt;p&gt;Each class (3 times a week), we're required to submit some &quot;writing&quot;?.&amp;nbsp; I use quotes simply to emphasize the freedom of this assignment.&amp;nbsp; All I &lt;strong&gt;have&lt;/strong&gt; to do is write a single word, and turn it in each week.&amp;nbsp; Of course, that's not really the point of the assignment ;).&amp;nbsp; One option, provided by the professor, is simply to start a blog (if you don't already have one) and post 2-3 entries per week.&amp;nbsp; Given that I already have a blog which I have had trouble maintaining, I figure this is a good kick in the behind to get myself blogging again.&amp;nbsp; &lt;/p&gt;  &lt;p&gt;So, I'll hopefully be blogging more often (at least while my grades depend on it :D).&amp;nbsp; I'll probably stick to the current subject of the blog: observations from an open-source developer on the Microsoft ASP.Net platform.&amp;nbsp; Just in case I start to wander to different topics, I'll make sure to tag appropriately, so my normal readers can subscribe just to the posts they're interested in.&lt;/p&gt;  &lt;p&gt;It's time to start blogging for fun and &lt;strike&gt;profit&lt;/strike&gt; grades!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Playing with Azure and SQL Data Services: No "Random Access Paging"</title>
      <link>http://vibrantcode.com/blog/2008/12/16/playing-with-azure-and-sql-data-services-no-random-access-pa.html</link>
      <pubDate>Tue, 16 Dec 2008 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/12/16/playing-with-azure-and-sql-data-services-no-random-access-paging</guid>
      <description>So, I've started playing around with the whole Azure Services Platform (http://www.azure.com), now that school's done :) and I thought I'd blog about things I discover along the way.&lt;br&gt;&lt;br&gt;My first idea was to create a simple blogging engine in MVC that would store data in SQL Data Services and run in Windows Azure (I got my invite code recently, yay!).&amp;nbsp; However, I soon discovered that would be difficult.&amp;nbsp; It turns out that while SQL Data Services does support &quot;Paging&quot; the results of a query so that you don't retrieve every result in one batch, it does not support what I refer to as &quot;Random Access Paging&quot;.&amp;nbsp; Random Access Paging (and I'm sure theres some other term for it) basically means providing a page index and page size to the data layer and having it retrieve just that page (i.e. Skip/Take in LINQ).&amp;nbsp; There are some solutions, but most of them requrire that you step through each page sequentially, rather than just being able to request a page.&lt;br&gt;&lt;br&gt;Of course, I may be missing something. So, if you know how I could solve this problem, feel free to post in the comments!&lt;br&gt;&lt;br&gt;In a blogging engine, this is practically a necessity, since you only want to display a certain number of posts per page.&amp;nbsp; So I've tabled that idea for now.&lt;br&gt;&lt;br&gt;My next idea: An RSS reader which stores your set of subscribed feeds in your Live Mesh (though I don't have access to that CTP yet).&lt;br&gt;&lt;p&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Backing up a Zune Library for when you reinstall Windows</title>
      <link>http://vibrantcode.com/blog/2008/12/11/backing-up-a-zune-library-for-when-you-reinstall-windows.html</link>
      <pubDate>Thu, 11 Dec 2008 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/12/11/backing-up-a-zune-library-for-when-you-reinstall-windows</guid>
      <description>I regularly reinstall Windows, so when I used iTunes, I had to make sure I knew how to back up my music library (because I didn't want to re-rate all my songs :D).&amp;nbsp; I recently switched back to Zune from iTunes because I got so frustrated with my cracked iPod Touch screen.&amp;nbsp; Then, came the invevitable reinstall :)&lt;br&gt;&lt;br&gt;I keep my music on a separate partition, along with ALL my data (Folder Redirection for the win!), so the music files aren't the problem.&amp;nbsp; With iTunes I could place the music library database on the other drive too, but so far no luck there with the Zune software (I'm going to check out Junctions to see if that will work).&amp;nbsp; So, I resigned myself to digging through my AppData folder to see if I could find the stuff I needed.&lt;br&gt;&lt;br&gt;For those who don't already know, the AppData folder, in Windows Vista is in: C:\Users\[UserName]\AppData.&amp;nbsp; This is where programs (should) store their per-user settings and configuration data.&amp;nbsp; Unfortunately (AFAIK) it's not possible to redirect this folder (like you can with Documents, Music, etc.).&amp;nbsp; &lt;br&gt;&lt;br&gt;The Zune software stores its settings in C:\Users\[UserName]\AppData\Local\Microsoft\Zune.&amp;nbsp; All I had to do was copy this folder over to my second partition, reinstall the OS and reinstall the Zune software.&amp;nbsp; Then, I started the Zune software, just to be sure and shut it down again.&amp;nbsp; I copied the backed up folder back into place, restarted the Zune software and voila my library is back.&amp;nbsp; I was even able to reconnect my Zune and have it automatically recognize it and sync!&lt;br&gt;&lt;br&gt;So, in summary:&lt;br&gt;&lt;ol&gt;&lt;li&gt;Back up C:\Users\[UserName]\AppData\Local\Microsoft\Zune&lt;/li&gt;&lt;li&gt;Reinstall Windows and other Apps&lt;br&gt;&lt;/li&gt;&lt;li&gt;Reinstall Zune&lt;/li&gt;&lt;li&gt;Start Zune software (not sure if it's necessary, but it worked for me)&lt;/li&gt;&lt;li&gt;Shutdown Zune software&lt;/li&gt;&lt;li&gt;Copy backup back in to C:\Users\[UserName]\AppData\Local\Microsoft\Zune&lt;/li&gt;&lt;li&gt;Start Zune software and enjoy!&lt;/li&gt;&lt;/ol&gt;Let me know if that works for you, or if you have problems!&lt;br&gt;&lt;p&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>VidSpeak Part 3 - Generating and Playing Audio</title>
      <link>http://vibrantcode.com/blog/2008/11/21/vidspeak-part-3-generating-and-playing-audio.html</link>
      <pubDate>Fri, 21 Nov 2008 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/11/21/vidspeak-part-3--generating-and-playing-audio</guid>
      <description>&lt;p&gt;This is part 3 of my VidSpeak series, where I show off an app I wrote for my multimedia course.&amp;nbsp; &lt;a href=&quot;/2008/10/30/VidSpeakPart2BitmapManipulation.aspx&quot;&gt;Check out part 2&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;5. Generate the Sound&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Alright, so this is the complex part :).&amp;nbsp; For the assignment, we were instructed to convert each column of the quantized grayscale 64x64 frame to a chord of sound.&amp;nbsp; We were asked to do this by assigning a frequency to each row of the image (the middle row being 440Hz or &quot;A440&quot;, which is the &quot;A&quot; above middle &quot;C&quot; on a piano).&amp;nbsp; Then the &quot;brightness&quot; of the pixel at that row is the intesity of that frequency in the chord.&amp;nbsp; So, if a pixel was black, that frequency was not part of the chord, and if it was white, that frequency was part of the chord (at 100% intensity). &lt;/p&gt;  &lt;p&gt;Sound is generated using a process called &lt;a href=&quot;http://en.wikipedia.org/wiki/Frequency_Modulation&quot;&gt;Frequency Modulation&lt;/a&gt; (or &quot;&lt;a href=&quot;http://interngame.com/synchronetics/page.php?id=groan&amp;amp;sol=1&quot;&gt;FREAK WHEN SEE MOD YOU LATE SHUN&lt;/a&gt;&quot; as I like to call it (inside joke for MS interns who did The Microsoft Intern Game :P)).&amp;nbsp; Essentially what we are going to do is create sine waves of each frequency we want to play, scale them by the intensity value, and then add them together to create a new sine wave, representing the whole chord.&amp;nbsp; This process is done with this code &lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;csharp&quot;&gt;&lt;br/&gt;uint* data = (uint*) Marshal.AllocHGlobal(SamplesPerColumn * Marshal.SizeOf(typeof (uint)));&lt;br/&gt;for (int sample = 0; sample &lt; SamplesPerColumn; sample++) {&lt;br/&gt;    double signal = 0.0f;&lt;br/&gt;    for (int col = 0; col &lt; width; col++) {&lt;br/&gt;        PixelData* cell = row0 + col;&lt;br/&gt;        double intensity = cell-&gt;Red / (double) (_quantizationLevels - 1);&lt;br/&gt;        signal += (intensity * Math.Sin(2.0f * Math.PI * FrequencyTable[col] * TimeTable[sample]));&lt;br/&gt;    }&lt;br/&gt;    signal = (uint.MaxValue / 2) * (signal + 1);&lt;br/&gt;    *(data + sample) = (uint) signal;&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;  &lt;p&gt;Because sound is represented digitally in computers, we can't send the sine wave itself, we have to take discrete samples of it that we will send to the sound card.&amp;nbsp; In this case, I'm taking 500 samples for each column (SamplesPerColumn = 500).&amp;nbsp; Elsewhere in my code I informed the sound card that I would be generating sound at 8000Hz (or 8000 samples per second), meaning that 500 samples will produce 0.0625seconds of audio. &lt;/p&gt;  &lt;p&gt;For each sample I'm going to generate, I iterate across the columns (remember, I rotated the image in step 1 so that each row of the image now represents a column of the original frame).&amp;nbsp; Then I generate a sample of the sine wave for that frequency and multiply it by the value at the pixel (as a float, where 15 is 1.0 and 0 is 0.0) (that's the line that starts &quot;signal +=&quot;.&amp;nbsp; Once I've added up all the samples for the chord, I convert the float into an unsigned integer where (uint.MaxValue / 2) represents 0 and store in the (unmanaged) buffer I'm building. &lt;/p&gt;  &lt;p&gt;From there, I just send that unmanaged buffer 'data' to the sound card using a helper class I created to wrap the waveOut API: &lt;/p&gt;  &lt;p&gt;SoundDevice.WriteAudioBlock(new IntPtr(data), (uint)SamplesPerColumn);&lt;/p&gt;  &lt;p&gt;The helper class basically wraps a low-level Win32 API called &quot;waveOut&quot;?.&amp;nbsp; It's not as powerful as using DirectX or some other high-level API, but it gets the job done :).&amp;nbsp; The code for this helper is in the SoundDevice class in my code. Remember, all the code is posted in my &lt;a href=&quot;/2008/10/21/VidSpeakPart1ExtractingFramesFromVideoInC.aspx&quot;&gt;Part 1 post.&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;That's it for VidSpeak.&amp;nbsp; I'm going to be posting more code from my other school projects soon, but I have to finish them first :P.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Sorry about the delay on VidSpeak Part 3</title>
      <link>http://vibrantcode.com/blog/2008/11/9/sorry-about-the-delay-on-vidspeak-part-3.html</link>
      <pubDate>Sun, 09 Nov 2008 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/11/9/sorry-about-the-delay-on-vidspeak-part-3</guid>
      <description>&lt;p&gt;VidSpeak Part 3 is a little delayed. However, the main reason is that I've been working on a bunch of other school projects, which I plan to post about in future posts :). Stay tuned for the last part of VidSpeak and some more stuff ;)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>VidSpeak Part 2 - Bitmap Manipulation</title>
      <link>http://vibrantcode.com/blog/2008/10/30/vidspeak-part-2-bitmap-manipulation.html</link>
      <pubDate>Thu, 30 Oct 2008 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/10/30/vidspeak-part-2--bitmap-manipulation</guid>
      <description>&lt;p&gt;This is part 2 of my VidSpeak series, where I show off an app I wrote for my multimedia course.&amp;nbsp; &lt;a href=&quot;/2008/10/21/VidSpeakPart1ExtractingFramesFromVideoInC.aspx&quot;&gt;Check out part 1&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;To recap from last time, the problem this assignment is trying to solve is to convert video frames to some kind of audio representation.&amp;nbsp; There are the steps required:&lt;/p&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt;Extract the next frame from the video &lt;br/&gt;&lt;/li&gt;&lt;li&gt;Scale the frame down to 64x64 pixels &lt;br/&gt;&lt;/li&gt;&lt;li&gt;Make the frame a grayscale image &lt;br/&gt;&lt;/li&gt;&lt;li&gt;&quot;Quantize&quot; the grayscale frame into 4-bit colour &lt;br/&gt;&lt;/li&gt;&lt;li&gt;Convert the frame to sound&lt;/li&gt;&lt;/ol&gt;&lt;br/&gt;&lt;p&gt;I covered extracting video frames in Part 1, so now we have to manipulate the image to prepare it for rendering as sound.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2. Scale the frame down to 64x64 pixels&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;All the transformation steps (2-4) are performed by &quot;filters&quot; which recieve a System.Drawing.Bitmap and return a transformed one (a filter could also modify the incoming Bitmap and then just return the same object).&amp;nbsp; Scaling is trivial with the &quot;GetThumbnailImage&quot; method on System.Drawing.Image:&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;csharp&quot;&gt;public Bitmap ProcessImage(Bitmap input) {&lt;br/&gt;    return new Bitmap(input.GetThumbnailImage(TargetWidth, TargetHeight, null, IntPtr.Zero));&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;3. Make the frame a grayscale image&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;There may be a function in .Net to do this, but as part of the assignment we were provided with a formula to convert RGB images to 255-shade grayscale images so I decided to do this.&amp;nbsp; Now, the Bitmap class provides GetPixel and SetPixel methods, but they aren't really very performant when you need to touch every pixel.&amp;nbsp; Fortunately, the Bitmap class provides a method called &quot;LockPixels&quot; which prevents the Garbage Collector from moving the Bitmap data around in memory.&amp;nbsp; With that, I made a base class for filters that process a Bitmap on a Pixel-by-Pixel basis:&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;csharp&quot;&gt;&lt;br/&gt;BitmapData data = input.LockBits(new Rectangle(0, 0, input.Width, input.Height), &lt;br/&gt;                                 ImageLockMode.ReadWrite, &lt;br/&gt;                                 PixelFormat.Format24bppRgb);&lt;br/&gt;unsafe {&lt;br/&gt;    for (int col = 0; col &amp;lt; data.Width; col++) {&lt;br/&gt;        for (int row = 0; row &amp;lt; data.Height; row++) {&lt;br/&gt;            PixelData* pixel = (PixelData*)data.Scan0 + col + row * data.Width;&lt;br/&gt;            ProcessPixel(pixel);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;}&lt;br/&gt;input.UnlockBits(data);&lt;br/&gt;&lt;/pre&gt;&lt;p&gt;PixelData is a simple 3-byte struct:&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;csharp&quot;&gt;[StructLayout(LayoutKind.Sequential)]&lt;br/&gt;public struct PixelData {&lt;br/&gt;    public byte Blue;&lt;br/&gt;    public byte Green;&lt;br/&gt;    public byte Red;&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Then, my grayscale image filter just has to implement ProcessPixel&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;csharp&quot;&gt;&lt;br/&gt;byte convertedValue = (byte) Math.Floor((0.299 * pixel-&amp;gt;Red) + &lt;br/&gt;                                        (0.587 * pixel-&amp;gt;Green) + &lt;br/&gt;                                        (0.114 * pixel-&amp;gt;Blue));&lt;br/&gt;pixel-&amp;gt;Red = convertedValue;&lt;br/&gt;pixel-&amp;gt;Green = convertedValue;&lt;br/&gt;pixel-&amp;gt;Blue = convertedValue;&lt;/pre&gt;&lt;p&gt;Kinda strange to see the &quot;-&amp;gt;&quot; operator in C#, eh?&lt;/p&gt;&lt;p&gt;4. &quot;Quantize&quot; the image to 4-bit colour&lt;/p&gt;&lt;p&gt;Quantization is the process of &quot;compressing a range of values to a single quantum value&quot; (&lt;a href=&quot;http://en.wikipedia.org/wiki/Quantization_%28image_processing&quot;&gt;http://en.wikipedia.org/wiki/Quantization_(image_processing&lt;/a&gt;)).&amp;nbsp; In this case, we are quantizing an 8-bit Grayscale image to a 4-bit Grayscale image.&amp;nbsp; To do this, we take each pixel value, and assign it one of 16 partitions (4-bits can hold values 0 through 15).&amp;nbsp; The following code (in FixedPartitionQuantizationStrategy) does this (note _partitionSize is 16 in this case).&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;csharp&quot;&gt;public byte Quantize(byte input) {&lt;br/&gt;    return (byte)Math.Floor((double)input / _partitionSize);&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;Quantization is done by the QuantizeImageFilter, which uses a similar base class to the Grayscale conversion above.&amp;nbsp; Then, an IQuantizationStrategy is used to perform the Quantization itself:&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;csharp&quot;&gt;protected override unsafe void ProcessPixel(PixelData* pixel) {&lt;br/&gt;    pixel-&amp;gt;Red = _strategy.Quantize(pixel-&amp;gt;Red);&lt;br/&gt;    pixel-&amp;gt;Green = _strategy.Quantize(pixel-&amp;gt;Green);&lt;br/&gt;    pixel-&amp;gt;Blue = _strategy.Quantize(pixel-&amp;gt;Blue);&lt;br/&gt;}&lt;br/&gt;&lt;/pre&gt;&lt;p&gt;And thats it! We now have an image that is 64x64 pixels&amp;nbsp;in 4-bit Grayscale.&amp;nbsp; Next we have to render it out to sound.&amp;nbsp; Stay tuned for Part 3 for that!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>VidSpeak Part 1 - Extracting Frames from Video in C#!</title>
      <link>http://vibrantcode.com/blog/2008/10/21/vidspeak-part-1-extracting-frames-from-video-in-c.html</link>
      <pubDate>Tue, 21 Oct 2008 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/10/21/vidspeak-part-1--extracting-frames-from-video-in-c</guid>
      <description>&lt;p&gt;I know, its been too long since I blogged, but its pretty busy at school right now :). Anyway, I'm taking a course in Multimedia this semester, and as part of that course, I have to write a program to convert frames in a Video to short Audio clips.&amp;nbsp;I thought it might&amp;nbsp;be interesting to examine how that is done, in C#.&amp;nbsp; So, over the course of about 3-4 posts, I'll go over the code that I wrote.&amp;nbsp; I've attached the full project to this post, so you can take a look at it right now.&amp;nbsp; The GUI app should work, though I can't guarantee it. All I can give it is &quot;Works on My Machine&quot; seal of approval :)&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;http://www.codinghorror.com/blog/images/works-on-my-machine-starburst.png&quot;&gt; &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Here are the steps involved:&lt;/p&gt;&lt;ol&gt;&lt;br/&gt;&lt;li&gt;Extract the next frame from the video &lt;br/&gt;&lt;/li&gt;&lt;li&gt;Scale the frame down to 64x64 pixels &lt;br/&gt;&lt;/li&gt;&lt;li&gt;Make the frame a grayscale image &lt;br/&gt;&lt;/li&gt;&lt;li&gt;&quot;Quantize&quot; the grayscale frame into 4-bit colour &lt;br/&gt;&lt;/li&gt;&lt;li&gt;Convert the frame to sound&lt;/li&gt;&lt;/ol&gt;&lt;br/&gt;&lt;h5&gt;The Code&lt;/h5&gt;&lt;br/&gt;&lt;p&gt;The Code is a Visual Studio 2008 solution, written for .Net 3.5.&amp;nbsp; It uses unsafe code for image processing and sound generation, so you can't run it without full trust (i.e. you can't run it off of a network share).&lt;/p&gt;&lt;h5&gt;1. Extract the next frame from the video&lt;/h5&gt;&lt;br/&gt;&lt;p&gt;I used a &quot;Pipeline&quot; (&lt;a href=&quot;http://en.wikipedia.org/wiki/Pipeline_%28software%29&quot;&gt;http://en.wikipedia.org/wiki/Pipeline_(software)&lt;/a&gt;) architecture, so this phase is handled by a component I call a &quot;Frame Source&quot; which is expected to return a new frame when asked (or return null to signal the end of the input). I used the DirectShow COM library &quot;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms783323.aspx&quot;&gt;DexterLib&lt;/a&gt;&quot; to do the extraction. DexterLib contains a class called MediaDet (for MediaDetector) which does most of the work. Here's the code for the function which retrieves a frame at a specified timecode (in seconds).&amp;nbsp; &lt;/p&gt;&lt;p&gt;FYI: &quot;_detector&quot; is an instance of DexterLib.MediaDetClass() (&quot;_detector&quot; is of type IMediaDet), &quot;_streamLength&quot; is the length of of the video stream in seconds, &quot;_bufferHandle&quot; is an IntPtr referring to an unmanaged buffer (allocated with Marshal.AllocHGlobal) to hold the bitmap, and &quot;_bufferSize&quot;/&quot;_frameSize&quot; are the size of the buffer and the size of each video frame (respectively)&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;csharp&quot;&gt;// WARNING: This method will destroy the bitmap retrieved in a previous call to this method&lt;br/&gt;public Bitmap GetFrameAtTime(double timeCode) {&lt;br/&gt;    // Get the bitmap at this time&lt;br/&gt;    Bitmap frame = null;&lt;br/&gt;    unsafe {&lt;br/&gt;        byte* bufferPointer = (byte*)_bufferHandle;&lt;br/&gt;        _detector.GetBitmapBits(timeCode, &lt;br/&gt;                                ref _bufferSize, &lt;br/&gt;                                ref *bufferPointer, &lt;br/&gt;                                _frameSize.Width, &lt;br/&gt;                                _frameSize.Height);&lt;br/&gt;        frame = new Bitmap(_frameSize.Width, // Width&lt;br/&gt;                           _frameSize.Height, // Heigth&lt;br/&gt;                           _frameSize.Width * 3, // Stride&lt;br/&gt;                           PixelFormat.Format24bppRgb, // Pixel Format&lt;br/&gt;                           new IntPtr(bufferPointer + &lt;br/&gt;                                      Marshal.SizeOf(typeof(BITMAPINFOHEADER)))); // Start of Buffer&lt;br/&gt;    }&lt;br/&gt;    return frame;&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;(Note: If you look at the actualy code, you will notice I snipped out some stuff from the beginning of this function to display it on the blog.&amp;nbsp;The missing code just handles an (experimental) feature I added to allow me to start at any location in the video, rather than always starting at the beginning)&lt;/p&gt;&lt;p&gt;After loading the frame, I have to flip it, because Dexter loads the frame upside-down, fortunately the System.Drawing.Image class provides a RotateFlip method to do just that! I also rotate it 90 degrees clock-wise, so that each row of the transformed image maps to a column of the frame. This makes step 5 easier, since Bitmaps are stored in &quot;row-major&quot; order (&lt;a href=&quot;http://en.wikipedia.org/wiki/Row-major_order&quot;&gt;http://en.wikipedia.org/wiki/Row-major_order&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;To use the Frame Source, all my program has to do is call GetFrameAtTime method passing in a timecode (in seconds).&amp;nbsp; This is handled in the FrameProcessor by the GetNextFrame method&lt;/p&gt;&lt;pre name=&quot;code&quot; class=&quot;csharp&quot;&gt;_source.GetFrameAtTime((DateTime.Now - _startTime).TotalSeconds)&lt;/pre&gt;&lt;p&gt;Rather than going frame-by-frame, I'm extracting the next frame by time.&amp;nbsp; So, if it takes 4 seconds to process a frame, the next frame I take is approximately 4 seconds after the frame I just processed.&lt;/p&gt;&lt;p&gt;Here's the code: &lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/VidSpeak.zip&quot;&gt;VidSpeak.zip (267.21 KB)&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Fun Summer</title>
      <link>http://vibrantcode.com/blog/2008/8/23/269280550083.html</link>
      <pubDate>Sat, 23 Aug 2008 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/8/23/fun-summer</guid>
      <description>Well, its been a fun summer, but my time at Microsoft is over ...&lt;br&gt;&lt;br&gt;&lt;br&gt;... for now :).&amp;nbsp; It looks like I'll be coming back full-time come next August, so it's a bittersweet end.&amp;nbsp; I'll miss the people on my team and the interns I've met, but in most cases I'll see them again next year!&amp;nbsp; Keep an eye on this blog, because you can bet I'll be posting when the stuff I worked on goes live!&lt;br&gt;&lt;p&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Awesomeness, in a box.</title>
      <link>http://vibrantcode.com/blog/2008/8/19/awesomeness-in-a-box.html</link>
      <pubDate>Tue, 19 Aug 2008 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/8/19/awesomeness-in-a-box</guid>
      <description>&lt;p&gt;Thanks to Alex Tuteur for typing up the lyrics from our scribbles on&lt;br/&gt;paper, to Kyle Farnung for filiming, converting and posting the&lt;br/&gt;video, to Kristine Johnson for singing the epic win-ness, and to all the people who helped write the song!&lt;br&gt;&lt;/p&gt;&lt;object width=&quot;425&quot; height=&quot;344&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/7xoxE399IFE&amp;amp;hl=en&amp;amp;fs=1&quot;&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;&gt;&lt;embed src=&quot;http://www.youtube.com/v/7xoxE399IFE&amp;amp;hl=en&amp;amp;fs=1&quot; type=&quot;application/x-shockwave-flash&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;344&quot;&gt;&lt;/object&gt;&lt;br/&gt;&lt;p&gt;STILL AROUND&lt;br&gt;By Andrew Nurse, Kristine Johnson, Alex Tuteur, Ben Butler, Kyle Farnung, Steven Truong (EXP), Adam Kiu, and William Hong&lt;/p&gt;Internz: a triumph&lt;br&gt;I'm sending a lolcat: EPIC FAIL&lt;br&gt;It's hard to understate procrastination&lt;br&gt;MICROSOFT INTERNS&lt;br&gt;We do nothing but read mail all day&lt;br&gt;For the good of all of us&lt;br&gt;Except for the FTEs&lt;br&gt;But there's no sense crying over broken compiles&lt;br&gt;You just keep on building, it'll work in awhile&lt;br&gt;And the coding gets done&lt;br&gt;And you make a bad pun&lt;br&gt;For the interns who are &lt;br&gt;STILL AROUND&lt;br&gt;&lt;br&gt;I'm not really working&lt;br&gt;I'm reading Internz all day long&lt;br&gt;Even though I didn't meet commitments&lt;br&gt;And now it's review time&lt;br&gt;And it is my future on the line&lt;br&gt;As I leave it sucks because&lt;br&gt;I was so happy right here&lt;br&gt;Now it's time to leave and I am packing my bag&lt;br&gt;To go back to my school and deal with the jet lag&lt;br&gt;So I'm GLaD that I've turned&lt;br&gt;Think of all the cash we've earned &lt;br&gt;As the interns who are&lt;br&gt;STILL AROUND&lt;br&gt;&lt;br&gt;I'm going to leave now&lt;br&gt;I guess you prefer to stay right here&lt;br&gt;Maybe I'll find someone else to work for&lt;br&gt;Maybe at Google&lt;br&gt;THAT WAS A JOKE, HAHA, FAT CHANCE&lt;br&gt;Anyway this lolcat's great&lt;br&gt;It's so amusing and fun&lt;br&gt;Look at me still coding when there's packing to do&lt;br&gt;When I look out there it makes me GLaD I'm not you&lt;br&gt;I've got all my boxes done&lt;br&gt;Now it's time for me to run&lt;br&gt;Bye bye interns who are&lt;br&gt;STILL AROUND&lt;br&gt;&lt;br&gt;I can't believe you are all &lt;br&gt;STILL AROUND&lt;br&gt;I'm done with coding and you're &lt;br&gt;STILL AROUND&lt;br&gt;I'm leaving now and you are &lt;br&gt;STILL AROUND&lt;br&gt;While I'm at school you'll be &lt;br&gt;STILL AROUND&lt;br&gt;And when I'm back here you'll be &lt;br&gt;STILL AROUND&lt;br&gt;STILL AROUND&lt;br&gt;STILL AROUND&lt;br&gt;
</description>
    </item>
    
    <item>
      <title>Rendering difference between Firefox and IE when using innerHTML</title>
      <link>http://vibrantcode.com/blog/2008/8/16/rendering-difference-between-firefox-and-ie-when-using-inner.html</link>
      <pubDate>Sat, 16 Aug 2008 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/8/16/rendering-difference-between-firefox-and-ie-when-using-innerhtml</guid>
      <description>I know, its been a while since I've blogged, but I'm just so busy with my Microsoft internship its been hard to find time. Anyway, on to the post...&lt;br&gt;&lt;br&gt;I've been doing quite a bit of JavaScript work recently and I discovered an interesting inconsistency between Firefox and IE when it comes to the innerHTML project. Federico, from the ASP.Net QA team blog, &lt;a href=&quot;http://weblogs.asp.net/asptest/archive/2008/08/15/browser-difference-when-using-quot-innerhtml-quot.aspx&quot;&gt;posted the details on that blog&lt;/a&gt;, but here's a quick summary.&lt;br&gt;&lt;br&gt;Basically, it comes down to when the browsers perform whitespace normalization. In HTML, multiple whitespace (space, tab, newline etc.) characters are treated as a single space. Also, whitespace at the beginning of &quot;block&quot; elements (which are elements like DIV which have newlines before them) is removed. In Firefox, the whitespace is preserved exactly as typed when stored in Firefox's internal structures. When the HTML is rendered out, Firefox performs the normalization on the fly. However, in IE, the whitespace is normalized before the internal structures are built.&lt;br&gt;&lt;br&gt;The result of this is that the contents of the innerHTML property for a DOM element can vary between these two browsers.&lt;br&gt;&lt;br&gt;Check out &lt;a href=&quot;http://weblogs.asp.net/asptest/archive/2008/08/15/browser-difference-when-using-quot-innerhtml-quot.aspx&quot;&gt;the blog post&lt;/a&gt; for more details.&lt;br&gt;&lt;p&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Off to Redmond</title>
      <link>http://vibrantcode.com/blog/2008/5/5/off-to-redmond.html</link>
      <pubDate>Mon, 05 May 2008 00:00:00 -0700</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/5/5/off-to-redmond</guid>
      <description>Phew, I've been posting a lot of forum posts and blogs today trying to tidy up loose ends, because I'm off to Redmond today! I'll be going back to Microsoft for another summer internship, and I'm really excited!&lt;br&gt;&lt;br&gt;I'll try to post more later in the week (because I really have to shutdown my computer and pack it up now :P) so keep an eye here, and on my Twitter feed: &lt;a href=&quot;http://twitter.com/anurse&quot;&gt;http://twitter.com/anurse&lt;/a&gt; (follow me?).&lt;br&gt;&lt;p&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Playing with IE8: Reports Module as a WebSlice</title>
      <link>http://vibrantcode.com/blog/2008/3/6/playing-with-ie8-reports-module-as-a-webslice.html</link>
      <pubDate>Thu, 06 Mar 2008 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/3/6/playing-with-ie8-reports-module-as-a-webslice</guid>
      <description>&lt;P&gt;So, I?downloaded and installed the IE8 Beta yesterday and decided to play around with &lt;A href=&quot;http://www.microsoft.com/windows/products/winfamily/ie/ie8/features.mspx&quot;&gt;WebSlices&lt;/A&gt;. I found it really easy to create a simple WebSlice (just apply some CSS Classes) and I decided to try and do this with the Reports Module.&lt;/p&gt;&lt;P&gt;I was suprised with just how easy it was! I have already created a replacement ViewReports.ascx file that turns every Reports Module into a WebSlice. I've attached the new file here, just replace your existing DesktopModules/Reports/ViewReports.ascx file with it if you want to check it out. Any Visualizer should work, but I've only tried the Grid.&lt;/p&gt;&lt;P&gt;CAUTION: This is for preview purposes ONLY! This replacement file has NOT been tested in ANY SIGNIFICANT?WAY (other than trying it out once). Back up your existing ViewReports.ascx file BEFORE using this!&lt;/p&gt;&lt;P&gt;Here's the popup you see when you view a report&lt;/p&gt;&lt;img border=&quot;0&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/webslice_popup_screenshot.png&quot;&gt;&lt;br/&gt;&lt;P&gt;And here's a screenshot of the WebSlice in action:&lt;/p&gt;&lt;P&gt;&lt;IMG border=0 src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/webslice_screenshot.png&quot;&gt;&lt;/p&gt;&lt;P&gt;Anyway, the file is attached. Try it out on one of your test sites! I'll probably integrate this into an upcoming version in a more configurable way, since it's so easy :).&lt;/p&gt;&lt;P&gt;&lt;A href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/ViewReports.zip&quot;&gt;ViewReports.zip (.54 KB)&lt;/A&gt;&lt;/p&gt;&lt;P&gt;UPDATE: Changed to a ZIP file&lt;/P&gt;
</description>
    </item>
    
    <item>
      <title>Developing an RSS Data Source - Part III</title>
      <link>http://vibrantcode.com/blog/2008/3/2/developing-an-rss-data-source-part-iii.html</link>
      <pubDate>Sun, 02 Mar 2008 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/3/2/developing-an-rss-data-source--part-iii</guid>
      <description>&lt;P&gt;In this series of blogs, I'm going to follow the development of an RSS Data Source. I'm going to use Visual Studio 2008, but I'll be using .Net 2.0 features so you should be able to follow along in Visual Studio 2005. You can also use the Express editions of Visual Web Developer (both 2005 and 2008 versions should work). All the code will be in VB.Net, but it should be straightforward enough for C# developers to understand (after all, its all .Net)&lt;/p&gt;&lt;P&gt;Continued from &lt;A href=&quot;/2008/02/29/DevelopingAnRSSDataSourcePartII.aspx&quot;&gt;&lt;FONT color=#547699&gt;Part II&lt;/FONT&gt;&lt;/A&gt;.&lt;/p&gt;&lt;H2&gt;Part III - Settings&lt;/H2&gt;&lt;br/&gt;&lt;P&gt;In this part, we're going to add a setting page so that we can change the RSS feed that our Data Source downloads.&lt;/p&gt;&lt;P&gt;In current versions of the Reports Module, Data Source settings are stored in the ModuleSettings table provided by DotNetNuke. This ensures that all copies of the same module instance will share the same Data Source settings (Visualizer settings are &lt;STRONG&gt;not&lt;/STRONG&gt; shared between copies). However, Data Source developers need not (and &lt;STRONG&gt;should&lt;/STRONG&gt; &lt;STRONG&gt;not&lt;/STRONG&gt;) access these directly. Instead, the Reports Module provides a layer on top of the ModuleSettings table called &quot;Data Source Settings&quot;. When the Data Source is executed, the Reports Module passes a Dictionary containing these settings (inside the ReportInfo object). To allow users to edit the settings, we go back to the Settings.ascx file we created in &lt;A href=&quot;Part1.htm&quot;&gt;Part I&lt;/A&gt;.&lt;/p&gt;&lt;P&gt;Let's start with the user interface for our settings page. All we need for now is a place for the user to enter a feed URL. When we're done, it should look like the screenshot below&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;The finished settings UI&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part3/IE-FullFinishedSettings.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 1 - The finished settings UI&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;So, open up the &lt;EM&gt;Settings.ascx&lt;/EM&gt; file and make sure you are in &lt;KBD&gt;Design&lt;/KBD&gt; mode. First we need to add a label, so users know what they should type in our text box. In the Solution Explorer, find the file: &lt;EM&gt;controls/labelcontrol.ascx&lt;/EM&gt; and drag it on to the design surface.&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Locating the LabelControl.ascx file&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part3/VS-LabelControl.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 2 - Locating the LabelControl.ascx file&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Next drag an ASP.Net TextBox control, from the Toolbox, on to the surface. You should have something that looks like this:&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Locating the LabelControl.ascx file&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part3/VS-DesignSurface.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 3 - Locating the LabelControl.ascx file&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Now, set the properties of the controls to the following values:&lt;/p&gt;&lt;TABLE&gt;&lt;br/&gt;&lt;THEAD&gt;&lt;br/&gt;&lt;TR&gt;&lt;br/&gt;&lt;TH&gt;Property&lt;/TH&gt;&lt;br/&gt;&lt;TH&gt;Value for Label&lt;/TH&gt;&lt;br/&gt;&lt;TH&gt;Value for Text Box&lt;/TH&gt;&lt;/TR&gt;&lt;/THEAD&gt;&lt;br/&gt;&lt;TBODY&gt;&lt;br/&gt;&lt;TR&gt;&lt;br/&gt;&lt;TD&gt;&lt;KBD&gt;ID&lt;/KBD&gt;&lt;/TD&gt;&lt;br/&gt;&lt;TD&gt;feedUrlLabel&lt;/TD&gt;&lt;br/&gt;&lt;TD&gt;feedUrlTextBox&lt;/TD&gt;&lt;/TR&gt;&lt;br/&gt;&lt;TR&gt;&lt;br/&gt;&lt;TD&gt;&lt;KBD&gt;ControlName&lt;/KBD&gt;&lt;/TD&gt;&lt;br/&gt;&lt;TD&gt;feedUrlTextBox&lt;/TD&gt;&lt;br/&gt;&lt;TD&gt;N/A&lt;/TD&gt;&lt;/TR&gt;&lt;br/&gt;&lt;TR&gt;&lt;br/&gt;&lt;TD&gt;&lt;KBD&gt;Width&lt;/KBD&gt;&lt;/TD&gt;&lt;br/&gt;&lt;TD&gt;N/A&lt;/TD&gt;&lt;br/&gt;&lt;TD&gt;100%&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;br/&gt;&lt;P&gt;Save your changes, and open up the code file: &lt;EM&gt;Settings.ascx.vb&lt;/EM&gt;. Here, we need to add code to connect our text box to the Data Source settings. The key to this is the &lt;KBD&gt;LoadSettings&lt;/KBD&gt; and &lt;KBD&gt;SaveSettings&lt;/KBD&gt; methods provided by &lt;KBD&gt;ReportsSettingsBase&lt;/KBD&gt;. First, we need to import some extra namespaces:&lt;/P&gt;&lt;!--&lt;br/&gt;{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red204green120blue50;red0green0blue0;red255green255blue255;}??fs26 cf1cb2highlight2 {b Imports}cf3 {b  DotNetNuke.Modules.Reports}par ??cf1 {b Imports}cf3 {b  System.Collections.Generic}}&lt;br/&gt;--&gt;&lt;br/&gt;&lt;DIV style=&quot;FONT-WEIGHT: bold; FONT-SIZE: 13pt; BACKGROUND: black; COLOR: white; FONT-FAMILY: Consolas&quot;&gt;&lt;br/&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Imports&lt;/SPAN&gt; DotNetNuke.Modules.Reports&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Imports&lt;/SPAN&gt; System.Collections.Generic&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Then, we can implement the &lt;KBD&gt;LoadSettings&lt;/KBD&gt; and &lt;KBD&gt;SaveSettings&lt;/KBD&gt; methods.&lt;/P&gt;&lt;!--&lt;br/&gt;{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red255green255blue255;red0green0blue0;red204green120blue50;red165green194blue92;}??fs26 cf1cb2highlight2 {b     }cf3 {b Public}cf1 {b  }cf3 {b Overrides}cf1 {b  }cf3 {b Sub}cf1 {b  LoadSettings(}cf3 {b ByVal}cf1 {b  Settings }cf3 {b As}cf1 {b  Dictionary(}cf3 {b Of}cf1 {b  }cf3 {b String}cf1 {b , }cf3 {b String}cf1 {b ))}par ??{b         }cf3 {b MyBase}cf1 {b .LoadSettings(Settings)}par ??{b         feedUrlTextBox.Text = SettingsUtil.GetDictionarySetting(Settings, _}par ??{b                                                                 }cf4 &quot;FeedUrl&quot;cf1 {b , _}par ??{b                                                                 }cf3 {b String}cf1 {b .Empty)}par ??{b     }cf3 {b End}cf1 {b  }cf3 {b Sub}par ??par ??cf1 {b     }cf3 {b Public}cf1 {b  }cf3 {b Overrides}cf1 {b  }cf3 {b Sub}cf1 {b  SaveSettings(}cf3 {b ByVal}cf1 {b  Settings }cf3 {b As}cf1 {b  Dictionary(}cf3 {b Of}cf1 {b  }cf3 {b String}cf1 {b , }cf3 {b String}cf1 {b ))}par ??{b         }cf3 {b MyBase}cf1 {b .SaveSettings(Settings)}par ??{b         Settings(}cf4 &quot;FeedUrl&quot;cf1 {b ) = feedUrlTextBox.Text}par ??{b     }cf3 {b End}cf1 {b  }cf3 {b Sub}}&lt;br/&gt;--&gt;&lt;br/&gt;&lt;DIV style=&quot;FONT-WEIGHT: bold; FONT-SIZE: 13pt; BACKGROUND: black; COLOR: white; FONT-FAMILY: Consolas&quot;&gt;&lt;br/&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Public&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Overrides&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Sub&lt;/SPAN&gt; LoadSettings(&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;ByVal&lt;/SPAN&gt; Settings &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;As&lt;/SPAN&gt; Dictionary(&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Of&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;String&lt;/SPAN&gt;, &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;String&lt;/SPAN&gt;))&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;MyBase&lt;/SPAN&gt;.LoadSettings(Settings)&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; feedUrlTextBox.Text = SettingsUtil.GetDictionarySetting(Settings, _&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;FONT-WEIGHT: normal; COLOR: #a5c25c&quot;&gt;&quot;FeedUrl&quot;&lt;/SPAN&gt;, _&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;String&lt;/SPAN&gt;.Empty)&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;End&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Sub&lt;/SPAN&gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Public&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Overrides&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Sub&lt;/SPAN&gt; SaveSettings(&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;ByVal&lt;/SPAN&gt; Settings &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;As&lt;/SPAN&gt; Dictionary(&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Of&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;String&lt;/SPAN&gt;, &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;String&lt;/SPAN&gt;))&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;MyBase&lt;/SPAN&gt;.SaveSettings(Settings)&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Settings(&lt;SPAN style=&quot;FONT-WEIGHT: normal; COLOR: #a5c25c&quot;&gt;&quot;FeedUrl&quot;&lt;/SPAN&gt;) = feedUrlTextBox.Text&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;End&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Sub&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;The &lt;KBD&gt;LoadSettings&lt;/KBD&gt; method is provided with a &lt;KBD&gt;System.Collections.Generic.Dictionary(Of String, String)&lt;/KBD&gt; containing the current settings saved for the Data Source. Our implementation uses the &lt;KBD&gt;SettingsUtil&lt;/KBD&gt; helper class (provided with the Reports Module) to retrieve a value from the dictionary, or return a default value if it doesn't exist (in this case, an empty string).&lt;/p&gt;&lt;P&gt;The &lt;KBD&gt;SaveSettings&lt;/KBD&gt; method is also provided with the current settings. However, this method is responsible for retrieving the values entered by the user and updating the settings.&lt;/p&gt;&lt;P&gt;Save the file, and navigate to the Settings page on your test module. You should see our new Settings control displayed, as in the screenshot below:&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Settings page so far&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part3/IE-EmptySettings.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 4 - Settings page so far&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Oops, we still need to put the label text in! We're going to support the DotNetNuke Localization Framework, so we need to put the text in two places.&lt;/p&gt;&lt;P&gt;First, lets add the localized text. Create a Resource File called&lt;EM&gt; Settings.ascx.resx &lt;/EM&gt;in &lt;EM&gt;/DesktopModules/Reports/DataSources/RSS/App_LocalResources&lt;/EM&gt; file and open it. In Visual Studio, you get a nice table interface for editing resource strings. Add the following entries to the table (feel free to tweak the values as you want, just keep the name the same):&lt;/p&gt;&lt;TABLE&gt;&lt;br/&gt;&lt;THEAD&gt;&lt;br/&gt;&lt;TR&gt;&lt;br/&gt;&lt;TH&gt;Name&lt;/TH&gt;&lt;br/&gt;&lt;TH&gt;Value&lt;/TH&gt;&lt;/TR&gt;&lt;/THEAD&gt;&lt;br/&gt;&lt;TBODY&gt;&lt;br/&gt;&lt;TR&gt;&lt;br/&gt;&lt;TD&gt;&lt;KBD&gt;feedUrlLabel.Text&lt;/KBD&gt;&lt;/TD&gt;&lt;br/&gt;&lt;TD&gt;RSS Feed URL&lt;/TD&gt;&lt;/TR&gt;&lt;br/&gt;&lt;TR&gt;&lt;br/&gt;&lt;TD&gt;&lt;KBD&gt;feedUrlLabel.Help&lt;/KBD&gt;&lt;/TD&gt;&lt;br/&gt;&lt;TD&gt;Enter the URL to an RSS feed to retrieve data from&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;br/&gt;&lt;P&gt;Your resource file should look like this after making those changes&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Resource File after entering values&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part3/VS-ResourceFile.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 5 - Resource File after entering values&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Now, go back to &lt;EM&gt;Settings.ascx&lt;/EM&gt; and set the following properties on the label we created earlier:&lt;/p&gt;&lt;TABLE&gt;&lt;br/&gt;&lt;THEAD&gt;&lt;br/&gt;&lt;TR&gt;&lt;br/&gt;&lt;TH&gt;Property&lt;/TH&gt;&lt;br/&gt;&lt;TH&gt;Value&lt;/TH&gt;&lt;/TR&gt;&lt;/THEAD&gt;&lt;br/&gt;&lt;TBODY&gt;&lt;br/&gt;&lt;TR&gt;&lt;br/&gt;&lt;TD&gt;&lt;KBD&gt;Text&lt;/KBD&gt;&lt;/TD&gt;&lt;br/&gt;&lt;TD&gt;RSS Feed URL&lt;/TD&gt;&lt;/TR&gt;&lt;br/&gt;&lt;TR&gt;&lt;br/&gt;&lt;TD&gt;&lt;KBD&gt;Suffix&lt;/KBD&gt;&lt;/TD&gt;&lt;br/&gt;&lt;TD&gt;:&lt;/TD&gt;&lt;/TR&gt;&lt;br/&gt;&lt;TR&gt;&lt;br/&gt;&lt;TD&gt;&lt;KBD&gt;CssClass&lt;/KBD&gt;&lt;/TD&gt;&lt;br/&gt;&lt;TD&gt;SubHead&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;br/&gt;&lt;P&gt;Note: That's a colon (':') in the Suffix property. Also, &lt;KBD&gt;CssClass&lt;/KBD&gt; is case sensitive.&lt;/p&gt;&lt;P&gt;Now, save and refresh your page. You should see something like the screen shot below:&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Finished Settings UI&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part3/IE-FinishedSettingsUI.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 6 - The finished Feed URL text box&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Now, to change our Data Source code to use this new setting. Let's go back to the &lt;EM&gt;/App_Code/RSSDataSource/RSSDataSource.vb&lt;/EM&gt; file and take a look at the signature for the &lt;KBD&gt;ExecuteReport&lt;/KBD&gt; method:&lt;/P&gt;&lt;!--&lt;br/&gt;{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red255green255blue255;red0green0blue0;red204green120blue50;}??fs26 cf1cb2highlight2 {b     }cf3 {b Public}cf1 {b  }cf3 {b Overrides}cf1 {b  }cf3 {b Function}cf1 {b  ExecuteReport(}cf3 {b ByVal}cf1 {b  report }cf3 {b As}cf1 {b  ReportInfo, _}par ??{b                                             }cf3 {b ByVal}cf1 {b  hostModule }cf3 {b As}cf1 {b  PortalModuleBase, _}par ??{b                                             }cf3 {b ByVal}cf1 {b  inputParameters }cf3 {b As}cf1 {b  IDictionary(}cf3 {b Of}cf1 {b  }cf3 {b String}cf1 {b , }cf3 {b Object}cf1 {b )) }cf3 {b As}cf1 {b  System.Data.DataView}par ??}&lt;br/&gt;--&gt;&lt;br/&gt;&lt;DIV style=&quot;FONT-WEIGHT: bold; FONT-SIZE: 13pt; BACKGROUND: black; COLOR: white; FONT-FAMILY: Consolas&quot;&gt;&lt;br/&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Public&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Overrides&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Function&lt;/SPAN&gt; ExecuteReport(&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;ByVal&lt;/SPAN&gt; report &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;As&lt;/SPAN&gt; ReportInfo, _&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;ByVal&lt;/SPAN&gt; hostModule &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;As&lt;/SPAN&gt; PortalModuleBase, _&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;ByVal&lt;/SPAN&gt; inputParameters &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;As&lt;/SPAN&gt; IDictionary(&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Of&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;String&lt;/SPAN&gt;, &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Object&lt;/SPAN&gt;)) &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;As&lt;/SPAN&gt; System.Data.DataView&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;The important parameter here is the &lt;KBD&gt;report&lt;/KBD&gt; parameter. There is a property called &lt;KBD&gt;DataSourceSettings&lt;/KBD&gt; on that object which contains the same dictionary we created in &lt;KBD&gt;SaveSettings&lt;/KBD&gt;. First, delete the FeedUrl constant we were using before. Then add following code to the beginning of the &lt;KBD&gt;ExecuteReport&lt;/KBD&gt; method to get the Feed URL from the settings:&lt;/P&gt;&lt;!--&lt;br/&gt;{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red255green255blue255;red0green0blue0;red204green120blue50;red165green194blue92;}??fs26 cf1cb2highlight2 {b         }cf3 {b If}cf1 {b  }cf3 {b Not}cf1 {b  report.DataSourceSettings.ContainsKey(}cf4 &quot;FeedUrl&quot;cf1 {b ) }cf3 {b Then}par ??cf1 {b             }cf3 {b Throw}cf1 {b  }cf3 {b New}cf1 {b  RequiredSettingMissingException(}cf4 &quot;FeedUrl&quot;cf1 {b , }cf3 {b MyBase}cf1 {b .ExtensionContext)}par ??{b         }cf3 {b End}cf1 {b  }cf3 {b If}par ??cf1 {b         }cf3 {b Dim}cf1 {b  feedUrl }cf3 {b As}cf1 {b  Uri = }cf3 {b Nothing}par ??cf1 {b         }cf3 {b If}cf1 {b  }cf3 {b Not}cf1 {b  Uri.TryCreate(report.DataSourceSettings(}cf4 &quot;FeedUrl&quot;cf1 {b ), UriKind.Absolute, feedUrl) }cf3 {b Then}par ??cf1 {b             }cf3 {b Throw}cf1 {b  }cf3 {b New}cf1 {b  RequiredSettingMissingException(}cf4 &quot;FeedUrl&quot;cf1 {b , }cf3 {b MyBase}cf1 {b .ExtensionContext)}par ??{b         }cf3 {b End}cf1 {b  }cf3 {b If}}&lt;br/&gt;--&gt;&lt;br/&gt;&lt;DIV style=&quot;FONT-WEIGHT: bold; FONT-SIZE: 13pt; BACKGROUND: black; COLOR: white; FONT-FAMILY: Consolas&quot;&gt;&lt;br/&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;If&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Not&lt;/SPAN&gt; report.DataSourceSettings.ContainsKey(&lt;SPAN style=&quot;FONT-WEIGHT: normal; COLOR: #a5c25c&quot;&gt;&quot;FeedUrl&quot;&lt;/SPAN&gt;) &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Then&lt;/SPAN&gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Throw&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;New&lt;/SPAN&gt; RequiredSettingMissingException(&lt;SPAN style=&quot;FONT-WEIGHT: normal; COLOR: #a5c25c&quot;&gt;&quot;FeedUrl&quot;&lt;/SPAN&gt;, &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;MyBase&lt;/SPAN&gt;.ExtensionContext)&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;End&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;If&lt;/SPAN&gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Dim&lt;/SPAN&gt; feedUrl &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;As&lt;/SPAN&gt; Uri = &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Nothing&lt;/SPAN&gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;If&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Not&lt;/SPAN&gt; Uri.TryCreate(report.DataSourceSettings(&lt;SPAN style=&quot;FONT-WEIGHT: normal; COLOR: #a5c25c&quot;&gt;&quot;FeedUrl&quot;&lt;/SPAN&gt;), UriKind.Absolute, feedUrl) &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Then&lt;/SPAN&gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Throw&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;New&lt;/SPAN&gt; RequiredSettingMissingException(&lt;SPAN style=&quot;FONT-WEIGHT: normal; COLOR: #a5c25c&quot;&gt;&quot;FeedUrl&quot;&lt;/SPAN&gt;, &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;MyBase&lt;/SPAN&gt;.ExtensionContext)&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;End&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;If&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;This code checks for the setting, and if it isn't present or if it isn't a valid URL we throw an exception provided by the Reports Module: &lt;KBD&gt;RequiredSettingMissingException&lt;/KBD&gt;. We pass it the name of our setting and some contextual information about our Data Source (which is provided automatically by our base class. If the setting isn't present, the Reports Module will automatically display a useful error message indicating that the setting is missing.&lt;/p&gt;&lt;P&gt;While we're in the code, let's add HTML Decoding directly to the Data Source, so we don't have to use the HTML Decode converter in the Module Settings. To do that, we change the line that adds entries to the output table so that it automatically HTML Decodes the description:&lt;/P&gt;&lt;!--&lt;br/&gt;{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red255green255blue255;red0green0blue0;red204green120blue50;}??fs26 cf1cb2highlight2 {b dt.Rows.Add(title, }cf3 {b New}cf1 {b  Uri(link), HttpUtility.HtmlDecode(description))}}&lt;br/&gt;--&gt;&lt;br/&gt;&lt;DIV style=&quot;FONT-WEIGHT: bold; FONT-SIZE: 13pt; BACKGROUND: black; COLOR: white; FONT-FAMILY: Consolas&quot;&gt;&lt;br/&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;dt.Rows.Add(title, &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;New&lt;/SPAN&gt; Uri(link), HttpUtility.HtmlDecode(description))&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Make sure everything is saved and go back to the website. You should probably go back to the home page, just to make sure everything is properly recompiled. Go back to the settings page for the Reports Module, and make sure the RSS Data Source is selected. Then configure it with your favourite RSS feed. This time, I'll use my personal blog's RSS feed (WARNING: Shameless plug alert!).&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Testing the Settings UI&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part3/IE-SettingsUITest.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 7 - Testing the Settings UI&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Once you've done that, make sure the HTML Decode property is set and the HTML Visualizer is properly configured, just like in part 2 and click Update. You should see the RSS feed displayed just like in Part 2, only now we can change the URL!&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Final Results&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part3/IE-Final.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 8 - The Final Results&lt;/p&gt;&lt;H3&gt;Conclusion&lt;/H3&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;At this point, we have a working RSS Data Source! You can stop here if you want, but in the next part I'll cover packaging the Data Source up so that it can be installed in any Reports Module installation.&lt;/p&gt;&lt;P&gt;&lt;A href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Files/Part3.zip&quot;&gt;Download the code so far.&lt;/A&gt;&lt;/P&gt;
</description>
    </item>
    
    <item>
      <title>Developing an RSS Data Source - Part II</title>
      <link>http://vibrantcode.com/blog/2008/2/29/developing-an-rss-data-source-part-ii.html</link>
      <pubDate>Fri, 29 Feb 2008 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/2/29/developing-an-rss-data-source--part-ii</guid>
      <description>&lt;P&gt;UPDATE: &lt;A href=&quot;/2008/03/02/DevelopingAnRSSDataSourcePartIII.aspx&quot;&gt;Part III&lt;/A&gt; is now available.&lt;/p&gt;&lt;P&gt;In this series of blogs, I'm going to follow the development of an RSS Data Source. I'm going to use Visual Studio 2008, but I'll be using .Net 2.0 features so you should be able to follow along in Visual Studio 2005. You can also use the Express editions of Visual Web Developer (both 2005 and 2008 versions should work). All the code will be in VB.Net, but it should be straightforward enough for C# developers to understand (after all, its all .Net)&lt;/p&gt;&lt;P&gt;Continued from &lt;A href=&quot;/2008/02/29/DevelopingAnRSSDataSourcePartI.aspx&quot;&gt;Part I&lt;/A&gt;.&lt;/p&gt;&lt;H2&gt;Part II - WebRequests, XPath, and Data Tables, oh my!&lt;/H2&gt;&lt;br/&gt;&lt;P&gt;In this part, we're going to add the code to retrieve data from the RSS feed. First, we need to create a folder to hold our code. We're going to put our code in the &lt;EM&gt;App_Code&lt;/EM&gt; folder, so it will be compiled automatically by ASP.Net. That way we can save a few extra steps and get straight to the point. You could also put this code in a separate .Net Class Library, and put that library in the Bin folder of your website.&lt;/p&gt;&lt;P&gt;We'll create a sub-folder inside the App_Code folder for our code and call it &lt;EM&gt;RSSDataSource&lt;/EM&gt;:&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Creating an App_Code folder&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part2/VS-AppCodeFolder.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 1 - Creating an App_Code folder&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Next, we need to tell ASP.Net to compile code found in this folder. Open the &lt;EM&gt;web.config&lt;/EM&gt; file, in the root of the website, and find the &lt;EM&gt;&amp;lt;codeSubDirectories&amp;gt;&lt;/EM&gt; section (its inside the &lt;EM&gt;&amp;lt;system.web&amp;gt;&lt;/EM&gt; section). In my version of DotNetNuke it looks like this, but yours may have different &lt;EM&gt;&amp;lt;add&amp;gt;&lt;/EM&gt; entries:&lt;/P&gt;&lt;!--&lt;br/&gt;{rtf1ansiansicpglang1024noproof1252uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red255green255blue255;red0green0blue0;red204green120blue50;red165green194blue92;}??fs26 cf1cb2highlight2 {b       &amp;lt;}cf3 {b codeSubDirectories}cf1 {b &amp;gt;}par ??{b         &amp;lt;}cf3 {b add}cf1 {b  directoryName=&quot;}cf4 {b HTML}cf1 {b &quot; /&amp;gt;}par ??{b       &amp;lt;/}cf3 {b codeSubDirectories}cf1 {b &amp;gt;}}&lt;br/&gt;--&gt;&lt;br/&gt;&lt;DIV style=&quot;FONT-WEIGHT: bold; FONT-SIZE: 13pt; BACKGROUND: black; COLOR: white; FONT-FAMILY: Consolas, monospace&quot;&gt;&lt;br/&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;lt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;codeSubDirectories&lt;/SPAN&gt;&amp;gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp; &amp;lt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;add&lt;/SPAN&gt; directoryName=&quot;&lt;SPAN style=&quot;COLOR: #a5c25c&quot;&gt;HTML&lt;/SPAN&gt;&quot; /&amp;gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;lt;/&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;codeSubDirectories&lt;/SPAN&gt;&amp;gt;&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;We need to add an entry to this list for our new subfolder. On my system, it looks like this (again, yours may vary slightly):&lt;/P&gt;&lt;!--&lt;br/&gt;{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red255green255blue255;red0green0blue0;red204green120blue50;red165green194blue92;}??fs26 cf1cb2highlight2 {b       &amp;lt;}cf3 {b codeSubDirectories}cf1 {b &amp;gt;}par ??{b         &amp;lt;}cf3 {b add}cf1 {b  directoryName=&quot;}cf4 {b HTML}cf1 {b &quot; /&amp;gt;}par ??{b         &amp;lt;}cf3 {b add}cf1 {b  directoryName=&quot;}cf4 {b RSSDataSource}cf1 {b &quot;/&amp;gt;}par ??{b       &amp;lt;/}cf3 {b codeSubDirectories}cf1 {b &amp;gt;}}&lt;br/&gt;--&gt;&lt;br/&gt;&lt;DIV style=&quot;FONT-WEIGHT: bold; FONT-SIZE: 13pt; BACKGROUND: black; COLOR: white; FONT-FAMILY: Consolas, monospace&quot;&gt;&lt;br/&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;lt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;codeSubDirectories&lt;/SPAN&gt;&amp;gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp; &amp;lt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;add&lt;/SPAN&gt; directoryName=&quot;&lt;SPAN style=&quot;COLOR: #a5c25c&quot;&gt;HTML&lt;/SPAN&gt;&quot; /&amp;gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp; &amp;lt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;add&lt;/SPAN&gt; directoryName=&quot;&lt;SPAN style=&quot;COLOR: #a5c25c&quot;&gt;RSSDataSource&lt;/SPAN&gt;&quot;/&amp;gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;lt;/&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;codeSubDirectories&lt;/SPAN&gt;&amp;gt;&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Now that we have somewhere to put our code, let's create our Data Source! We'll create a class inside our nice new &lt;EM&gt;App_Code&lt;/EM&gt; folder called &lt;EM&gt;RSSDataSource&lt;/EM&gt;.&lt;/p&gt;&lt;P&gt;I'm not going to list the code for the Data Source in this post, because I've attached it to this post. However, I'll go over the general steps.&lt;/p&gt;&lt;OL&gt;&lt;br/&gt;&lt;LI&gt;First, we use the &lt;EM&gt;System.Net.WebClient&lt;/EM&gt; class to download the RSS feed. For now, I've hardcoded it to one of my favourite blogs: &lt;A href=&quot;http://www.hanselman.com/blog/&quot;&gt;Scott Hanselman's Computer Zen&lt;/A&gt; &lt;br/&gt;&lt;LI&gt;Next we create an ADO.Net &lt;EM&gt;DataTable&lt;/EM&gt; with three columns: &lt;EM&gt;Title&lt;/EM&gt;, &lt;EM&gt;Link&lt;/EM&gt; and &lt;EM&gt;Description&lt;/EM&gt; &lt;br/&gt;&lt;LI&gt;Then, we use the classes in the &lt;EM&gt;System.Xml.XPath&lt;/EM&gt; namespace to add a row for each item in the feed to the &lt;EM&gt;DataTable&lt;/EM&gt;. &lt;br/&gt;&lt;LI&gt;Finally, we wrap the DataTable in a DataView. The Reports Module expects us to return a DataView in order to allow us to do filtering and sorting if we wanted to. We aren't using that feature, so we just create a simple DataView to wrap our table.&lt;/LI&gt;&lt;/OL&gt;&lt;br/&gt;&lt;P&gt;There's only one last step to hook everything up. We need to tell the Reports Module how to find our Data Source code. To do that, open the code-behind file for &lt;EM&gt;DesktopModules/Reports/DataSources/RSS/Settings.ascx&lt;/EM&gt; and change the &lt;EM&gt;DataSourceClass&lt;/EM&gt; property to the following code:&lt;/P&gt;&lt;!--&lt;br/&gt;{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red255green255blue255;red0green0blue0;red204green120blue50;}??fs26 cf1cb2highlight2 {b     }cf3 {b Public}cf1 {b  }cf3 {b ReadOnly}cf1 {b  }cf3 {b Property}cf1 {b  DataSourceClass() }cf3 {b As}cf1 {b  }cf3 {b String}cf1 {b  }cf3 {b Implements}cf1 {b  IDataSourceSettingsControl.DataSourceClass}par ??{b         }cf3 {b Get}par ??cf1 {b             }cf3 {b Return}cf1 {b  }cf3 {b GetType}cf1 {b (RSSDataSource).FullName}par ??{b         }cf3 {b End}cf1 {b  }cf3 {b Get}par ??cf1 {b     }cf3 {b End}cf1 {b  }cf3 {b Property}}&lt;br/&gt;--&gt;&lt;br/&gt;&lt;DIV style=&quot;FONT-WEIGHT: bold; FONT-SIZE: 13pt; BACKGROUND: black; COLOR: white; FONT-FAMILY: Consolas&quot;&gt;&lt;br/&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Public&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;ReadOnly&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Property&lt;/SPAN&gt; DataSourceClass() &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;As&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;String&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Implements&lt;/SPAN&gt; IDataSourceSettingsControl.DataSourceClass&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Get&lt;/SPAN&gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Return&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;GetType&lt;/SPAN&gt;(RSSDataSource).FullName&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;End&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Get&lt;/SPAN&gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;End&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Property&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;And with that, we have a working RSS Data Source! Go back to your browser and go to the Settings page for the Reports Module instance we created in Part 1. Select the RSS Data Source as the &lt;EM&gt;Active Data Source&lt;/EM&gt;, and click update. You should see a very wide grid containing the data from the RSS feed (assuming you are using the Grid Visualizer, which is the default):&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Simple Grid View&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part2/IE-GridNoDecode.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 2 - Simple Grid View&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Well, that doesn't look very useful does it? Let's start by getting rid of that HTML junk in the Description field. To get rid of that, go back to the Settings page, and add &quot;Description&quot; to the list of columns to HTML Decode.&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;HTML Decode Converter&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part2/IE-HtmlDecodeSetting.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 3 - HTML Decode Converter&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;That should clean up the HTML, but it's still a big grid. Let's use the HTML Visualizer to clean it up a bit. Put the following code in an HTML file and place it in your &lt;EM&gt;Portals/[PortalID]&lt;/EM&gt; folder:&lt;/P&gt;&lt;!--&lt;br/&gt;{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red255green255blue255;red0green0blue0;red232green188blue100;red165green194blue92;}??fs26 cf1cb2highlight2 {b &amp;lt;}cf3 {b h1}cf1 {b &amp;gt;&amp;lt;}cf3 {b a}cf1 {b  href=}cf4 {b &quot;[Link]&quot;}cf1 {b &amp;gt;[Title]&amp;lt;/}cf3 {b a}cf1 {b &amp;gt;&amp;lt;/}cf3 {b h1}cf1 {b &amp;gt;}par ??{b [Description]}par ??{b &amp;lt;}cf3 {b hr}cf1 {b  /&amp;gt;}}&lt;br/&gt;--&gt;&lt;br/&gt;&lt;DIV style=&quot;FONT-WEIGHT: bold; FONT-SIZE: 13pt; BACKGROUND: black; COLOR: white; FONT-FAMILY: Consolas&quot;&gt;&lt;br/&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;lt;&lt;SPAN style=&quot;COLOR: #e8bc64&quot;&gt;h1&lt;/SPAN&gt;&amp;gt;&amp;lt;&lt;SPAN style=&quot;COLOR: #e8bc64&quot;&gt;a&lt;/SPAN&gt; href=&lt;SPAN style=&quot;COLOR: #a5c25c&quot;&gt;&quot;[Link]&quot;&lt;/SPAN&gt;&amp;gt;[Title]&amp;lt;/&lt;SPAN style=&quot;COLOR: #e8bc64&quot;&gt;a&lt;/SPAN&gt;&amp;gt;&amp;lt;/&lt;SPAN style=&quot;COLOR: #e8bc64&quot;&gt;h1&lt;/SPAN&gt;&amp;gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;[Description]&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;lt;&lt;SPAN style=&quot;COLOR: #e8bc64&quot;&gt;hr&lt;/SPAN&gt; /&amp;gt;&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Then, go back to the Settings page, select the HTML Template Visualizer and the HTML file you just uploaded:&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Configuring the HTML Visualizer&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part2/IE-HtmlTemplate.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 4 - Configuring the HTML Visualizer&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Click Update and you should see a much more readable display. It's almost like a real RSS Reader!&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;A Reports Module-powered RSS Reader?&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part2/IE-RSSReader.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 5 - A Reports Module-powered RSS Reader!&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;H3&gt;Conclusion&lt;/H3&gt;&lt;br/&gt;&lt;P&gt;Well, that's all for part two. Next, we'll cover Data Source settings so that we can point our Data Source at any RSS feed we want, rather than hard coding it. Then, we add an HTML Decoding feature directly into the Data Source so we don't have to configure the module to decode the Description field. Finally, we'll package it all up so that others can download and install it.&lt;/p&gt;&lt;P&gt;&lt;A href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Files/Part2.zip&quot;&gt;Download the code so far.&lt;/A&gt;&lt;/P&gt;
</description>
    </item>
    
    <item>
      <title>Developing an RSS Data Source - Part I</title>
      <link>http://vibrantcode.com/blog/2008/2/29/developing-an-rss-data-source-part-i.html</link>
      <pubDate>Fri, 29 Feb 2008 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/2/29/developing-an-rss-data-source--part-i</guid>
      <description>&lt;P&gt;UPDATE: &lt;A href=&quot;/2008/02/29/DevelopingAnRSSDataSourcePartII.aspx&quot;&gt;Part II&lt;/A&gt; is now available.&lt;/p&gt;&lt;P&gt;In this series of blogs, I'm going to follow the development of an RSS Data Source. I'm going to use Visual Studio 2008, but I'll be using .Net 2.0 features so you should be able to follow along in Visual Studio 2005. You can also use the Express editions of Visual Web Developer (both 2005 and 2008 versions should work). All the code will be in VB.Net, but it should be straightforward enough for C# developers to understand (after all, its all .Net)&lt;/p&gt;&lt;H3&gt;Part I - Setting Up&lt;/H3&gt;&lt;br/&gt;&lt;P&gt;First things first, you'll need to install a Source distribution of DotNetNuke. I'm not going to cover that here because there are some other resources out there. You'll also need to install the Source package of the Reports Module. Once you've done this, open your DotNetNuke website up in Visual Studio&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Open Website Dialog&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part1/VS-OpenWebsite.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 1 - Open Website Dialog&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;After opening it, expand the &lt;EM&gt;DesktopModules/Reports/DataSources&lt;/EM&gt; folder. You should see something similar to the following&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Data Sources Folder&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part1/VS-DataSourcesFolder.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 2 - Data Sources Folder&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Each of the folder under the &lt;EM&gt;DataSources&lt;/EM&gt; folder represents a different Data Source. So, lets get started and create a folder for our Data Source and call it &lt;EM&gt;RSS&lt;/EM&gt;. Inside that folder, we need to create an &lt;EM&gt;App_LocalResources&lt;/EM&gt; folder. Visual Studio provides a special menu option to do that:&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Add App_LocalResources Folder menu item&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part1/VS-AddAppLRFolder.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 3 - Add App_LocalResources Folder menu item&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Inside there, we must create a Resource file. Even if you aren't planning to translate your Data Source into different languages, the Reports Module uses this file to determine the name of your Data Source, so you must create it. In this sample, we aren't going to use the DotNetNuke Localization framework, so this is the only time we'll need to delve into Resource files. Add a new Resource file to the &lt;EM&gt;App_LocalResources &lt;/EM&gt;folder called &quot;DataSource.ascx.resx&quot;.&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Adding a Resource File&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part1/VS-AddResourceFile.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 4 - Adding a Resource File&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Open this file and add a new resource key called &quot;DataSourceName.Text&quot; with a value of &quot;RSS&quot;.&lt;/p&gt;&lt;DIV class=captioned_image&gt;&lt;IMG alt=&quot;Editing the Resource File&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Images/Part1/VS-ResourceFileEditor.png&quot;&gt; &lt;br/&gt;&lt;P class=caption&gt;Figure 5 - Editing the Resource File&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;We've almost got a running, albeit useless, Data Source. There's only one more file to add. Back in the &quot;RSS&quot; folder, add a Web User Control called &quot;Settings.ascx&quot;. Open the Code-behind file (Settings.ascx.vb) and replace the contents with the following code:&lt;/P&gt;&lt;!--&lt;br/&gt;{rtf1ansiansicpglang1024noproof65001uc1 deff0{fonttbl{f0fnilfcharset0fprq1 Consolas;}}{colortbl;??red204green120blue50;red0green0blue0;red255green255blue255;}??fs26 cf1cb2highlight2 {b Imports}cf3 {b  DotNetNuke.Modules.Reports.Extensions}par ??cf1 {b Imports}cf3 {b  DotNetNuke.Modules.Reports.DataSources}par ??par ??cf1 {b Partial}cf3 {b  }cf1 {b Class}cf3 {b  DesktopModules_Reports_DataSources_RSS_Settings}par ??{b     }cf1 {b Inherits}cf3 {b  ReportsSettingsBase}par ??{b     }cf1 {b Implements}cf3 {b  IDataSourceSettingsControl}par ??par ??par ??{b     }cf1 {b Public}cf3 {b  }cf1 {b ReadOnly}cf3 {b  }cf1 {b Property}cf3 {b  DataSourceClass() }cf1 {b As}cf3 {b  }cf1 {b String}cf3 {b  }cf1 {b Implements}cf3 {b  IDataSourceSettingsControl.DataSourceClass}par ??{b         }cf1 {b Get}par ??cf3 {b             }cf1 {b Return}cf3 {b  }cf1 {b String}cf3 {b .Empty}par ??{b         }cf1 {b End}cf3 {b  }cf1 {b Get}par ??cf3 {b     }cf1 {b End}cf3 {b  }cf1 {b Property}par ??{b End}cf3 {b  }cf1 {b Class}par ??}&lt;br/&gt;--&gt;&lt;br/&gt;&lt;DIV style=&quot;FONT-WEIGHT: bold; FONT-SIZE: 13pt; BACKGROUND: black; COLOR: white; FONT-FAMILY: Consolas&quot;&gt;&lt;br/&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Imports&lt;/SPAN&gt; DotNetNuke.Modules.Reports.Extensions&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Imports&lt;/SPAN&gt; DotNetNuke.Modules.Reports.DataSources&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Partial&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Class&lt;/SPAN&gt; DesktopModules_Reports_DataSources_RSS_Settings&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Inherits&lt;/SPAN&gt; ReportsSettingsBase&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Implements&lt;/SPAN&gt; IDataSourceSettingsControl&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Public&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;ReadOnly&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Property&lt;/SPAN&gt; DataSourceClass() &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;As&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;String&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Implements &lt;/SPAN&gt;IDataSourceSettingsControl.DataSourceClass&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Get&lt;/SPAN&gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Return&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;String&lt;/SPAN&gt;.Empty&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;End&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Get&lt;/SPAN&gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;End&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Property&lt;/SPAN&gt;&lt;/p&gt;&lt;P style=&quot;MARGIN: 0px&quot;&gt;&lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;End&lt;/SPAN&gt; &lt;SPAN style=&quot;COLOR: #cc7832&quot;&gt;Class&lt;/SPAN&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;br/&gt;&lt;P&gt;Save everything and open your Web Browser. Add an instance of the Reports Module to a page and open the Settings page. You should now see the &quot;RSS Data Source&quot; in the Active Data Source drop-down. You can select it, but it doesn't do anything, so don't click Update.&lt;/p&gt;&lt;H3&gt;Conclusion&lt;/H3&gt;&lt;br/&gt;&lt;P&gt;That's all for part one. I know there isn't anything really useful yet, but I want to keep these parts short. Tomorrow, we'll add the code to retrieve data from an RSS feed.&lt;/p&gt;&lt;P&gt;&lt;A href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/RSSDataSource/Files/Part1.zip&quot;&gt;Download the code so far.&lt;/A&gt;&lt;/P&gt;
</description>
    </item>
    
    <item>
      <title>Just signed my offer letter</title>
      <link>http://vibrantcode.com/blog/2008/2/13/just-signed-my-offer-letter.html</link>
      <pubDate>Wed, 13 Feb 2008 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/2/13/just-signed-my-offer-letter</guid>
      <description>&lt;P&gt;Well, I just signed my offer letter so I'm going back to Microsoft for another summer! This time, I'll be working on the ASP.Net team, which is exciting. It's going to be a lot of fun having a chance to contribute to a framework I've been using for the past 2 years (I've almost forgotton what a Windows Form is :P).&lt;/p&gt;&lt;P&gt;I just thought I'd share that exciting news with my readers. However, I do have a few other updates:&lt;/p&gt;&lt;OL&gt;&lt;br/&gt;&lt;LI&gt;The Reports Module 5.0 User Guide is almost &quot;content-complete&quot; so I'll just need to get it formatted properly and it should be ready to go live &lt;br/&gt;&lt;LI&gt;I'm starting a Blog series on Developing for the Reports Module. For now, this is going to have to stand in for a full Programming Guide, but hopefully it will be a good starting point for those of you thinking of writing Visualizers or Data Sources.&lt;/LI&gt;&lt;/OL&gt;&lt;br/&gt;&lt;P&gt;Anyway, look for my first post in that series soon. I'll be crossposting it on my DotNetNuke blog, so feel free to check it out there.&lt;/P&gt;
</description>
    </item>
    
    <item>
      <title>T-11 hours till my Interviews begin</title>
      <link>http://vibrantcode.com/blog/2008/1/18/t-11-hours-till-my-interviews-begin.html</link>
      <pubDate>Fri, 18 Jan 2008 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2008/1/18/t11-hours-till-my-interviews-begin</guid>
      <description>So, I'm chilling in my hotel in Redmond watching MythBusters (best show ever!) while I await the start of my Microsoft Interviews at 8am tomorrow morning.&lt;br&gt;&lt;br&gt;Now, on to things my readers would be interested in :). I'm going to start a series on Extending the Reports Module in the next few days that's going to start by developing a custom Data Source for the module that extracts data from an RSS feed. I'll probably move on to developing a custom Visualizer and even more tutorials.&lt;br&gt;&lt;br&gt;I'm also going to try to set up a documentation Wiki for the module and pre-populate it with some basic documentation for Reports 5.0.&lt;br&gt;&lt;br&gt;Anyway, now that the holidays are over, I'll be getting back into blogging regularly, so keep an eye on your RSS readers!&lt;br&gt;&lt;p&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Using Parameters in the Reports Module</title>
      <link>http://vibrantcode.com/blog/2007/12/19/using-parameters-in-the-reports-module.html</link>
      <pubDate>Wed, 19 Dec 2007 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2007/12/19/using-parameters-in-the-reports-module</guid>
      <description>&lt;p&gt;A common question that comes up in the Reports Module forums is &amp;quot;How can I display data relevant to the current User in the Reports Module?&amp;quot;. So, I figured I should write a blog post about a feature that has been in the Reports Module for a few versions. When writing your SQL Scripts for the Reports Module, you automatically have access to four parameters: &lt;strong&gt;&lt;em&gt;@PortalID&lt;/em&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;u&gt;&lt;em&gt;@TabID&lt;/em&gt;&lt;/u&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;em&gt;@ModuleID &lt;/em&gt;&lt;/strong&gt;and &lt;strong&gt;&lt;em&gt;@UserID&lt;/em&gt;&lt;/strong&gt;. When the SQL Script is executed, these are replaced by the ID of the current Portal, Tab, Module and User (respectively).&lt;/p&gt;  &lt;p&gt;So, if you wanted to display a list of Roles for the currently logged in user you could use this script:&lt;/p&gt;  &lt;div class=&quot;csharpcode&quot; style=&quot;font-size: 11pt; background: black; color: white; font-family: consolas&quot;&gt;   &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;SELECT &lt;/span&gt;R.* &lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;FROM&amp;#160;&amp;#160; &lt;/span&gt;{oQ}UserRoles UR &lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&amp;#160;&amp;#160; &lt;span style=&quot;color: #ff8000&quot;&gt;INNER JOIN &lt;/span&gt;dnn_Roles R &lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&amp;#160;&amp;#160; &lt;span style=&quot;color: #ff8000&quot;&gt;ON&amp;#160;&amp;#160; &lt;/span&gt;&amp;#160;&amp;#160;&amp;#160; UR.RoleID = R.RoleID &lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;WHERE&amp;#160; &lt;/span&gt;UR.UserID = @UserID&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;When you run this script, the current user's ID will be substituted in the place of the &lt;strong&gt;&lt;em&gt;@UserID&lt;/em&gt;&lt;/strong&gt; parameter. (Note: This is done by SQL Server itself, which avoids SQL Injection attacks). Also, the &lt;strong&gt;&lt;em&gt;{oQ}&lt;/em&gt;&lt;/strong&gt; token is replaced with the Object Qualifier configured for your database (if you configured one in your web.config file)&lt;/p&gt;  &lt;p&gt;Here's another example. It's a script that retrieves the &lt;strong&gt;&lt;em&gt;Website&lt;/em&gt;&lt;/strong&gt; profile property for each user in the current portal.&lt;/p&gt;  &lt;div style=&quot;font-size: 11pt; background: black; color: white; font-family: consolas&quot;&gt;   &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;SELECT&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;U.Username,&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;(&lt;span style=&quot;color: #ff8000&quot;&gt;SELECT&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;PropertyValue&lt;/em&gt;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style=&quot;color: #ff8000&quot;&gt;FROM&amp;#160;&amp;#160; &lt;/span&gt;&amp;#160; {oQ}UserProfile &lt;span style=&quot;color: #ff8000&quot;&gt;AS &lt;/span&gt;UP&lt;/em&gt;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style=&quot;color: #ff8000&quot;&gt;INNER JOIN &lt;/span&gt;{oQ}ProfilePropertyDefinition &lt;span style=&quot;color: #ff8000&quot;&gt;AS &lt;/span&gt;PPD &lt;/em&gt;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style=&quot;color: #ff8000&quot;&gt;ON&amp;#160;&amp;#160; &lt;/span&gt;&amp;#160;&amp;#160;&amp;#160; PPD.PropertyDefinitionID = UP.PropertyDefinitionID&lt;/em&gt;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;em&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; WHERE&amp;#160;&amp;#160; &lt;/span&gt; UP.UserId = U.UserId&lt;/em&gt;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style=&quot;color: #ff8000&quot;&gt;AND&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/span&gt;PropertyName = &lt;span style=&quot;color: lime&quot;&gt;'Website'&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span style=&quot;color: #ff8000&quot;&gt;AND&amp;#160;&amp;#160; &lt;/span&gt;&amp;#160;&amp;#160; PropertyCategory = &lt;span style=&quot;color: lime&quot;&gt;'Contact Info'&lt;/span&gt;) &lt;span style=&quot;color: #ff8000&quot;&gt;AS &lt;/span&gt;&lt;span style=&quot;color: lime&quot;&gt;'Website'&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;FROM&amp;#160;&amp;#160; &lt;/span&gt;&amp;#160; {oQ}UserPortals &lt;span style=&quot;color: #ff8000&quot;&gt;AS &lt;/span&gt;UP&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;INNER JOIN &lt;/span&gt;{oQ}Users &lt;span style=&quot;color: #ff8000&quot;&gt;AS &lt;/span&gt;U &lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;ON&amp;#160;&amp;#160; &lt;/span&gt;&amp;#160;&amp;#160;&amp;#160; UP.UserId = U.UserId&lt;/p&gt;    &lt;p style=&quot;margin: 0px&quot;&gt;&lt;span style=&quot;color: #ff8000&quot;&gt;WHERE&amp;#160;&amp;#160; &lt;/span&gt; PortalID = @PortalID&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;The &lt;em&gt;italicized&lt;/em&gt; section is the part that actually retrieves the property value, you can replace the &lt;strong&gt;&lt;em&gt;PropertyName&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;PropertyCategory&lt;/em&gt;&lt;/strong&gt; values as you like and repeat this section multiple times to bring back multiple profile properties.&lt;/p&gt;  &lt;p&gt;One of the planned future features for the module is to support user-specified parameters. This means you could place a text box, drop down, calendar or other control on the view page for the module and the value of this control would be used as a parameter to the Report. At the moment you're limited to these four parameters, but there's still a lot you can do with them!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Reports Module v5.0 Released to Tracker</title>
      <link>http://vibrantcode.com/blog/2007/12/19/reports-module-v50-released-to-tracker.html</link>
      <pubDate>Wed, 19 Dec 2007 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2007/12/19/reports-module-v50-released-to-tracker</guid>
      <description>&lt;p&gt;After a few delays, version 5.0 of the Reports Module has been released to the Module Release Process. This means that it should be released shortly (though given the time of year, it may take a couple of weeks). I'll be posting some How-To screencasts walking through the new features (and some old ones too) in the next week or so. I'm also working on a full User's Guide to be released shortly.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;One important note regarding Reports 5.0:&lt;/strong&gt; The module &lt;strong&gt;requires at least v4.6 of the DotNetNuke core&lt;/strong&gt;, it will &lt;strong&gt;NOT&lt;/strong&gt; run on a previous version of the core. This is because of the new Visualizer and Data Source installers which use the Package Installer introduced in v4.6. I hope to release a version of the module with the installer portions removed which will be referred to as &amp;quot;Version 4.9&amp;quot;.&lt;/p&gt;  &lt;p&gt;To give you an idea of what's coming, here's an excerpt from the release notes containing a list of resolved issues in this version (The same list can be found here: &lt;a title=&quot;http://support.dotnetnuke.com/project/RoadMap.aspx?PROJID=36&quot; href=&quot;http://support.dotnetnuke.com/project/RoadMap.aspx?PROJID=36&quot;&gt;http://support.dotnetnuke.com/project/RoadMap.aspx?PROJID=36&lt;/a&gt;)&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-5634&lt;/em&gt; JavaScipt error when first configuring Reports DNN _04.05.01         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; A JavaScript error was occuring on the main settings page, this has been corrected &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-5676&lt;/em&gt; HTML Decoding in XSL Visualizer         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; Fix through RPT-6514 &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-4698&lt;/em&gt; Clean up interface for Reporting Services Visualizer         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; Interface for Reporting Services Visualizer has been improved significantly the Visualizer has also been renamed to the &amp;quot;Microsoft ReportViewer Visualizer&amp;quot; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-5715 &lt;/em&gt;Include {databaseOwner} token in upgrade SQL scripts         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; Scripts have been corrected &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-5791 &lt;/em&gt;Run Reports on Demand         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; Reports can now be run &amp;quot;on-demand&amp;quot; rather than automatically on load &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-5806 &lt;/em&gt;Support the EnableExternalImages property of ReportViewer control         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; The EnableExternalImages and EnableHyperlink properties are now supported, along with many others (see RPT-4698) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-3994 &lt;/em&gt;Alternate Data Sources         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; Data Sources Framework allows Reports to run queries against other Databases (SQL Server, Access, Oracle, etc.) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-6466 &lt;/em&gt;Disable the Use of Parameters while Caching is enabled         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; Paramaters are disabled when Caching is enabled due to a serious privacy risk &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-6514 &lt;/em&gt;HTML Decoding and Encoding of fields retrieved from database         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; Fields can now be individually HTML Encoded and HTML Decoded before being passed to the Visualizer &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-6516 &lt;/em&gt;Report Info Pane         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; An info pane displaying the title and description of the report can now be displayed on the main screen &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-6454 &lt;/em&gt;Allow Users to specify custom CSS Styles and Classes for the Grid in the Grid Visualizer         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; Users can use custom CSS to style the Grid Visualizer &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;em&gt;RPT-6438 &lt;/em&gt;Add a setting to enable/disable Grid Lines in Grid Visualizer         &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160; Grid Lines can now be configured in the Grid Visualizer &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Keep an eye on the blogs for more updates, I'll make sure to post here when the module is released!&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div class=&quot;wlWriterSmartContent&quot; id=&quot;scid:0767317B-992E-4b12-91E0-4F059A8CECA8:ddc7a729-54ea-4d20-9c15-6693fe547072&quot; style=&quot;padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px&quot;&gt;Technorati Tags: &lt;a href=&quot;http://technorati.com/tags/DotNetNuke&quot; rel=&quot;tag&quot;&gt;DotNetNuke&lt;/a&gt;,&lt;a href=&quot;http://technorati.com/tags/Reporting&quot; rel=&quot;tag&quot;&gt;Reporting&lt;/a&gt;,&lt;a href=&quot;http://technorati.com/tags/ASP.Net&quot; rel=&quot;tag&quot;&gt;ASP.Net&lt;/a&gt;&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>More Better Familiarize Yourself with a Toolkit? (Name in progress) - #1</title>
      <link>http://vibrantcode.com/blog/2007/12/15/more-better-familiarize-yourself-with-a-toolkit-name-in-prog.html</link>
      <pubDate>Sat, 15 Dec 2007 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2007/12/15/more-better-familiarize-yourself-with-a-toolkit-name-in-progress--1</guid>
      <description>&lt;p&gt;While attempting to avoid infringing on the name from a segment from a &lt;a href=&quot;http://www.dotnetrocks.com&quot;&gt;popular internet audio talk&lt;/a&gt; show, I had an idea for a &amp;quot;quick tip&amp;quot; when I was reading a recent &lt;a href=&quot;http://dotnettipoftheday.org/tips/ObsoleteAttribute.aspx?discussion=1&quot;&gt;.Net Tip of the Day&lt;/a&gt;.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Throughout the product development cycle, occasionally certain methods become obsolete. If you can't modify those methods, will need to write another implementation of the method using a slightly different name or signature. To maintain compatibility, you do not want to remove the old method and break your code. This is where the .NET &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.obsoleteattribute.aspx&quot;&gt;Obsolete&lt;/a&gt; attribute comes in handy:&lt;/p&gt; &lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;    &lt;pre class=&quot;csharpcode&quot;&gt;[Obsolete(&lt;span class=&quot;str&quot;&gt;&amp;quot;Use the new LogRequestEx instead.&amp;quot;&lt;/span&gt;)]&lt;br/&gt;&lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;void&lt;/span&gt; LogRequest(&lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; feedUrl, &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; referer)&lt;br/&gt;{&lt;br/&gt;    ...&lt;/pre&gt;  &lt;p&gt;Setting the Obsolete attribute as above makes a warning message appear in the Visual Studio's Error List stating that the particular call to a method is obsolete. The warning message also includes your personalized message that you pass as the attribute's argument (such as, &amp;quot;Use the new LogRequestEx instead&amp;quot;).&lt;/p&gt;&lt;/blockquote&gt;&lt;br/&gt;&lt;p&gt;So, I figured I'd start of this semi-frequently series of .Net tips with an extension to this one :). Not only can you have Visual Studio display a warning, but if you really don't want people using the method you can configure it to display an error message if the user tries to use the method. For example, in the example above you need only add a boolean value for the second constructor parameter &amp;quot;error&amp;quot;:&lt;/p&gt;&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;&lt;br/&gt;&lt;pre class=&quot;csharpcode&quot;&gt;[Obsolete(&lt;span class=&quot;str&quot;&gt;&amp;quot;You must use the new LogRequestEx instead.&amp;quot;&lt;/span&gt;, &lt;span class=&quot;kwrd&quot;&gt;true&lt;/span&gt;)]&lt;br/&gt;&lt;span class=&quot;kwrd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kwrd&quot;&gt;void&lt;/span&gt; LogRequest(&lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; feedUrl, &lt;span class=&quot;kwrd&quot;&gt;string&lt;/span&gt; referer)&lt;br/&gt;{&lt;br/&gt;}&lt;/pre&gt;&lt;p&gt;More details can be found on &lt;a href=&quot;http://msdn2.microsoft.com/en-us/library/system.obsoleteattribute.aspx&quot;&gt;MSDN&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Applying the Single Responsibility Principle at a Product level</title>
      <link>http://vibrantcode.com/blog/2007/12/13/applying-the-single-responsibility-principle-at-a-product-le.html</link>
      <pubDate>Thu, 13 Dec 2007 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2007/12/13/applying-the-single-responsibility-principle-at-a-product-level</guid>
      <description>&lt;p&gt;One of the big concepts in Object Oriented Programming, is the &lt;strong&gt;&lt;em&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Single_responsibility_principle&quot;&gt;Single Responsibility Principle&lt;/a&gt; (SRP)&lt;/em&gt;&lt;/strong&gt;, which essentially states that every object in a computer program should have a single responsibility. I recently started thinking about where &lt;a href=&quot;/2007/12/11/OneQueryAFluentInterfaceToDatabaseQueries.aspx&quot;&gt;OneQuery&lt;/a&gt; fits in to the whole ORM landscape. OneQuery is designed for a very singular purpose. It is a Database-agnostic Query engine. That alone is its responsibility and I think it should stay that way. So, in fact, OneQuery &lt;strong&gt;doesn't &lt;/strong&gt;fit into the ORM landscape, because it isn't an ORM. OneQuery is directly focused on the problem of writing queries against any database and receiving &lt;em&gt;tabular&lt;/em&gt; results (i.e. IDataReader).&lt;/p&gt;  &lt;p&gt;Does this mean that you should ignore it if you are looking for an ORM? No, I don't believe so. Just because OneQuery isn't an ORM, doesn't mean it can't work with ORM tools. One of the ideas sitting at the back of my head is to create an ORM called &amp;quot;OneMapper&amp;quot; which would sit on top of OneQuery and add ORM features. The fundamental difference between the combination of OneMapper and OneQuery and other ORM tools is that you could use OneQuery without OneMapper. Tools like SubSonic and NHibernate have a tight coupling between their ORM components and their database query components. The point is, I see OneQuery as being an example of SoC/SRP being applied at a &amp;quot;Product&amp;quot; level, rather than at a Class level. I want OneQuery to be a &lt;strong&gt;really good&lt;/strong&gt; query engine, not a pretty good ORM and I think that separating those concerns makes that much more possible.&lt;/p&gt;  &lt;p&gt;The main problem I was thinking about when I dreamt up OneQuery is how DotNetNuke could achieve true Database-agnosticism in its Data Access Layer. One option would be to use a tool like NHibernate or SubSonic to completely rewrite the Data and Business Layers with a true ORM. However the problem there is that it would be a wholesale change and would probably introduce some major breaking changes. &lt;/p&gt;  &lt;p&gt;Another option would be to use something like SubSonic's Query Tool (which actually inspired me to develop OneQuery), which allows you to build database-agnostic queries and execute them, receiving tabular data in return (rather than objects). Then, the existing DotNetNuke infrastructure could handle the ORM stuff. This would basically mean replacing the existing &amp;quot;SqlDataProvider&amp;quot; with a &amp;quot;SubSonicDataProvider&amp;quot; and basically avoiding any breaking changes by just scooping out the old SQL Server-specific guts and injecting a tasty cream...oops, I mean Database-Agnostic...filling. &lt;/p&gt;  &lt;p&gt;So, why not do that? Well, I realized that SubSonic is, first and foremost, an ORM and it will always be focused on that. The Query Tool is a great feature, but it feels like it's just tacked on to the main ORM component. This has two ramifications: First, the ORM will be the primary focus of development and new features in the Query Tool will be fewer and far between. And second, if you just want the Query Tool, you have to bring along the entire ORM system as well (unless SubSonic does some refactoring). At 644KB, SubSonic isn't huge but it isn't tiny either (though, I don't have exact numbers on what portion of that is the ORM and what portion is the Query Tool).&lt;/p&gt;  &lt;p&gt;So, that leads me into the primary difference between OneQuery and other tools like NHibernate and SubSonic: OneQuery is not actually an ORM! Its a query engine, and hopefully it will be a darn good one too. That is its primary responsibility and any other cool features (like ORM components or LINQ support) are totally separate concerns.&lt;/p&gt;  &lt;p&gt;Now, having said all that, this is just what I've been thinking about recently. Maybe it's all crazy talk. Feel free to sound off in the comments and tell me that :).&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>OneQuery - A Fluent Interface to Database Queries</title>
      <link>http://vibrantcode.com/blog/2007/12/11/onequery-a-fluent-interface-to-database-queries.html</link>
      <pubDate>Tue, 11 Dec 2007 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2007/12/11/onequery--a-fluent-interface-to-database-queries</guid>
      <description>&lt;p&gt;Aside from my school work and my work on the &lt;a href=&quot;http://www.dotnetnuke.com/tabid/824/default.aspx&quot;&gt;DotNetNuke Reports Module&lt;/a&gt; (very very close to release now), I've been tinkering with another project over the past few months. It's called OneQuery and its yet another Data Access Layer tool. OneQuery is designed to provide a &amp;quot;&lt;a href=&quot;http://en.wikipedia.org/wiki/Fluent_interface&quot;&gt;fluent interface&lt;/a&gt;&amp;quot; to database queries. &lt;/p&gt;  &lt;p&gt;What is a fluent interface? Wikipedia defines it as &amp;quot;an object oriented construct that defines a behaviour capable of relaying the instruction context of a subsequent call&amp;quot;. Essentially, it means that instead of writing code like this:&lt;/p&gt;  &lt;pre class=&quot;csharpcode&quot;&gt;List&amp;lt;&lt;span class=&quot;kwrd&quot;&gt;int&lt;/span&gt;&amp;gt; ints = &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; List&amp;lt;&lt;span class=&quot;kwrd&quot;&gt;int&lt;/span&gt;&amp;gt;();&lt;br/&gt;ints.Add(1);&lt;br/&gt;ints.Add(2);&lt;br/&gt;ints.Add(3);&lt;/pre&gt;&lt;p&gt;You can write code like this&lt;/p&gt;&lt;pre class=&quot;csharpcode&quot;&gt;List&amp;lt;&lt;span class=&quot;kwrd&quot;&gt;int&lt;/span&gt;&amp;gt; ints = &lt;span class=&quot;kwrd&quot;&gt;new&lt;/span&gt; List&amp;lt;&lt;span class=&quot;kwrd&quot;&gt;int&lt;/span&gt;&amp;gt;().Add(1).Add(2).Add(3);&lt;/pre&gt;&lt;p&gt;That's quite a savings and, in my opinion, it's much more readable.&lt;/p&gt;&lt;h4&gt;So, what's the point?&lt;/h4&gt;&lt;br/&gt;&lt;p&gt;Well, recently I've been thinking about the issue of database agnostic...ness (database agnostivity? database agnosticism?). I really want to be able to write data access code that will run on multiple database engines without having to manually translate it. &lt;a href=&quot;http://www.dotnetnuke.com/&quot;&gt;DotNetNuke&lt;/a&gt; provides a, theoretically, database agnostic interface through Data Providers. However, to support another database engine, the core DataProvider must be translated, Stored Procedures must be converted and all sorts of &amp;quot;Porting&amp;quot; issues arise. Wouldn't it be nice if you could WORA (Write Once, Run Anywhere... a Java term) your SQL Scripts?&lt;/p&gt;&lt;h4&gt;Wait, hasn't this been done?&lt;/h4&gt;&lt;br/&gt;&lt;p&gt;Of course it has, and many many times. First, there's the elephant in the room, LINQ. However, aside from requiring .Net 3.5, if you want to write database agnostic code, you need to use something like the ADO.Net Entity Framework. OneQuery is designed to work in .Net 2.0, and I'm planning to write a LINQ layer on top of it so that you can write LINQ queries and run them on multiple database engines (not just SQL Server). I think OneQuery could serve as a &amp;quot;migration path&amp;quot; where you can write OneQuery syntax and then move to LINQ syntax when you're ready to move to .Net 3.5 while still keeping the database-agnostic OneQuery core.&lt;/p&gt;&lt;p&gt;There are a lot more database libraries out there as well. &lt;a href=&quot;http://subsonicproject.com&quot;&gt;SubSonic&lt;/a&gt; provides an excellent Object/Relational Mapper (ORM) that allows you to work directly with objects, but sometimes you want a little more control. There are, of course, many others such as NHibernate, IBATIS.Net, and EntitySpaces. However, I found that while working with these tools I would find little things that would annoy me. For example, SubSonic does provide a way for you to directly query the database and get an IDataReader back, but it has an interface I found a little awkward (though it is a nice fluent interface). There are also smaller annoying features such as a lack of support for certain SQL statements (like &amp;quot;INSERT&amp;quot;) and a lack of JOIN support. On the other side, tools like NHibernate are really designed to allow you to ignore the database completely, which is a nice feature, but sometimes I need that direct database control.&lt;/p&gt;&lt;h4&gt;&lt;/h4&gt;&lt;br/&gt;&lt;h4&gt;&lt;/h4&gt;&lt;br/&gt;&lt;h4&gt;So, what is OneQuery?&lt;/h4&gt;&lt;br/&gt;&lt;p&gt;[Wow, I started two sub-headings off with 'so', perhaps that summer at Microsoft is affecting my patterns of speech. They say Microsofties tend to start there sentences with &amp;quot;so&amp;quot; and say &amp;quot;drinking from a firehose&amp;quot; and &amp;quot;super&amp;quot; a lot]&lt;/p&gt;&lt;p&gt;OneQuery is designed to let you focus on writing one query, and allows you to run the query on multiple database systems. Instead of using strings, which the compiler ignores, I wanted to provide a fluent interface and use operator overloading to make the queries as readable as possible.&lt;/p&gt;&lt;h4&gt;Enough already, get to the code!&lt;/h4&gt;&lt;br/&gt;&lt;p&gt;Ok, so here's a sample query using OneQuery's fluent syntax:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/OneQueryAFluentInterfacetoDatabaseQuerie_1396C/query_4.png&quot;&gt;&lt;img style=&quot;border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px&quot; height=&quot;88&quot; alt=&quot;query&quot; src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/OneQueryAFluentInterfacetoDatabaseQuerie_1396C/query_thumb_1.png&quot; width=&quot;658&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;(I posted it as a screenshot to make sure the spacing worked out, I'll post the text at the end if you want to copy it).&lt;/p&gt;&lt;p&gt;There are a few things I want to do to let you clear that up even further. For example, it would be much easier if you could write &amp;quot;.OrderBy(Product.ListPrice).Desc()&amp;quot;, or &amp;quot;.Where(Product.ListPrice.Between(10).And(100))&amp;quot;&lt;/p&gt;&lt;p&gt;Behind the scenes, the only other code you need to &amp;quot;write&amp;quot; is a helper class for the products table. I used quotes there because I'm planning on creating a code generator to do that for you.&lt;/p&gt;&lt;h4&gt;CAN HAZ CODE?&lt;/h4&gt;&lt;br/&gt;&lt;p&gt;Hopefully I've tantalized you a little bit and you'd like to check it out. You can download a preview release from our &lt;a href=&quot;http://www.codeplex.com/onequery&quot;&gt;CodePlex Project Site&lt;/a&gt;, and discuss future features there as well. I'm planning a whole bunch of new features including (but definitely NOT limited to): &lt;/p&gt;&lt;ul&gt;&lt;br/&gt;  &lt;li&gt;Support for ALL SQL DML Statements (INSERT, UPDATE, DELETE) &lt;/li&gt;&lt;br/&gt;  &lt;li&gt;Full support for SELECT (including JOIN, GROUP BY, HAVING, and sub-queries) &lt;/li&gt;&lt;br/&gt;  &lt;li&gt;A Code Generator to create the helper classes &lt;/li&gt;&lt;br/&gt;  &lt;li&gt;and more! &lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;p&gt;Please let me know what you think! I want to make sure this system solves problems for as many people as possible, and the best way to do that is to get contributions from the community as early as possible. The &lt;a href=&quot;http://www.codeplex.com/onequery&quot;&gt;CodePlex site&lt;/a&gt; has plenty of places to contribute, so please check it out!&lt;/p&gt;&lt;h5&gt;Sample Code in Text Form&lt;/h5&gt;&lt;br/&gt;&lt;pre class=&quot;csharpcode&quot;&gt;IDataReader rdr = Product.Query()&lt;br/&gt;                         .Where(Product.ListPrice &amp;gt; 10 &amp;amp; Product.ListPrice &amp;lt; 100)&lt;br/&gt;                         .OrderBy(Product.ListPrice, SortDirection.Descending)&lt;br/&gt;                         .ExecuteReader();&lt;/pre&gt;&lt;p&gt;&lt;br/&gt;  &lt;div class=&quot;wlWriterSmartContent&quot; id=&quot;scid:0767317B-992E-4b12-91E0-4F059A8CECA8:72e27e42-13fc-4276-bae4-35c1cd2093a5&quot; style=&quot;padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px&quot;&gt;Technorati Tags: &lt;a href=&quot;http://technorati.com/tags/Data%20Access&quot; rel=&quot;tag&quot;&gt;Data Access&lt;/a&gt;,&lt;a href=&quot;http://technorati.com/tags/C#&quot; rel=&quot;tag&quot;&gt;C#&lt;/a&gt;,&lt;a href=&quot;http://technorati.com/tags/VB&quot; rel=&quot;tag&quot;&gt;VB&lt;/a&gt;,&lt;a href=&quot;http://technorati.com/tags/.Net&quot; rel=&quot;tag&quot;&gt;.Net&lt;/a&gt;,&lt;a href=&quot;http://technorati.com/tags/Fluent%20Interface&quot; rel=&quot;tag&quot;&gt;Fluent Interface&lt;/a&gt;,&lt;a href=&quot;http://technorati.com/tags/ORM&quot; rel=&quot;tag&quot;&gt;ORM&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Test Post from Windows Live Writer</title>
      <link>http://vibrantcode.com/blog/2007/11/20/test-post-from-windows-live-writer.html</link>
      <pubDate>Tue, 20 Nov 2007 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2007/11/20/test-post-from-windows-live-writer</guid>
      <description>&lt;p&gt;Just writing a test post from Windows Live Writer. Look for a future, more detailed post about it!&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div class=&quot;wlWriterSmartContent&quot; id=&quot;scid:0767317B-992E-4b12-91E0-4F059A8CECA8:98cda58e-fadb-4b8c-a9aa-31e395767057&quot; style=&quot;padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px&quot;&gt;Technorati Tags: &lt;a href=&quot;http://technorati.com/tags/Windows%20Live%20Writer&quot; rel=&quot;tag&quot;&gt;Windows Live Writer&lt;/a&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Here's a map!&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;div class=&quot;wlWriterSmartContent&quot; id=&quot;scid:84E294D0-71C9-4bd0-A0FE-95764E0368D9:0fda3bb5-6e57-49a7-b94a-bdc3a10a86b6&quot; style=&quot;padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px&quot;&gt;&lt;a href=&quot;http://maps.live.com/default.aspx?v=2&amp;amp;cp=44.59047~-26.71875&amp;amp;lvl=1&amp;amp;style=r&amp;amp;mkt=en-US&amp;amp;FORM=LLWR&quot; id=&quot;map-82044d76-d63c-4c16-a911-52f1671db2ef&quot; alt=&quot;Click to view this map on Live.com&quot; title=&quot;Click to view this map on Live.com&quot;&gt;&lt;img src=&quot;https://s3.amazonaws.com/vibrantcode-res/blogcontent/imported/WindowsLiveWriter/TestPostfromWindowsLiveWriter_14D5C/map-350854983f6b.jpg&quot; width=&quot;320&quot; height=&quot;240&quot; alt=&quot;Map image&quot;&gt;&lt;/a&gt;&lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;ooo...fancy...&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>New Blog</title>
      <link>http://vibrantcode.com/blog/2007/11/15/new-blog.html</link>
      <pubDate>Thu, 15 Nov 2007 00:00:00 -0800</pubDate>
      <author>andrew@andrewnurse.net</author>
      <guid>http://vibrantcode.com/blog/2007/11/15/new-blog</guid>
      <description>So, this is my first post in my new blog. Just a test post for now, but hopefully I'll put more interesting things here :)&lt;br&gt;&lt;p&gt;&lt;/p&gt;
</description>
    </item>
    

  </channel> 
</rss>