Software Development

Application configuration in .NET Core – Part 1

.NET Core has a new way of working with configuration that is much more flexible than the way that previous versions of .NET have.

It allows you to:

  1. Pull configuration from multiple sources and bring it in to one place.
  2. Easily map that configuration information into classes to make access easier.
  3. Override configuration from previous sources so that you can import a base configuration then override settings on per-environment basis.

This post will be concerned with the first of these: Pulling configuration from multiple sources and bringing it together in to one place. We’ll discuss the second and third aspect in future posts.

Getting Started

To use it you need to add the Microsoft.Extensions.Configuration NuGet package to your application.

Microsoft.Extensions.Configuration 1.0.0 NuGet package
Microsoft.Extensions.Configuration NuGet package

Once you’ve imported the package your project.json will contain:

  "dependencies": {
    "Microsoft.Extensions.Configuration": "1.0.0",
    .... Other dependencies here ....
  }

From the basic configuration package you don’t really get much in the way of configuration sources, only the in-memory one is available. However, that’s just enough to show you the basic set up of the configuration in an application.

public class Program
{
    public static void Main(string[] args)
    {
        // Defines the sources of configuration information for the 
        // application.
        var builder = new ConfigurationBuilder()
            .AddInMemoryCollection(new []
            {
                new KeyValuePair("the-key", "the-value"),
            });

        // Create the configuration object that the application will
        // use to retrieve configuration information.
        var configuration = builder.Build();

        // Retrieve the configuration information.
        var configValue = configuration["the-key"];
        Console.WriteLine($"The value for 'the-key' is '{configValue}'");

        Console.ReadLine();
    }
}

The builder is the thing that allows you to set up the sources of configuration information. Each provider adds extension methods so you can add them easily to the builder. The InMemoryCollection simply takes an IEnumerable of KeyValuePairs to initialise its values.

Once you have set up your configuration sources you can build all that into an actual object you can use in your application, by calling Build() on the builder object. From here on you can access configuration values with indexer notation.

Adding a JSON File Source

So far, what we have isn’t very useful. We need to pull configuration information from outside the application such as a JSON file. To do that, we need to add another NuGet package. This one provides a JSON provider and is called Microsoft.Extensions.Configuration.Json.

Microsoft.Extensions.Configuration.Json NuGet package
Microsoft.Extensions.Configuration.Json NuGet package

We can now extend the simple application above by adding an appsettings.json file and adding in the code to build it.

var builder = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .AddInMemoryCollection(new []
    {
        new KeyValuePair("the-key", "the-value"),
    });

And the appsettings.json looks like this:

{
  "my-other-key": "my-other-value" 
}

And the value is retrieved like any other:

configValue = configuration["my-other-key"];
Console.WriteLine($"The value for 'my-other-key' is '{configValue}'");

However, while this looks like it should work, it won’t. When you added a settings file previously, Visual Studio would mark it for copying to the output folder so that the running application could find it. However, it doesn’t do that with .NET Core (yet – I do hope they add it).

Instead you get a FileNotFoundException, like this:

Exception Assistant showing a File Not Found Exception
An unhandled exception of type ‘System.IO.FileNotFoundException’ occurred in Microsoft.Extensions.Configuration.FileExtensions.dll Additional information: The configuration file ‘appsettings.json’ was not found and is not optional.

To get the appsettings.json file added to the output folder you are going to have to modify the project.json file.

In the buildOptions section add copyToOutput with the name of the file. If there is more than one file you can put in an array of files rather than just the one. The top of the project.json file now looks like this:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true,
    "copyToOutput": "appsettings.json"
  },
  .... The rest of the file goes here ....

The next time the project is run it will copy the appsettings.json file and you won’t get an exception to say that the file was not found.

Software Development

Setting up Ubuntu for .NET Development

First up, at the time of writing only Ubuntu 14.04LTS is supported. I’ve read that it will work on 15.04, but I know it won’t work on 15.10 because of a binary incompatibility on a library that .net core relies on.

Step 1: Install the .NET Execution Environment

Follow the instructions at https://docs.asp.net/en/latest/getting-started/installing-on-linux.htm

This will install the .NET Execution Environment (DNX)

Step 2: Install Node.js

Since .NET Core relies on node js for parts, and there are some cool code generators using node.js as the templating engine, install node.js by following the instructions here: https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions

I used version 4.x LTS (4.4.1 to be exact)

Step 3: Install Visual Studio Code

This is actually optional – I’m installing it because I wanted to get the standard IDE for C#. You can get away with running just the regular text editor installed with Ubuntu.

First, download Visual Studio Code. Then follow the setup instructions…. Kind of.

