Can .Net Class Libraries Utilise app.config files?

A few months back I was migrating a .Net solution with 110 projects from .Net 4.5 to .Net 4.6.2 as well as upgrading the Azure SDK. Each project came with its own set of NuGet packages. As you can guess, there were a decent number of packages that needed to be upgraded. Given that the whole solution required testing after the upgrade, then was as good a time as any to bring everything up to date.

When it was time to merge this branch back to the main development branch, there were a number of conflicts, mostly in app.config files belonging to class library projects. Virtually every class library project in the solution had an app.config which didn’t sit right with me. It was something I’d often noticed but never really given any thought to, until now that it was causing some pain.

Does an app.config file in a class library project do anything?

In a nutshell, no, but with a caveat. Configuration files have application wide scope, not assembly wide scope (ignoring machine configurations and publisher policy files). Even though the configuration files contain assembly binding redirects and other important things, they’re really not used (unless you have code to load settings from a local configuration file). It’s one of those things that you know the answer too, but there is a shadow of a doubt in there.

So why do these files appear?

Continue reading

TypeLoadException when using SqlColumnEncryptionAzureKeyVaultProvider

Problem

An exception is thrown when trying to use the SqlColumnEncryptionAzureKeyVaultProvider for working with Always Encrypted columns in SQL Azure.

An unhandled exception of type 'System.TypeLoadException' occurred in Hyak.Common.dllInheritance security rules violated by type: 'System.Net.Http.WebRequestHandler'. Derived types must either match the security accessibility of the base type or be less accessible.

Solution

There’s an issue with the 4.1 version of System.Net.Http assembly. Downgrade to version 4.0.

Background

