Code generation with Roslyn

I recently wrote an answer on regarding what I’ve learned doing code generation with Roslyn.

My conclusion after a few weeks playing around is that using a combination of inline code snippets (parsed using CSharpSyntaxTree.ParseText) and manually generated SyntaxNodes, works well. But I felt a strong preference for the former. I have also used T4 in the past but am moving away from them due to general lack of integration & capability. I compare the three approaches below and conclude with some tips about doing code gen with Roslyn:

Advantages/disadvantages of each:

Roslyn ParseText

  • Generates arguably more readable code-generator code.
  • Allows ‘text templating’ approach e.g. using C# 6 string interpolation.
  • Less verbose.
  • Guarantees valid syntax trees.
  • Can be more performant.
  • Easier to get started.
  • Text can become harder to read than SyntaxNodes if majority is procedural.

Roslyn SyntaxNode building

  • Better for transforming existing syntax trees – no need to start from scratch.
    • But existing trivia can make this confusing/complex.
  • More verbose. Arguably harder to read and build.
    • Syntax trees are often more complex than you imagine
  • SyntaxFactory API provides guidance on valid syntax.
  • Roslyn Quoter helps you transform textual code to factory code.
  • Syntax trees are not necessarily valid.
  • Code is perhaps more robust once written.

T4 templates

  • Good if majority of code to be generated is boiler plate.
  • No proper CI support.
  • No syntax highlighting or intellisense without 3rd party extensions.
  • One to one mapping between input and output files.
    • Not ideal if you are doing more complex generation e.g. entire class hierarchy based on single input.
  • Still probably want to use Roslyn to “reflect” on input types, otherwise you will get into trouble with System.Reflection and file locks etc.
  • Less discoverable API. T4 includes, parameters etc. can be confusing to learn.

Roslyn code-gen tips

  • If you are only parsing snippets of code e.g. method statements, then you will need to use CSharpParseOptions.Default.WithKind(SourceCodeKind.Script) to get the right syntax nodes back.
  • If you are parsing a whole block of code for a method body then you will want to parse it as a GlobalStatementSyntax and then access the Statement property as a BlockSyntax.
  • Use a helper method to parse single SyntaxNodes:
        private static TSyntax ParseText<TSyntax>(string code, bool asScript = false)
            var options = asScript
                ? CSharpParseOptions.Default.WithKind(SourceCodeKind.Script)
                : CSharpParseOptions.Default;
            var syntaxNodes =
                CSharpSyntaxTree.ParseText(code, options)
            return syntaxNodes.OfType<TSyntax>().First();
  • When building SyntaxNodes by hand you will typically want to make a final call to SyntaxTree.NormalizeWhitespace(elasticTrivia: true) to make the code “round-trippable”.
  • Typically you will want to use SyntaxNode.ToFullString() to get the actual code text including trivia.
  • Use SyntaxTree.WithFilePath() as a convenient place to store the eventual file name for when you come to write out the code.
  • If your goal is to output source files, the end game is to end up with valid CompilationUnitSyntaxs.
  • Don’t forget to pretty-print using Formatter.Format as one of the final steps.

Diagnosing ASP.NET page compilation errors

Page compilation errors are a common cause of ‘yellow screens of death’ (YSOD) encountered by ASP.NET developers. During the heat of development it’s very easy to ignore the details of these error messages, and instead resolve them with a bit of intuition. But there are limits to intuition. Today I had to drill into one of these errors and I learnt quite a bit along the way.

Are you missing an assembly reference?

I’m going to tackle some of the most common page compilation errors, which relate to missing references and/or incorrect using statements. The screenshot below shows a typical 'CS0234' error:

The compiler error message reads:

The type or namespace name ‘Helpers’ does not exist in the namespace ‘System.Web’ (are you missing an assembly reference?).

Page compilation errors

To understand what is going on it’s useful to have a quick reminder of how ASP.NET works under the hood.

Every page or view in an ASP.NET site ultimately gets converted into executable code. By default this happens at runtime.

It’s a two-step process: Using a Razor view as an example, first the Razor view engine uses code generation to translate the .cshtml file into a .cs file. Then ASP.NET compiles that .cs source into an executable binary.

It’s errors occuring during this second step which reveal themselves as YSODs like the one shown above. YSODs do actually include useful debug information…