Unzipped the zip file to /usr/local/bin with

sudo unzip ~/Downloads/VSCode-linux-x64-stable.zip

Then I created the link as in the instructions so that I can launch from the terminal.

To launch from the terminal and get the prompt back use

code &

Step 4: Install Yeoman

Before you do, you’ll need up to update NPM as the version that comes with 4.x LTS is older and the current version of Yeomen doesn’t like it.

sudo npm install -g npm

Install yoman by following the instructions here: https://github.com/omnisharp/generator-aspnet#generator-aspnet

Remember to put sudo in front of install commands specifying -g (global) otherwise you’ll get an error message.

Step 5: Create a project

Move to a directory that you want to create a new project in. I use ~/dev for all my development work.

Then start Yeoman with:

yo aspnet

This will result in a prompt that looks like this:

     _-----_
    |       |    .--------------------------.
    |--(o)--|    |      Welcome to the      |
   `---------´   |   marvellous ASP.NET 5   |
    ( _´U`_ )    |        generator!        |
    /___A___\    '--------------------------'
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

? What type of application do you want to create? (Use arrow keys)
❯ Empty Application 
  Console Application 
  Web Application 
  Web Application Basic [without Membership and Authorization] 
  Web API Application 
  Nancy ASP.NET Application 
  Class Library 
  Unit test project 

You can then use the arrow keys to move up and down the list.

Choose “Web Application Basic”

It will then prompt for a name. I chose “MyHelloWorldApp”

It will create that directory and populate it with files for the project. You’ll still need to restore the packages that you need, and yeomen gives you some help on getting that done.

If you follow the yeomen instructions you’ll find that at the dnu build step it fails. This is because the project template has dual targeting. It targets .NET 4.5.1 and .NET Core. On Linux only .NET Core will run. To remove the dual targetting open the project.json file and find the section that looks like this:

  "frameworks": {
    "dnx451": {},
    "dnxcore50": {}
  },

And remove the entry for "dnx451" then save the file.

dnu build won’t work just yet. If you try it you’ll get an error message:

/home/colin/dev/MyHelloWorldApp/project.lock.json(1,0): error NU1006: Dependencies in project.json were modified. Please run "dnu restore" to generate a new lock file.

Build failed.
    0 Warning(s)
    1 Error(s)

So, run dnu restore once again so that the dependencies synchronised with the project.

Once that’s done type dnu build and it will now succeed.

You now have a basic environment set up on Linux for developing .NET Core applications and have demonstrated that you can create and build a simple ASP.NET Core application.

Software Development

Using GitHub Two Factor Authentication (2FA) with TeamCity

If you have two factor authentication (2FA) set up in GitHub and you also want to use TeamCity, the easiest way to set this up is to set up SSH keys to access the GitHub repository.

The first step is to follow this guide to creating SSH keys for GitHub. Remember the passphrase you use when creating the key, you’ll need it later.

Once you have created your keys and applied it to your GitHub account you can then follow this guide for managing SSH keys in TeamCity.

Finally, when setting up your VCS Root in Team City you set the Fetch URL to the SSH variant. You can find this on your project page on Github towards the bottom of the right sidebar.

You may need to click the “SSH” link below the URL if it does not already show the SSH URL.

Back in Team City you can paste this URL in the Fetch URL box in the general settings. Further down the form in the Authentication Settings section you can specify the SSH key you uploaded earlier.

By specifying “Uploaded Key” the boxes below will change. Select the key you uploaded earlier, the user name is “git”, and enter the passphase you used when you created the SSH key.

You should now be able to test the connection to see if all is well.

Software Development

Debugging a process that cannot be invoked through Visual Studio.

Sometimes it is rather difficult to debug through Visual Studio directly even although the project is right there in front of you. In my case I have an assembly that is invoked from a wrapper that is itself invoked from an MSBuild script. I could potentially get VS to invoke the whole pipeline but it seemed to me a less convoluted process to try and attach the debugger to the running process and debug from there.

But what if the process is something quite ephemeral. If the process starts up, does its thing, then shuts down you might not have time to attach a debugger to it before the process has completed. Or the thing you are debugging is in the start up code and there is no way to attach a debugger in time for that.

However there is something that can be done (if you have access to the source code and can rebuild).

for (int i = 30; i >= 0; i--)
{
    Console.WriteLine("Waiting for debugger to attach... {0}", i);
    if (Debugger.IsAttached)
        break;
    Thread.Sleep(1000);
}

if (Debugger.IsAttached)
{
    Console.WriteLine("A debugger has attached to the process.");
    Debugger.Break();
}
else
{
    Console.WriteLine("A debugger was not detected... Continuing with process anyway.");
}