I’m working on a data migration project that involves moving encrypted data over to Always Encrypted columns. The first part of getting that up and running is to get the Always Encrypted SQL database driver up and running. I’ve worked a fair bit with the Azure Key Vault so was surprised to see the exception detailed above when first running my application. The stack trace wasn’t overly helpful:

   at Microsoft.Azure.Common.Platform.HttpTransportHandlerProvider.CreateHttpTransportHandler()
   at Hyak.Common.ServiceClient`1..ctor()
   at Microsoft.Azure.KeyVault.Internal.KeyVaultInternalClient..ctor()
   at Microsoft.Azure.KeyVault.Internal.KeyVaultInternalClient..ctor(KeyVaultCredential credentials)
   at Microsoft.Azure.KeyVault.KeyVaultClient..ctor(AuthenticationCallback authenticationCallback)
   at Microsoft.SqlServer.Management.AlwaysEncrypted.AzureKeyVaultProvider.SqlColumnEncryptionAzureKeyVaultProvider..ctor(AuthenticationCallback authenticationCallback) in d:\DsMain\DS_Main\Sql\mpu\shared\Security\AzureKeyVaultProvider\SqlColumnEncryptionAzureKeyVaultProvider.cs:line 56
   at AlwaysEncryptedKeyVaultIssue.Program.InitializeAzureKeyVaultProvider() in C:\Dev\AlwaysEncryptedKeyVaultIssue\AlwaysEncryptedKeyVaultIssue\Program.cs:line 21
   at AlwaysEncryptedKeyVaultIssue.Program.Main(String[] args) in C:\Dev\AlwaysEncryptedKeyVaultIssue\AlwaysEncryptedKeyVaultIssue\Program.cs:line 44
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

After a fair bit of Googling, I eventually came across up a fairly fresh Microsoft Connect ticket detailing the issue.

The issue really is not obvious and hats off to ‘lucavgobbi’ for diagnosing the root cause! Luckily it’s quite simple to remedy, although there are a few caveats.

For the purpose of this post, I created a simple test project that demonstrates the issue. It’s very easy to create using the following steps.

  1. Create a new console application (targeting 4.6.1)
  2. Install the following 2 Nuget packages:
    • Install-Package Microsoft.SqlServer.Management.AlwaysEncrypted.AzureKeyVaultProvider
    • Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory
  3. Copy this example Program.cs from the demo source.
  4. Run the app and watch it explode!

On running the application, you’ll be presented with the lovely exception from above. So what do?

As described in the Microsoft Connect issue, we need to switch the version of System.Net.Http from v4.1 to v4.0. It’s important to note that this dependency is added via Nuget as a dependency of which is the first gotcha. Run the following command to downgrade the package:

Update-Package System.Net.Http -Version 4.0.0

Run the application again and BOOM, it still fails… Ok…. The problem here lies in your app / web confg (App.config or web.config). An assembly binding redirect is added when the package is installed, redirecting to version 4.1.0, totally subverting our package downgrade. This is again simple to fix, change the dependency from this:

<dependentAssembly>
    <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
</dependentAssembly>

To look like this:

<dependentAssembly>
    <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.0.0.0" />
</dependentAssembly>

Now you’re good to go!

Browse the demo source code on GitHub.

Source Code for the application’s Program.cs:

namespace AlwaysEncryptedKeyVaultIssue
{
    using Microsoft.IdentityModel.Clients.ActiveDirectory;
    using Microsoft.SqlServer.Management.AlwaysEncrypted.AzureKeyVaultProvider;
    using System;
    using System.Collections.Generic;
    using System.Data.SqlClient;
    using System.Threading.Tasks;

    public class Program
    {
        private static ClientCredential clientCredential;

        static void Main(string[] args)
        {
            InitializeAzureKeyVaultProvider();
        }

        public static void InitializeAzureKeyVaultProvider()
        {
            var clientId = Guid.NewGuid().ToString();
            var clientSecret = "ITS_A_SECRET";

            clientCredential = new ClientCredential(clientId, clientSecret);

            var azureKeyVaultProvider = new SqlColumnEncryptionAzureKeyVaultProvider(GetToken);

            var providers = new Dictionary()
            {
                { SqlColumnEncryptionAzureKeyVaultProvider.ProviderName, azureKeyVaultProvider }
            };

            SqlConnection.RegisterColumnEncryptionKeyStoreProviders(providers);
        }

        public async static Task GetToken(string authority, string resource, string scope)
        {
            var authContext = new AuthenticationContext(authority);
            AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCredential);

            if (result == null)
                throw new InvalidOperationException("Failed to obtain the access token");

            return result.AccessToken;
        }
    }
}

Enforcing BuildAction on VS Project Items

Whilst creating an application to run the excellent SQL migration tool DbUp as part of a continuous deployment setup, I stumbled across a question I hadn’t thought about before. Is it possible to enforce a particular build action on certain files in a Visual Studio project? In this particular case, making sure all SQL files are marked as EmbeddedResource.

With DbUp, there are several ways of supplying SQL files to be run during a migration. In my case, I don’t know which set of scripts need to be run until the deployment is underway. After toying around with several ideas, I settled on the approach of embedding the SQL files in to the migration tool. I can then use the connection string that’s passed in to determine a specific folder of scripts to be executed. Having the scripts as embedded resources will allow me to package up the migration tool as an artefact that can be run only when needed, i.e. during a deployment and not during a build.

So how does it work?

There are several ways of adding custom targets to a project file. After Googling around I came across the ever helpful StackOverflow which offered up some solutions. The first approach is simple, but would require you to add a case for each of the BuildAction types that exist. And if a new one is added at some point, you have to update your code. No thanks, I’m too lazy for that.

The second approach looked much more maintainable by focusing on everything that isn’t what you want. The problem was that it didn’t work! Nothing would ever be matched. I wasn’t able to see any information in Visual Studio, so ran the build from the command line which told me the target was being run, but no elements were matched.

After lots of trial and error and head scratching, I came across another StackOverflow post detailing that you need to specify the namespace for elements in the XPath query. Of course!

The following code is placed in to the project file that you wish to run the check in.

<Target Name="EnsureSQLScriptsAreEmbeddedResource" BeforeTargets="BeforeBuild">
    <XmlPeek 
        XmlInputPath="$(MSBuildProjectFile)" 
        Namespaces="&lt;Namespace Prefix='msb' Uri='http://schemas.microsoft.com/developer/msbuild/2003'/&gt;" 
        Query="/msb:Project/msb:ItemGroup/*[not(self::msb:EmbeddedResource)]/@Include">
            <Output TaskParameter="Result" ItemName="AllItems" />
    </XmlPeek>
	
    <ItemGroup>
        <Filtered Include="@(AllItems)" Exclude="SqlTemplate.sql" Condition="'%(Extension)' == '.sql'" />
    </ItemGroup>
    <Error 
        Code="SQL" 
        ContinueOnError="ErrorAndContinue"
        File="$(MSBuildProjectDirectory)\%(Filtered.Identity)" 
        Text="All scripts require a BuildAction of EmbeddedResource" 
        Condition="'@(Filtered)'!=''" />
</Target>

What’s going on here then?

  1. The XmlPeek task will take the project file and run the XPath query, collecting all matching attributes and sticking them in to a new parameter called AllItems.
  2. The XPath query works by looking at child elements of each ItemGroup element, matching against any that are not of type EmbeddedResource.
  3. For each of these, it will take the value of the Include attribute and use that to populate AllItems.
  4. The ItemGroup that follows will filter the AllItems collection to include only things which end with ‘.sql’. These will be stored in a new parameter called Filtered.
  5. Finally, the Error target will be invoked if any items made it through. Including the ContinueOnError attribute makes it possible to see all of the files that cause the build to fail, rather than stopping on the first one.

Props to StackOverflow users jessehouwing and Teun D for getting me on the right path!

Xamarin: aapt.exe exited with code 1

After adding the powered-by-google-on-white.png images to a project I’m working on, I’m suddenly hit with ‘aapt.exe exited with code 1’ whilst building. Did Google just give me some bad images? Nope!

http://stackoverflow.com/questions/11440741/aapt-exe-exited-with-code-1-when-building-mono-for-android-project

It’s because of the use of the hyphens (-) in the filename. Remove them, rebuild and off you go!

Revised: WPF Elliptical Layout Control – 3D!

The post WPF Elliptical Layout Control – 3D! was way more popular than I ever could have imagined with people still viewing and downloading the code daily. Not bad for a post that’s 6 years old! However, as you can imagine the code and solution are pretty outdated now with a few unresolved issues. Given the amount of views it still gets, I decided it was time to revisit it and see if I can bring it up to date.

window

Continue reading

Visual Studio Crashes and How to Recover a Corrupted .cs File

In spite of using source control, sometimes it’s still possible to lose work due to the quirks of computers. At least you can mitigate this and only suffer losing a few hours of work, but still, when those few hours were a stroke of genius, the likes of which cannot be reproduced, you can’t help but shed a tear when all is lost. But fear not, here are 4 techniques that you can try to recover your code with before crying.

Continue reading

Beware: WebUtility.UrlEncode vs HttpUtility.UrlEncode

Whilst experimenting with hash-based message authentication code (HMAC) request signing for a REST API I’m working on, I noticed that sometimes a signature would fail to validate server side, despite the hashing algorithm on both ends following the exact same algorithm. Upon closer inspection, it turned out that the client side URL encoding method was returning lowercase HEX values and the server side, when computing the string for hashing, was returning uppercase HEX values. Fair enough! The client was written in PHP and the server is .Net. There’s no standard requirement for the casing of url encoded values so some differences should be expected across platforms.

But would you expect that difference between two methods in the .Net framework? Experience tells you yes, but we can be hopeful all the same!

Continue reading

Debugger.Launch (.Net)

Now and then I come across a feature in .Net that I have managed to completely miss over the years. Whilst trying to figure out why a unit test was failing when running it, but passing whilst debugging, I came across this nifty feature.

Debugger.Launch will attempt to break the program execution and give you the chance to attach a debugger so you can examine what’s going on.

if (condition)
{
    Debugger.Launch();
}

If the code is already running with a debugger attached, nothing will happen when the code is hit. If you want the code to break whether or not you have a debugger attached, you can use Debugger.Break instead.

Durable Task Framework – Testing a TaskActivity

Problem

You’ve created an orchestration using the Service Bus Durable Task Framework that makes use of several tasks, but you want to be able to test out each task in isolation.

Solution

The Durable Task Test Framework provides you with a utility class that makes creating and executing a new orchestration with a single task painless and easy. Whilst this isn’t a unit test by any stretch of the imagination, the MSTest framework is perfect for running your tasks one by one and making sure everything is as it should be.

How it Works

Creating and configuring an orchestration is relatively simple, but involves quite a few lines of code. If you’re just testing a single TaskActivity, there’s no point in doing that over and over again, so I created a simple helper class to take care of the grunt work!
Continue reading

Durable Task Framework – Complex Types as Task Input Parameters

In my last post, Using Unity With The Durable Task Framework, I mentioned that I had originally overlooked the fact that the data passed to and from your TaskActivity objects in an orchestration are serialized and sent over the wire. If you’re using simple types then this isn’t a problem, but usually we want to be able to pass in something with a little more information.

Continue reading