YSOD examined

Clicking ‘Show Complete Compilation Source’ shows me the full C# source file which has been generated by the view engine for the requested page. Here you can clearly see all the using statements generated by the view engine code generator.

Clicking on ‘Show Detailed Compiler Output’ shows you exactly how csc.exe (the C# compiler) was invoked by ASP.NET in order to compile the page’s generated C# code. Importantly the /R: parameters are the referenced assemblies.

Every C# developer knows that in order to succesfully build an assembly from a module of code you need to make sure all the types you use are made available to the compiler via references.

With normal C# projects you add your own references and write your own using statements. But what determines the references and using statements when code is generate for pages and compiled by ASP.NET?


The references used by ASP.NET during page compilation are specified entirely in configuration files using the assemblies element for compilation.

“But I haven’t specified an assemblies element!”, I hear you say.

The reason you still get some by default is that the root-level web.config file (typically found in
, that comes distributed with .NET, contains something akin to the following:

            <remove assembly="Microsoft.VisualStudio.Web.PageInspector.Loader, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="Microsoft.VisualStudio.Web.PageInspector.Loader, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="mscorlib" />
            <add assembly="Microsoft.CSharp, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Configuration, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System.Web, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System.Data, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Web.Services, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System.Xml, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Drawing, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System.EnterpriseServices, Version=, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
            <add assembly="System.IdentityModel, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Runtime.Serialization, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.ServiceModel, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.ServiceModel.Activation, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.ServiceModel.Web, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.Activities, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.ServiceModel.Activities, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.WorkflowServices, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.Core, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Web.Extensions, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.Data.DataSetExtensions, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.Xml.Linq, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
            <add assembly="System.ComponentModel.DataAnnotations, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.Web.DynamicData, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="System.Web.ApplicationServices, Version=, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add assembly="*" />

Unless you make configuration changes this list will match the referenced assemblies you observe ‘Show Detailed Compiler Output’ section of the YSOD. Excluding one important exception…

Note that the final entry is special. It uses a star ‘*’ instead of providing an assembly name. The remarks on MSDN explain it’s purpose:

Optionally, you can specify the asterisk (*) wildcard character to add every assembly within the private assembly cache for the application, which is located either in the \bin subdirectory of an application or in the.NET Framework installation directory (%systemroot%\Microsoft.NET\Framework\version).

The implications of this are that you can easily ensure additional assemblies get referenced during page compilation by placing them in your private assembly cache. And you do that simply by changing the “Copy Local” property of an assembly to true (correlated with the Private reference attribute within an MSBUILD file).

But what if you don’t want to add the assembly to your private assembly cache? In that case you just explicity add it to your application-level web.config using the same assemblies.add element shown above.


Where do the default using statements come from for the generated code? Well this actually depends on the view engine you are using. The default view engine (Web Forms) takes its defaults from the root-level web.config under the namespaces element:

            <add namespace="System" />
            <add namespace="System.Collections" />
            <add namespace="System.Collections.Generic" />
            <add namespace="System.Collections.Specialized" />
            <add namespace="System.ComponentModel.DataAnnotations" />
            <add namespace="System.Configuration" />
            <add namespace="System.Linq" />
            <add namespace="System.Text" />
            <add namespace="System.Text.RegularExpressions" />
            <add namespace="System.Web" />
            <add namespace="System.Web.Caching" />
            <add namespace="System.Web.DynamicData" />
            <add namespace="System.Web.SessionState" />
            <add namespace="System.Web.Security" />
            <add namespace="System.Web.Profile" />
            <add namespace="System.Web.UI" />
            <add namespace="System.Web.UI.WebControls" />
            <add namespace="System.Web.UI.WebControls.WebParts" />
            <add namespace="System.Web.UI.HtmlControls" />
            <add namespace="System.Xml.Linq" />

Namespaces with Razor

If you are using Razor the default namespaces are hardcoded!

You can easily add to the list of default namespaces by adding a razor-specific namespaces element to your web.config (sample shown below), but you cannot easily remove default namespaces. Even attempting to use <clear/> does not work. If you really need to get rid of default namespaces you will have to do it in code.

  <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
  <pages pageBaseType="System.Web.Mvc.WebViewPage">
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Optimization"/>
    <add namespace="System.Web.Routing" />

A note about Web.configs

Bare in mind that projects often have a web.config specifically for the Views folder (e.g. MVC) and the page compiler will pay attention to the config heirarchy. Typically you will want to makes changes specific to your Views web.config.


Using the information in this blog post you should be able to understand and resolve any page compilation errors relating to missing references and/or incorrect using statements. Good luck!

The Economics of Microsoft Surface

This is a post I wrote August 2009 but never got around to publishing. Whilst spring cleaning my drafts, I re-read it and decided it wasn’t that bad, so here it is. I wonder if the issues are still the same in 2011….


It’s almost a year ago to the month that Amnesia Razorfish smuggled the first Microsoft Surface tables into Australia with the help of parent company Razorfish, much to the excitement of local geeks. There was also a fair bit of uproar from surprised parties who hadn’t expected to be usurped in such spectacular fashion.

I was hired by Amnesia shortly before Surface arrived, partly on speculation that they would soon need a Surface developer. I had experience with the technologies it uses, and a great interest in the product, so was really excited to get such an opportunity. It was also a bit of a gamble on my part, as it was by no means guaranteed at the time they would even be getting a table, let alone any paying clients.

The first few weeks, maybe months, there was a great buzz and curiosity from clients and media about this new device. The phones were ringing off the hook and there were regular coffee table tours.

Despite this, and the amazing stock of talent Amnesia had at its disposal, I think it’s safe to say that during my year there, they never needed more than this one, solitary, Surface developer.

How can that be? “Surely it would be as easy as selling antifreeze to Eskimos!”, I hear you mutter…

Here’s why: In many scenarios, the economics of Surface development simply don’t add up.

For background, let’s put a few ballpark figures on the coffee table:

– Cost of a MS Surface table: $10k
– Cost of  development/design time: $200/hour

Let’s tackle the most obvious thing first: This Is Software Development.

It’s been many years since the Adobe Flash experiences that draw crowds on the web have been built entirely with a visual tool. Most are chock full of ActionScript. In fact, dare I say, they probably contain more programming hours than design hours.

Suffice to say there are very few digital experiences of the richness that people expect these days, that can be built without significant software development capabilities, and that goes for Microsoft Surface too.

Microsoft Surface carries the extra burden of not only having slightly less mature tools than industry mainstay Adobe Flash, but more importantly having a much smaller experience pool, particularly in the crucial “devigner” niche. And as with any new technology, the early days often mean higher costs and higher risks.

So, creating a quality Surface experience means building software. But what do you get for your money? Well it could easily cost you $6000 per man week, and even after many weeks development the chances are you won’t get that award winning experience you were hoping for. My guess is that most commercial Surface applications you see being touted cost in the region of $300,000. Definitely in the hundreds of thousands. Let your imagination go wild and you could easily spend half a million.

The next most obvious thing is: Penetration.

Unlike building a user experience for the web, prospective clients will be footing the bill for each and every device that will end up in front of users. If you are going to pay a hefty sum for bespoke software development you sure as hell want to leverage that investment by deploying it to the maximum number of locations.

You can keep the costs low by only having a tiny number of tables (and maybe even spin that to your boss by claiming the experience would then be truly unique/exclusive!), but ultimately you are talking about investing in a piece of custom-written software that will only ever be seen by a tiny audience. Yes, that might be tenable for a small number of luxury brands, but for the majority who actually need to justify there expenditure? I think not.

So, to get “good value” from your investment in a Surface experience you need to also purchase a reasonably large number of tables. I would say at least in the tens if not hundreds (e.g. retail locations). There’s $500,000 right there.

Lastly: Cost/benefit.

At the end of the day, clients have to estimate how much a Surface experience is going to be worth to them. It’s obvious that many applications of Surface can be categorized as marketing in some sense; whether its experiential branding, attractive gimmick, or 9 o’clock news hype.

I can only imagine it’s very hard to estimate the financial benefits such a Surface experience will bring, because in the majority of cases it’s going to be an indirect effect at best. And such financial benefits are almost certainly going to be impossible to determine a-priori.

Which is also the case if Surface is used as Point-of-Sale platform – it’s all pretty much undiscovered country. With such little data on natural user interfaces, not to mention Surface specifically, it’s very hard at this stage to make confident guesses about how conversion rates or stickiness can be improved. The only way to find out for sure is by putting down the cash. And that’s a risk many firms can’t or wont take.

Running uTorrent as a Service on Windows Home Server 2011

Step 1: Download and Install uTorrent

  • Download uTorrent 2.2.1 (390 KB)
  • Install uTorrent as normal, by opening the downloaded EXE
  • It should install itself into C:\Program Files (x86)\uTorrent

Step 2: Configure uTorrent Web UI

  • Run uTorrent as normal (e.g. Start Menu)
  • Go to Options menu and select Preferences
  • Go to the Directories folder and set the folders where you want your torrents to be stored
    • Make a note of these directories, as you will need them in step 8


  • Go to the Web UI section and make three changes
    • Tick “Enable Web UI”
    • Set a username and password
    • Tick “Alternative Listening Port”; leave the number as 8080
      • Note: This sub-step is not strictly necessary but gives you a higher chance of things working first time


Step 3: Test uTorrent Web UI

  • Using a different computer on the local network ensure you can get to the uTorrent Web UI
  • The web address should of the form http://homeserver:8080/gui/
  • Note: You must replace homeserver in the above URL with the name of the computer where you install uTorrent.
  • The browser should ask for a username and password. Use the values provided in Step 2
  • You should see the uTorrent Web UI.
  • If you do not see the uTorrent Web UI do not proceed any further. You have a networking problem. Seek help.
  • At this stage you have a working uTorrent Web UI but it is NOT running as a service. This means that torrents can still only be downloaded when a user is logged on and running uTorrent. Continue with the following steps to run it as a service…
  • Important: Now Close down uTorrent by choosing File->Exit.

Step 4: Copy the uTorrent settings file

  • Copy the settings.dat file from C:\Users\<User>\AppData\Roaming\uTorrent to C:\Program Files (x86)\uTorrent

Note: Depending on your username you will need to substitute <User> in the above path

Step 5: Download and Install SRVANY.exe

  • Download Windows Server 2003 Resource Kit Tools (11.8 MB).
  • Install the entire tool suite as normal, by opening the downloaded exe.
  • By default srvany.exe will be installed to C:\Program Files (x86)\Windows Resource Kits\Tools\srvany.exe

Step 6: Create Windows Service for uTorrent

  • Open an administrative command prompt by following these steps:
    • Navigate to Start Menu –> Accessories –> Command Prompt
    • Right click and select “Run as Administrator”
  • At the command prompt enter the following:
    sc create uTorrent binPath= "C:\Program Files (x86)\Windows Resource Kits\Tools\srvany.exe" obj= "NT AUTHORITY\LocalService" start= auto
  • Note: Do not remove the spaces between the equals sign and parameters. This is an oddity of sc command and is required
  • If this works you should see something like the screenshot below:


If you get the “Access is denied” error then you are not running as administrator.

Step 7: Configure the SRVANY.EXE service

  • If you want to perform this step manually you will need to know about regedit. Here are the steps:
  • Run regedit
    • Navigate to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\uTorrent\Parameters
    • Create the Parameters key if it does not exist
    • Under the Parameters Key, add a new String Value named Application
    • Set the value to be C:\Program Files (x86)\uTorrent\uTorrent.exe
    • If you have done everything correctly it should look like the screenshot below:


Step 8: Modify permissions on your downloads directory

By default Windows will not allow your uTorrent service to read or write to the disk. In order for uTorrent to work you need to add read & write permissions on the directory or directories you specified in Step 2.

  • Navigate to the directory
  • View the directory properties
  • Select the Security tab
  • Click the Edit… button
  • Click the Add… button
  • Enter LOCAL SERVICE (including the space) then click OK
  • Ensure “Allow Modify” is ticked, and OK everything
  • It should look something like the screeshot below:


Step 9: Ensure the uTorrent service is running

  • Load the services control panel (Start->Run->Services.msc)
  • Locate the service named uTorrent and verify the Status column says “Started”.
  • If it does not say “Started”, then click the Start Service button


  • Log off your Windows session and repeat Step 3 to verify that the web UI is still working and you can download torrents successfully.

General trouble shooting:

  • Double check that uTorrent.exe is not running on your desktop.
    • Note: By default clicking the close button in top right of the uTorrent window will not actually exit the application
  • Double check that uTorrent.exe is running as a service.
    • In task manager, “Show processes from all users”, ensure you can see uTorrent.exe running with LOCAL SERVICE displaying in the User Name column
  • Please leave a comment if you have any issues with this guide

Using d:DesignSource for design-time DataGrid grouping with sample data

I recently had the need to use the row grouping feature of the WPF DataGrid.

As you know, in order to design with Blend effectively, you really need to have data displayed at design-time. It’s fairly straight forward to use combinations of d:DesignContext and d:DesignData to achieve that goal. In the case of DataGrid, you can bind ItemsSource directly to a collection in your design-time model.

The question is: How do you use design-time data and grouping at the same time?

The reason the solution is not obvious is because the DataGrid’s grouping feature relies on having a PropertyGroupDescription configured for the CollectionView that the DataGrid’s ItemSource is bound to. If you bind ItemsSource directly to a collection, you do not have access to the CollectionView at design-time.

Just to confuse things, if you Google for DataGrid grouping you will find a plethora of out-of-date articles suggesting you can configure the grouping by using the DataGrid.GroupingDescriptions in Xaml, which you can’t (it only worked on older/beta versions). On the other hand there are several articles which describe how to configure grouping programmatically. The problem with the programmatic approach is it does not run at design-time, and is in conflict with the design-time attributes. I want to use the well supported design-time sample data tool chain, and keep designers free from having to write code.

While Googling for a solution I came across the new design-time attribute documentation (note: it applies equally well to WPF in spite of the Silverlight bias!), which included an attribute I had never seen before: d:DesignSource. According to MSDN d:DesignSource

Specifies a design-time data source for a CollectionViewSource. This makes the designer aware of the shape of your types. This enables you to use the data binding builder to create bindings.

<CollectionViewSource x:Key="CustomerViewSource"
  local:Customer, CreateList=True}" /> 

The description was intriguing but after looking at the code sample it seemed to be mistakenly underselling the capability. The sample code shows that it does more than make the “designer aware of the shape of your types” – it’s actually allowing sample data to be injected into a CollectionViewSource using the well know d:DesignInstance … and presumably d:DesignData too.

As it turns out, the only way to specify the DataGrid grouping in Xaml is to use the CollectionViewSource. I figured by combining CollectionViewSource and d:DesignSource I could achieve my goals.

After some experimentation I got it working exactly as I hoped it would. Here is the code:


            <CollectionViewSource x:Key="groupedCollectionView"
                                  d:DesignSource="{d:DesignData Source=./SampleData/BookingRowCollectionSampleData.xaml }" 
                                  Source="{Binding RuntimeBookingRowCollection}">
                    <PropertyGroupDescription PropertyName="PropertyToGroupBy"/>

        <DataGrid AutoGenerateColumns="True"
                  ItemsSource="{Binding Source={StaticResource groupedCollectionView}}" >
                <x:Static Member="GroupStyle.Default"/>


There are a couple of things to point out:

  • I used “Create sample data from class…” in Blend to create my BookingRowCollectionSampleData.xaml. The class which I generate from was defined below. I found I had to create this specialized collection in order to satisfy the d:DesignSource. Conversely my attempt at creating sample data based off my view model which in turn had a collection property was a dead end – d:DesignSource needs to be given a raw collection; there is no way to dereference the collection property within a view model.
        public class BookingRowCollection : List<BookingRow>
  • I wanted to make sure that I didn’t need multiple paths in my code behind to handle the differences between design-time and run-time, specifically with binding and MVVM. In this case the design-time “switch” is handled purely within the CollectionViewSource, where the Source is set differently depending on what mode we are in. Note that even though the CollectionViewSource is a resource, it will still correctly bind to our RuntimeBookingRowCollection.

Declaring the CollectionViewSource proxy within your Xaml will not suit all MVVM projects as sometimes you might want to define a CollectionView within your view model, but it worked in my case because the grouping was never going to change. For this project the grouping can be considered purely part of presentation so I am happy to declare it in Xaml, and as a bonus it works beautifully with design-time sample data!

I think this solution will work for Silverlight too, but I have not tested it yet.