You could get away with less code, but I like this because is is reasonably flexible and I get to see what’s happening.

First up, I set a loop to count down thirty seconds to give me time to attach the debugger. On each loop it checks to see if the debugger is attached already and exits early if it has (This is important as otherwise you could attach the debugger then get frustrated waiting for the process to continue.)

After the loop (regardless of whether it simply timed-out or a debugger was detected) it does a final check and breaks the execution if a debugger is detected.

Each step of the way it outputs to the console what it is doing so you can see when to attach the debugger and you can see when the debugger got attached, or not.

My recommendation, if you want to use this code, is to put it in a utility class somewhere that you can call when needed, then take the call out afterwards.

Software Development

Two Factor Authentication with GitHub and Visual Studio 2013

New job, new tools, new processes. In my new job we’re using GitHub for source control, and because the data is sensitive we’re also using two factor authentication. Because I develop with Visual Studio that presents and interesting issue if you are using Visual Studio 2013’s build in Git Source Control provider.

After turning on Two Factor Authentication, the next time you have to communicate with GitHub (e.g. pull/push/sync’ing, etc.) it will pop up a dialog asking for your credentials, even if you already entered them previously before turning on 2FA.

You get an error message that looks like this:

An error occurred. Detailed message: An error was raised by libgit2. Category = Net (Error).
Response status code does not indicate success: 401 (Authorization Required).

Entering your credentials won’t do you any good. It won’t work. It will just request them again, ad infinitum.

There is no where to enterthe 2FA code, so you can’t authenticate yourself here.

However, you can go to GitHub and create a personal access token in order that Visual Studio 2013 can access your repositories.

You can either drop down the menu on your avatar and go to “Settings”, then go to “Personal Access Tokens” (link in the side bar) or you can just go here https://github.com/settings/tokens.

Then click on “Generate New Token”. You’ll be asked for your credentials again just to be sure you are still you.

Once you’ve done that you’ll be taken to the page to create your credentials

For what Visual Studio wants the default permissions are fine. Also, give the token an appropriate name so it can be identified easily.

Then press “Generate token”.

You will then be taken back to the “Personal access tokens” page. This time there is a new token which you can use in Visual Studio. Be careful here, this is the one and only time you will be able to access this token so copy it and keep it safe.

Back in Visual Studio try and sync the commits to GitHub. It will pop up the credentials dialog again. This time you are going to enter the token in the username box and leave the password box blank.

Then press OK.

Finally, your changes will sync with GitHub and you’ll get a success message.

Software Development

Custom routing to support multi-tenancy applications

The company I currently work for has many brands so they are looking for a website that can be restyled for each brand. They also want the styling information to be managed through an admin area rather than have to go to the development team each time they want to change something.

To that end I have added some custom routing into the application to allow assets to be delivered via a controller yet have the URL look like a path to a file on disk.

The summary of the steps involved are:

  • Set up a custom route with a custom route handler
  • Build the logic in the custom route handler to ensure that the data is passed to the controller correctly.
  • Update the web.config file to tell IIS to allow certain paths through to ASP.NET MVC that would otherwise look like a static path.

Setting up the custom route

My custom route is inside an area to keep all tenant specific URLs separate from the rest of the application.

public override void RegisterArea(AreaRegistrationContext context) 
{
    context.MapRoute(
        "Tenant_customLogic",
        "Tenant/{tenant}/content/{*contents}",
        new { action = "Index", controller="Content"}
    ).RouteHandler = new TenantRouteHandler();
}

So, this means that the routing engine can extract the “tenant” from the URL and it will also allow multiple path parts in the “contents” value. So, if the URL is: http://example.com/Tenant/MyBrand/content/my/virtual/file/path/to/styles.css then the RouteValueDictionary will contain:

  • tenant: MyBrand
  • controller = Content
  • action = Index
  • contents = my/virtual/file/path/to/styles.css

However, we want to split up the contents into its individual components, so a TenantRouteHandler class is created to do that.

Build the custom route handler

Without going too much in to what this class does in this specific instance (which isn’t relevant to the general concept) the basics are

  • Create a class that implements IRouteHandler
  • In GetHttpHandler process the routing information to get what we want in a format that suits the application.
  • Create a regular IRouteHandler object (normally an MvcRouteHandler) and call its GetHttpHandler() method with the updated requestContext as I otherwise want the same functionality as a regular handler.
public class TenantRouteHandler : IRouteHandler
{
    private readonly Func<IRouteHandler> _routeHandlerFactory;
 
    public TenantRouteHandler()
    {
        _routeHandlerFactory = ()=> new MvcRouteHandler();
    }

    public TenantRouteHandler(Func<IRouteHandler> routeHandlerFactory)
    {
        _routeHandlerFactory = routeHandlerFactory;
    }

    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        ProcessRoute(requestContext); // does stuff to modify the request context
        IRouteHandler handler = _routeHandlerFactory();
        return handler.GetHttpHandler(requestContext);
    }
}

ProcessRoute(requestContext) is the specific implementation that extracts the information out of the route and I then add it back into the RouteValueDictionary so my controller can access it. It isn’t relevant so I’m not including it.

What I also do here (because ASP.NET MVC, despite being launched in 2009 to a fanfare of being easy to unit test, isn’t east to unit test at all) is also set up some functional hooks that I can use in unit testing. The default constructor simply sets up the strategy to return a regular MvcRouteHandler and that’s the constructor that will be used in production. The other constructor is used in unit tests so that I can inject my own handler that doesn’t need tons of MVC infrastructure to be set up in advance.

So, the contents part of the route is now split out as we need it for the application.

Getting IIS to pass through these routes to ASP.NET MVC

Running the application at this point won’t return anything. In fact, IIS will throw up an error page that it cannot find the file. The expected paths all look like static content, which IIS thinks it is best placed to deal with. However, the web.config can be updated to let IIS know that certain paths have to be passed through to ASP.NET MVC for processing.

Once the following is added to the web.config everything should work as expected.

  <system.webServer>
    <handlers>
      <!-- This is required for the multi-tenancy part so it can serve virtual files that don't exist on the disk -->
      <add
        name="TenantVirtualFiles"
        path="Tenant/*"
        verb="GET"
        type="System.Web.Handlers.TransferRequestHandler"
        preCondition="integratedMode" />
    </handlers>
  </system.webServer>

And that’s it. Everything should work now. Anything in the Tenant/* path will be processed by ASP.NET MVC and the controller will decide what to serve up to the browser.

Software Development

Changing the default Assembly/Namespace on an MVC appliction

TL;DR

When getting an error message like this:

Compiler Error Message: CS0246: The type or namespace name 'UI' could not be found (are you missing a using directive or an assembly reference?)

when compiling Razor views after changing the namespace names in your project, check the web.config file in each of the view folders for a line that looks like this:

<add namespace="UI" />

And update it to the correct namespace, e.g.

<add namespace="‹CompanyName›.‹ProjectName›.UI" />

Full story

I guess this is something I’ve not done before, so it caught me out a little.

I’ve recently created a new project and to reduce the file paths I omitted information that is already implied by the parent directory.

So, what I ended up with is a folder called ‹Company Name›/‹ProjectName› and in it a solution with a number of projects named UI or Core and so on. I then added a couple of areas and ran up the application to see that the initial build would work. All okay… Great!

I now have a source code repository that looks like this:

/src
  /‹CompanyName›
    /‹ProjectName›
      /UI
      /Core

In previous projects I’d have the source set out like this:

/src
  /‹CompanyName›.‹ProjectName›.UI
  /‹CompanyName›.‹ProjectName›.Core

While this is nice and flat, it does mean that when you add in thing like C# project files you get lots of duplication in the paths that are created. e.g. /src/‹CompanyName›.‹ProjectName›.Core/‹CompanyName›.‹ProjectName›.Core.csproj

Next up I realised that the namespaces were out as they were defaulting to the name of the C# project file name. So I went into the project settings and changed the default namespace and assembly name so that they’d be fully qualified (just in case we ever take a third party tool with similar names, so we need to ensure they don’t clash in the actual code). I also went around the few code files that had been created so far and ensured their namespaces were consistent. (ReSharper is good at doing this, so you just have to press Alt-Enter on the namespace and it will correct it for you)

I ran the application again and it immediately failed when trying to compile a Razor view with the following error message:

Compiler Error Message: CS0246: The type or namespace name 'UI' could not be found (are you missing a using directive or an assembly reference?)

Looking at the compiler output I could see where it was happening:

Line 25:     using System.Web.Mvc.Html;
Line 26:     using System.Web.Routing;
Line 27:     using UI;
Line 28:     
Line 29: 

However, it took me a little investigation to figure out where that was coming from.

Each Views folder in the application has something like this in it:

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="UI" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

There was my old “UI” namespace that had been replaced. It was these settings that were generating the using statements in the Razor precompiled source.

The solution was simple, replace that “UI” namespace with the fully qualified version.

        <add namespace="‹CompanyName›.‹ProjectName›.UI" />

And now the application works!