<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>William Tulloch</title>
    <description>The occasional thoughts and musing of a coding tragic</description>
    <link>http://wtulloch.github.io/</link>
    <atom:link href="http://wtulloch.github.io/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 21 Aug 2019 03:52:35 +0000</pubDate>
    <lastBuildDate>Wed, 21 Aug 2019 03:52:35 +0000</lastBuildDate>
    <generator>Jekyll v3.8.5</generator>
    
      <item>
        <title>Running MS Orleans in Docker locally</title>
        <description>&lt;p&gt;A note for my future self since clearly I forget what I have in the past.&lt;/p&gt;

&lt;p&gt;If you have pulled down the Microsoft Orleans &lt;a href=&quot;https://github.com/dotnet/orleans/tree/master/Samples/2.0/docker-aspnet-core&quot;&gt;Docker sample&lt;/a&gt; and then try to run it against the Azure Storage Emulator you may find yourself pulling your hair out wondering why it doesn’t work.&lt;/p&gt;

&lt;p&gt;Simply put if you try to use the default Azure Storage Emulator connection string it won’t work because the storage emulator endpoints (http://127.0.0.1:10000-2) are not accessible by default from external networks including the Docker network.&lt;/p&gt;

&lt;p&gt;The first time I tackled this I solved it following Rahul Gupta’s &lt;a href=&quot;https://rahulgupta.us/azure-storage-emulator-with-docker-on-windows/&quot;&gt;article&lt;/a&gt; which uses netsh proxy mapping. This solution works but is itself a fair bit of work to set-up and doesn’t persist if you restart your machine.&lt;/p&gt;

&lt;p&gt;The second option, which is a lot simpler, is just to replace &lt;code class=&quot;highlighter-rouge&quot;&gt;http://127.0.0.1&lt;/code&gt; with &lt;code class=&quot;highlighter-rouge&quot;&gt;host.docker.internal&lt;/code&gt;.
so in you code the connection string to the Azure Storage Emulator will be as follows:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-CSharp&quot;&gt;const string connectionString = &quot;DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://host.docker.internal:10000/devstoreaccount1;TableEndpoint=http://host.docker.internal:10002/devstoreaccount1;QueueEndpoint=http://host.docker.internal:10001/devstoreaccount1;&quot;;

&lt;/code&gt;&lt;/pre&gt;
</description>
        <pubDate>Tue, 20 Aug 2019 02:22:52 +0000</pubDate>
        <link>http://wtulloch.github.io/orleans,/docker/2019/08/20/Running-MSOrleans-locally-in-docker.html</link>
        <guid isPermaLink="true">http://wtulloch.github.io/orleans,/docker/2019/08/20/Running-MSOrleans-locally-in-docker.html</guid>
        
        
        <category>Orleans,</category>
        
        <category>Docker</category>
        
      </item>
    
      <item>
        <title>Notes on creating NPM packages&quot;</title>
        <description>&lt;p&gt;Call me stupid but I have really struggled with creating NPM packages. Not so much with the actual publishing (I mean how hard is &lt;code class=&quot;highlighter-rouge&quot;&gt;npm publish&lt;/code&gt;) but more around how to structure the project, what and how to include/exclude files and folders, et.al.&lt;/p&gt;

&lt;p&gt;I think in part it is because the idea of creating a package on occurs to me when I am part way through something I have been hacking on which usually means that project already has too many moving parts and is in no fit state for packaging. Nevertheless I start trawling through the node modules I have installed, reading OSS projects trying to grok what they have done all to just end up in a ball of frustration.&lt;/p&gt;

&lt;p&gt;Of course being overly ambitious in what I want to achieve doesn’t help (currently I am trying to write a create- package for &lt;code class=&quot;highlighter-rouge&quot;&gt;npm init&lt;/code&gt;) but also, to my way of seeing if you dig into existing packages, there is no single way of structuring them or determining what files to include (do you use, &lt;code class=&quot;highlighter-rouge&quot;&gt;dist&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;lib&lt;/code&gt; folders, should you include &lt;code class=&quot;highlighter-rouge&quot;&gt;src&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;test&lt;/code&gt;, etc).&lt;/p&gt;

&lt;p&gt;Now the clouds have cleared. The other night I found this article by Bruno Krebs on the auth0 website: &lt;a href=&quot;https://auth0.com/blog/developing-npm-packages&quot;&gt;Developing and Publishing an NPM Package&lt;/a&gt;. To my mind, as walk through tutorial, this article is the clearest guidance I have come across in regard to setting up and creating NPM packages and worth working through.&lt;/p&gt;

&lt;p&gt;Next steps for me. Adapting for working with TypeScript and exploring different CI options (the tutorial uses Travis CI but CircleCI seems to be gaining traction. Also Azure Devops is to be considered).&lt;/p&gt;
</description>
        <pubDate>Wed, 26 Jun 2019 10:22:52 +0000</pubDate>
        <link>http://wtulloch.github.io/npm/2019/06/26/npm-packaging-notes.html</link>
        <guid isPermaLink="true">http://wtulloch.github.io/npm/2019/06/26/npm-packaging-notes.html</guid>
        
        
        <category>NPM</category>
        
      </item>
    
      <item>
        <title>Blazor - Setting up a JSInterop library using TypeScript</title>
        <description>&lt;h2 id=&quot;intro&quot;&gt;Intro&lt;/h2&gt;
&lt;p&gt;At some point, if you have been playing around with Blazor, you may consider creating a Blazor JsInterop library.
If you create a new Blazor library project (&lt;code class=&quot;highlighter-rouge&quot;&gt;dotnet new blazorlib&lt;/code&gt; ) the project assumes you use JavaScript but what if want use TypeScript to write your interop code?&lt;/p&gt;

&lt;p&gt;If you look through the Blazor source code will see that is exactly what is being done for the interop libraries where both TypeScript and webpack is being used. What is not immediately obvious is how this being wired together.&lt;/p&gt;

&lt;p&gt;The rest of this post is my attempt at documenting how to get this working to save time in the future plus some additional notes around creating JSInterop libraries for Blazor&lt;/p&gt;

&lt;h2 id=&quot;getting-started&quot;&gt;Getting started&lt;/h2&gt;
&lt;p&gt;NOTE: This is not of my own making but has been dug out of the Blazor solution (Microsoft.AspNetCore.Blazor.Browser.JS). I just thought it would be worth documenting it since the solution was new to me and would be worth making more visible.&lt;/p&gt;

&lt;p&gt;In summary the steps requred are as follows:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;initialise npm&lt;/li&gt;
  &lt;li&gt;import webpack and associated libraries&lt;/li&gt;
  &lt;li&gt;create a webpack configuration file&lt;/li&gt;
  &lt;li&gt;Edit the proj file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I am, for the sake of expendency, going to assume that have node and npm installed. I will also assume you have the Blazor pieces installed but if not you will need to install the following:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://go.microsoft.com/fwlink/?linkid=873092&quot;&gt;.NET Core 2.1 SDK&lt;/a&gt; (2.1.402 or later).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://go.microsoft.com/fwlink/?linkid=873093&quot;&gt;Visual Studio 2017&lt;/a&gt; (15.8 or later) with the &lt;em&gt;ASP.NET and web development&lt;/em&gt; workload selected.&lt;/li&gt;
  &lt;li&gt;The latest &lt;a href=&quot;https://go.microsoft.com/fwlink/?linkid=870389&quot;&gt;Blazor Language Services extension&lt;/a&gt; form the Visual Studio Marketplace&lt;/li&gt;
  &lt;li&gt;The Blazor templates on the command-line:    &lt;br /&gt;
&lt;code class=&quot;highlighter-rouge&quot;&gt;dotnet new -i Microsoft.AspNetCore.Blazor.Templates&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;create-a-new-blazor-library&quot;&gt;Create a new Blazor library&lt;/h3&gt;
&lt;p&gt;There isn’t a Visual Studio template for a Blazor library so to create one you use the dotnet cli:
&lt;code class=&quot;highlighter-rouge&quot;&gt;dotnet new blazorlib -o ExampleLibrary&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;add-node-modules&quot;&gt;Add node modules&lt;/h3&gt;
&lt;p&gt;While we are doing command line stuff &lt;code class=&quot;highlighter-rouge&quot;&gt;cd&lt;/code&gt; to the library project folder.&lt;/p&gt;

&lt;p&gt;First initialise npm  &lt;br /&gt;
&lt;code class=&quot;highlighter-rouge&quot;&gt;npm init -y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next install the following node modules:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;webpack&lt;/li&gt;
  &lt;li&gt;wepack-cli&lt;/li&gt;
  &lt;li&gt;typescript&lt;/li&gt;
  &lt;li&gt;ts-loader&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;npm i webpack webpack-cli typescript ts-loader -D&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once that is done open up the project in Visual Studio.&lt;/p&gt;

&lt;h3 id=&quot;configuring-webpack&quot;&gt;Configuring webpack&lt;/h3&gt;
&lt;p&gt;Add a new &lt;code class=&quot;highlighter-rouge&quot;&gt;webpack.config.js&lt;/code&gt; to the project and use the following as the basic configuration (replacing the entry values).&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;const path = require('path');
const webpack = require('webpack');

module.exports = (env, args) =&amp;gt;({
    resolve: {
        extensions: ['.ts', '.js']
    },
    devtool: args.mode === 'development' ? 'inline-source-map' : 'none',
    module: {
        rules: [
            {
                test: /\.ts?$/,
                loader: 'ts-loader'
            }
        ]
    },
    entry: {
        &quot;indexedDb.Blazor&quot;: './src/InitialiseIndexDbBlazor.ts'
    },
    output: {
        path: path.join(__dirname, '/dist'),
        filename: '[name].js'
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;update-the-project-file&quot;&gt;update the project file&lt;/h3&gt;
&lt;p&gt;Next open the project file and use the following example has a basic guideline for the changes that need to be made.&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;Project&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Sdk=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Microsoft.NET.Sdk&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;netstandard2.0&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;BlazorLinkOnBuild&amp;gt;&lt;/span&gt;false&lt;span class=&quot;nt&quot;&gt;&amp;lt;/BlazorLinkOnBuild&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptCompileBlocked&amp;gt;&lt;/span&gt;true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptCompileBlocked&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;TypeScriptToolsVersion&amp;gt;&lt;/span&gt;Latest&lt;span class=&quot;nt&quot;&gt;&amp;lt;/TypeScriptToolsVersion&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;DefaultItemExcludes&amp;gt;&lt;/span&gt;${DefaultItemExcludes};dist\**;node_modules\**&lt;span class=&quot;nt&quot;&gt;&amp;lt;/DefaultItemExcludes&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;NoWarn&amp;gt;&lt;/span&gt;CS2008&lt;span class=&quot;nt&quot;&gt;&amp;lt;/NoWarn&amp;gt;&lt;/span&gt;

    
     &lt;span class=&quot;c&quot;&gt;&amp;lt;!--VS's FastUpToDateCheck doesn't consider .ts file changes, so it's necessary to disable it to get incremental builds to work correctly (albeit not as fast as if FastUpToDateCheck did work for them)--&amp;gt;&lt;/span&gt; 
    
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;DisableFastUpToDateCheck&amp;gt;&lt;/span&gt;true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/DisableFastUpToDateCheck&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Include=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Microsoft.AspNetCore.Blazor.Build&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Version=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0.6.0&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;WebpackInputs&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Include=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;**\*.ts&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Exclude=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dist\**;node_modules\**; **\*.d.ts&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
  
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Target&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EnsureNpmRestored&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Condition=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;!Exists('node_modules')&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Message&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Importance=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;high&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Text=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Restoring dependencies using 'npm'. This may take several minutes...&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Command=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;npm install&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;nt&quot;&gt;&amp;lt;Target&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;RunWebpack&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;AfterTargets=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ResolveReferences&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Inputs=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;@(WebpackInputs)&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Outputs=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dist\indexedDb.Blazor.js&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;DependsOnTargets=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EnsureNpmRestored&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;RemoveDir&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Directories=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dist&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Command=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;npm run build:debug&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Condition=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;'$(Configuration)' == 'Debug'&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class=&quot;nt&quot;&gt;&amp;lt;Exec&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Command=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;npm run build:production&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Condition=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;'$(Configuration)' != 'Debug'&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;EmbeddedResource&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;Include=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;dist\**\*.js&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;LogicalName=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;blazor:js:%(RecursiveDir)%(Filename)%(Extension)&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Target&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;update-npm-config&quot;&gt;Update npm config.&lt;/h3&gt;
&lt;p&gt;Finally update the npm config (package.json) and add the following to the script node.&lt;/p&gt;
&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;build:debug&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;webpack --mode=development&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;build:production&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;webpack --mode=production&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
   
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In theory once this is all done running build should generate the JavaScript output.&lt;/p&gt;

</description>
        <pubDate>Sun, 30 Sep 2018 10:22:52 +0000</pubDate>
        <link>http://wtulloch.github.io/blazor;/.net/2018/09/30/Blazor-JSInteropWithTypeScript.html</link>
        <guid isPermaLink="true">http://wtulloch.github.io/blazor;/.net/2018/09/30/Blazor-JSInteropWithTypeScript.html</guid>
        
        
        <category>Blazor;</category>
        
        <category>.NET</category>
        
      </item>
    
      <item>
        <title>Compodoc - Documentation for Angular</title>
        <description>&lt;h2 id=&quot;so-sue-me&quot;&gt;So sue me&lt;/h2&gt;
&lt;p&gt;Okay so I am probably a bit a late to the party but just found this library for documenting Angular projects called &lt;a href=&quot;https://compodoc.github.io/compodoc/&quot;&gt;Compodoc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In all it took about 15 minutes to get up an running on an existing project. The great thing with it allows you to step back from the code and get a sense of the bigger picture.&lt;/p&gt;
</description>
        <pubDate>Fri, 22 Dec 2017 07:22:52 +0000</pubDate>
        <link>http://wtulloch.github.io/angular/2017/12/22/documenting-angular.html</link>
        <guid isPermaLink="true">http://wtulloch.github.io/angular/2017/12/22/documenting-angular.html</guid>
        
        
        <category>Angular</category>
        
      </item>
    
      <item>
        <title>Running Angular unit tests in VSTS - PhantomJs is dead to me</title>
        <description>&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;A current project I am working on is a hybrid Angular 4 and Asp.NET core 2.0 web application. 
CI has been set up on Visual Studio Team Services (VSTS) and as part of the build we wanted to run the Angular unit tests (logical really).&lt;/p&gt;

&lt;p&gt;Did a bit of research and the recommended approach, in summary, is to install as dev dependencies phantomjs-prebuilt and karma-phantomjs-launcher, configure the karma config to include phantomjs as a browser. Then on VSTS add a new  command line task to run angular-cli (ng) with the following arguments:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    test --watch=false --single-run=true --reporters=junit,progress --browsers=PhantomJs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Cool, do an initial build and the test run. But then a couple of days later this happened:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   SyntaxError: Unexpected token 'const'
  at http://localhost:9876/_karma_webpack_/vendor.bundle.js:1318
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;What the f***!.&lt;/p&gt;

&lt;p&gt;After much swearing, comparing commits and experiementation found the problem, PhantomJS only provides Javascript support upto ES5 beyond that it throughs a wobbly.&lt;/p&gt;

&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;/h2&gt;
&lt;p&gt;The simple solution is to abandon PhantomJS and use Headless Chrome. 
Here is how it’s done.&lt;/p&gt;

&lt;p&gt;install &lt;a href=&quot;https://github.com/GoogleChrome/puppeteer&quot;&gt;GoogleChrome Puppeteer&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  yarn add puppeteer
  # npm i puppeteer -D
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Modify Karma.config.js. add the following line above the module.exports statement&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;    process.env.CHROME_BIN = require('puppeteer').executablePath();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Update the browser to include ChromeHeadless&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt;    browsers: ['Chrome', 'ChromeHeadless']
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To test it locally run the following command.&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;   ng test --watch=false --single-run=true --reporters=junit,progress --browsers=ChromeHeadless
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;At this point it should all work.&lt;/p&gt;

&lt;p&gt;Now on VSTS, in the build definition (and this assumes you already have a command to run npm install) add a new command line task.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://wtulloch.github.io/assets/ng-test-task.png&quot; alt=&quot;sample ng test task&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Done! angular unit tests are now running successfully in VSTS.&lt;/p&gt;

&lt;p&gt;The final piece is to publish the test results.&lt;/p&gt;

&lt;p&gt;Back in the karma.config.js modify or add the jUnitReporter configuration as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-JavaScript&quot;&gt; junitReporter:{
      outputDir: '',
      outputFile: 'test-client.xml'
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then in the VSTS build definition add a new Publish Test Results task and complete it has in the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://wtulloch.github.io/assets/publish-ng-test-results.png&quot; alt=&quot;Junit publish test results&quot; /&gt;&lt;/p&gt;

</description>
        <pubDate>Thu, 21 Dec 2017 23:22:52 +0000</pubDate>
        <link>http://wtulloch.github.io/vsts/angular/unit-tests/2017/12/21/vsts-angular-unittests.html</link>
        <guid isPermaLink="true">http://wtulloch.github.io/vsts/angular/unit-tests/2017/12/21/vsts-angular-unittests.html</guid>
        
        
        <category>VSTS</category>
        
        <category>Angular</category>
        
        <category>Unit-Tests</category>
        
      </item>
    
      <item>
        <title>Ruminations on five years presenting at DDD Melbourne</title>
        <description>&lt;p&gt;A few weeks ago, along with Aaron Powell, I was recognised for being voted up five years in a row for DDD melbourne. 
Aaron has already blogged on his experience over those five years &lt;a href=&quot;http://www.aaron-powell.com/posts/2014-07-22-5-years-of-dddmelb.html&quot;&gt;5 Years of DDD Melbourne&lt;/a&gt;
 and not to be out done I thought I would chip in with my two cents worth.&lt;/p&gt;

&lt;p&gt;In this post I am going to reflect back on those five years and look at some of the things I have learnt.&lt;/p&gt;

&lt;p&gt;##2010 - Code Contracts
When the first DDD Melbourne was announced I thought this would be a bit of a hoot so tossed my hat into the ring.&lt;/p&gt;

&lt;p&gt;I had over the years done presentations before, including a senate committee hearing once, and in a previous life I had been a musician so I had some familiarity with standing in front of a room full of people and making a fool of myself. A technical presentation in front of your peers though that is a different kettle of fish.&lt;/p&gt;

&lt;p&gt;This was around the time that Visual Studio 2010 had just been released and out of some kind of perversity proposed a talk on Code Contracts. To be honest I didn’t think this would get voted up but it did.&lt;/p&gt;

&lt;p&gt;For a first-timer the talk went well. I was lucky in my choice of topic; Code Contracts is/was a reasonably self-contained so I avoided the classic first-time presenters trap of running out of presentation time though it was a close run thing.&lt;/p&gt;

&lt;p&gt;##2011 - Securing web services (WCF) with WIF
I had been an early fan of claims-based identity and in particular working with WIF. At the time I did this talk I had been working at client where I had developed a custom STS to issue SAML tokens for securing WCF services and it was this work that I used for the basis of this talk.&lt;/p&gt;

&lt;p&gt;My intention was to take the audience through the entire process; from creating a custom Security Token Service (STS) through to using it to secure a WCF service. In hindsight I probably overreached a little bit on this one and tried to cover too much which meant I ended rushing towards the end.
This was a good learning experience through. Some of the keys things that I learnt were:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Don’t be too clever&lt;/strong&gt; - I invested too much energy creating a back story for my presentation and the “humour” of it was lost on anyone who didn’t know anything about the New York art scene in the 60’s (really doesn’t anyone know about Andy Warhol and The Factory).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Too much code&lt;/strong&gt; - I ended up writing too much boiler plate code which really didn’t add anything to the talk. Additionally by using code snippets the audience really didn’t get a chance to understand what was happening.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;##2012 - What’s new in .NET 4.5
At the time of this talk I was co-authoring a book on .NET 4.5 with two of my colleagues which formed the basis for this talk. This was what I think of as a shopping list presentation.&lt;/p&gt;

&lt;p&gt;For this talk I took eight of the key new features in .NET 4.5 and gave a brief rundown on each of them. Again, in hindsight, I think the code examples didn’t always hit the mark. This was in part due to the nature of shopping list talks, since you are essentially jumping from topic to the next without any really story arc. This meant the demo code couldn’t be built up and thus giving the audience a context for the examples which were occasionally a bit laboured.&lt;/p&gt;

&lt;p&gt;##2013 - Securing .NET WEB API
I was personally very happy with this talk. The story arc and timing all came together. No rushing to get to the end and all the demos made sense and kept the audience engaged.&lt;/p&gt;

&lt;p&gt;One of the key things I did this time was to show key code concepts in my slides rather than in Visual Studio. This allowed me to remove any extraneous information and keep the focus on what was important. This also meant that when running the code demos the audience already had some context for what was being shown.&lt;/p&gt;

&lt;p&gt;##2014 - Don’t Say F*$k to the Client and other war stories
I had been playing around with the idea of doing a non-technical talk for a while and this was the result. The intention had been for a light-hearted talk but as I worked up the stories things took a more serious tone.&lt;/p&gt;

&lt;p&gt;Though this was probably the hardest talk I have done, there was no code to hide behind, on a personal level I think it was one of my best and the feedback from the audience was positive.&lt;/p&gt;

&lt;p&gt;The hardest part of developing this talk was finding a “voice” for the presentation and I spent a lot of time writing, editing and rejecting stories to discover it.&lt;/p&gt;

&lt;p&gt;##In Summary
I love presenting. It is challenging, requires work and I would be lying if I didn’t admit to being scared shitless every time I did it but the payoff has always been worth it.&lt;/p&gt;

&lt;p&gt;The following is ragtag collection of some of the things I have learnt over the last five years.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Avoid dot points.&lt;/strong&gt;&lt;br /&gt;
Too often I had attended talks where every slide shown was crowded out with dot points. Effect of this is that your audience has to split their focus between what you are saying and reading what is on the screen. My preference is to use slides primary as context markers.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Words are a visual element.&lt;/strong&gt;&lt;br /&gt;
Think of words as images as opposed to text on a page.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Coding in front of an audience is hard&lt;/strong&gt;&lt;br /&gt;
You do it everyday, how hard can it be. Bloody hard, especially when you make a mistake and half the audience are shouting out suggestions. &lt;br /&gt;
 If you are going to do code examples you really need to plan ahead and keep it concise. Also practice coding standing up, very rarely do you do a talk sitting down. Finally learn to talk while you writing code. There is nothing worse then the silence of an auditorium while you bash away at a keyboard for five minutes. Keep the audience engaged, explain what you are doing.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Giving a talk is entertainment not a form of punishment.&lt;/strong&gt;&lt;br /&gt;
Yes it is a technical talk but that is no reason to be boring.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;In the beginning get all your ideas down and then edit ruthlessly.&lt;/strong&gt;&lt;br /&gt;
It is easy to overload a talk with unnecessary detail. When I first start a working on a talk I use a mind map to capture as much as I can and then start shaping the story I want to tell.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Writing demo code takes time.&lt;/strong&gt; &lt;br /&gt;
Give yourself enough time to get it right and always have a fall-back position if you intend to code live in case things don’t go as planned.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Don’t read from your slides, talk to them.&lt;/strong&gt;&lt;br /&gt;
There is nothing more tedious then a presenter who recites word for word the content of their slides. Additionally this means you end up not engaging the audience (see the next point).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Talk to your audience.&lt;/strong&gt;&lt;br /&gt;
When people attend your presentation they are there to hear you talk so do them the courtesy of engaging with them.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;You will always be nervous before you present.&lt;/strong&gt; &lt;br /&gt;
I always have this moment, about an hour out from when I have to present, when the weight of stupidity descends. The thing is if you have done the prep it should all fall into place.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Practise your talk.&lt;/strong&gt; &lt;br /&gt;
This is not one of my strong points, let’s face talking aloud to yourself can feel a bit weird. The thing is it doesn’t have to be word perfect but it will help you get the talk’s rhythm. For the last talk I did I practiced my talk by dictating to the computer. This allowed me to practise my delivery as well as fine tune the content.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Sun, 17 Aug 2014 10:22:52 +0000</pubDate>
        <link>http://wtulloch.github.io/stuff/2014/08/17/On-five-presenting-at-ddd.html</link>
        <guid isPermaLink="true">http://wtulloch.github.io/stuff/2014/08/17/On-five-presenting-at-ddd.html</guid>
        
        
        <category>Stuff</category>
        
      </item>
    
      <item>
        <title>The ng-include, the $watch and the child scope</title>
        <description>&lt;p&gt;“Beware the child scope for it will bite you on the arse”&lt;/p&gt;

&lt;p&gt;Even after eight months on a project that is using AngularJS the most I can claim is I know enough to be dangerous and to be lulled into a false sense of security. This false sense of security lead to no small amount of hair-pulling the over day.&lt;/p&gt;

&lt;p&gt;The issue I encountered involved a custom directive we have for auto-completing values in a text field. The field itself is used to look-up hospitals. As the user types in a name the directive displays a list of possible matches and when the user selects one it takes the corresponding hospital object and assigns it to a property on the scope that was passed into the directive. A watch is set-up in the scope to listen to the property so that when it changes it extracts values from the hospital object and displays them to the user. To express this is in code, the controller had the following:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var controller = function ($scope, patientReferralService) {
        $scope.selectedPatientHospital = undefined;

        $scope.$watch(&quot;selectedPatientHospital&quot;, function (newValue, oldValue) {
            // if we have a hospital then populate required values. 
            if (newValue) {
                $scope.referral.Patient.Location.Hospital = newValue.Nickname;
                $scope.referral.Patient.Location.HospitalId = newValue.Id;
                if (newValue.hasOwnProperty(&quot;SwitchboardPhone&quot;)) {
                    $scope.referral.Patient.Location.SwitchboardNumber = newValue.SwitchboardPhone;
                }
            }
        });
        //rest of code removed for brevity
    };
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the html:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;input type=&quot;text&quot; data-ng-model=&quot;referral.Patient.Location.Hospital&quot; id=&quot;inputHospitalName&quot; name=&quot;inputHospitalName&quot;
           data-campus-auto-complete=&quot;selectedPatientHospital&quot; data-source=&quot;campuses&quot;
    /&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All well and good, and this has been working just fine until I decided extract some of the UI into a partial view and add it to the form as an ng-include. Now when I ran the application the $watch was not being fired.&lt;/p&gt;

&lt;p&gt;Just to show how much I still have to learn, what I didn’t know is that when you use ng-include (or  ng-repeat, ng-include, ng-switch, ng-view, ng-controller) is that Angular creates a new/child scope which prototypically inherits from its parent scope.&lt;/p&gt;

&lt;p&gt;This is usually not a problem until you either attempt a 2-way binding on a primitive value defined on the parent or, as in my case, try to add a new instance of an object defined on the parent. The problem is not with Angular but with how prototypical inheritance works in JavaScript.&lt;/p&gt;

&lt;p&gt;In essence what happens, why my code no longer worked, is that when you assign a value to a primitive on the child, instead of walking the inheritance tree of the child to find the corresponding property it creates a new property which shadows/hides the parent property.&lt;/p&gt;

&lt;p&gt;The solution, once I understood this was fairly simple. Rather than having a property on the parent that the directive changed directly I created an object that would have properties that could assigned to and watched. The modified code looks something like this:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;var controller = function ($scope, patientReferralService) {
$scope.thingsToWatch = {
    selectedPatientHospital: undefined,
    selectedPlannedDestinationSite: undefined
};
$scope.$watch(&quot;thingsToWatch.selectedPatientHospital&quot;, function (newValue, oldValue) {
    // if we have a hospital then populate required values. 
    if (newValue) {
        $scope.referral.Patient.Location.Hospital = newValue.Nickname;
        $scope.referral.Patient.Location.HospitalId = newValue.Id;
        if (newValue.hasOwnProperty(&quot;SwitchboardPhone&quot;)) {
            $scope.referral.Patient.Location.SwitchboardNumber = newValue.SwitchboardPhone;
        }
    }
});
//rest of code removed for brevity
};

&amp;lt;div&amp;gt;
    &amp;lt;input type=&quot;text&quot; data-ng-model=&quot;referral.Patient.Location.Hospital&quot; id=&quot;inputHospitalName&quot; name=&quot;inputHospitalName&quot;
data-campus-auto-complete=&quot;thingsToWatch.selectedPatientHospital&quot; data-source=&quot;campuses&quot;/&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you want a more in-depth explantation of the problem, I found this article really helpful &lt;a href=&quot;https://github.com/angular/angular.js/wiki/Understanding-Scopes#wiki-ngInclude&quot;&gt;Understanding Scopes&lt;/a&gt;.&lt;/p&gt;

</description>
        <pubDate>Tue, 18 Feb 2014 10:22:52 +0000</pubDate>
        <link>http://wtulloch.github.io/angularjs/javascript/2014/02/18/ng-include-watch-childscope.html</link>
        <guid isPermaLink="true">http://wtulloch.github.io/angularjs/javascript/2014/02/18/ng-include-watch-childscope.html</guid>
        
        
        <category>Angularjs</category>
        
        <category>JavaScript</category>
        
      </item>
    
      <item>
        <title>Weird shit with WebAPI, Basic Authentication &amp; Session Authentication Modules</title>
        <description>&lt;p&gt;On a current client’s site we have the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;A custom login REST service endpoint that allows the passing in of a username and password using basic authentication and issue a Json Web Token (JWT).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Another REST service to update data. This requires the JWT to be passed in with the call as a Bearer token in the Authorization header.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Within the web application itself this has been working fine XHR and adding the Authorization header with the appropriate value where required.&lt;/p&gt;

&lt;p&gt;This has all been working fine.&lt;/p&gt;

&lt;p&gt;Recently the client has requested that their clients would like to have the ability to update data from their own systems rather than entering it through the website. Fine, not a problem since the REST services already exist. I thought I would knock up a quick proof of concept just (as a console app) to confirm that all works as expected and to provide guidance for external users.&lt;/p&gt;

&lt;p&gt;Now I have done this numerous times and here is a sample of the code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;	
&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TokenResponse&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetAuthenticationToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HttpClient&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;Uri&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loginUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetEncoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;iso-8859-1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;TokenResponse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenResponse&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authHeader&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;AuthenticationHeaderValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Basic&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;Convert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToBase64String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetBytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{0}:{1}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;testUser&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;somepassword&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))));&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DefaultRequestHeaders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Authorization&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authHeader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DefaultRequestHeaders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Accept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ParseAdd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loginUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsSuccessStatusCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ReadAsStringAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;tokenResponse&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;JsonConvert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DeserializeObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TokenResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StatusCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Thing is every time I ran it the call to the login endpoint returned a 401.
Okay clearly I am doing some wrong. Fire up Fiddler and check the header. Nope all good I have an Authorization header. Okay next debug into the delegating handler that handles the basic authentication. Inspect the request header and I have no Authorization header. Somewhere between making the call and hitting the delegating handler the Authorization header has been nuked.&lt;/p&gt;

&lt;p&gt;As you could appreciate this is a little disconcerting and after a few hours of exploration and hair pulling downright frustrating. And then I noticed this in the web.config.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;add&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;SessionAuthenticationModule&quot;&lt;/span&gt; 
     &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
 &lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Hmmm at some point we must have playing around with the idea of using WIF for our authentication. Surely that can’t be causing the problem but with nothing to lose at this point I decided to comment it out. Ran my test app and it all worked.&lt;/p&gt;

&lt;p&gt;Now why this was nuking my Authorization header I am not sure. I have debugged into the class but can’t Identity where it is doing it but removing it has fixed the problem so I am going to leave it at.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note to self:&lt;/strong&gt; remember to removed unneeded settings from the web.config&lt;/p&gt;
</description>
        <pubDate>Wed, 12 Feb 2014 10:22:52 +0000</pubDate>
        <link>http://wtulloch.github.io/webapi/2014/02/12/WeirdShitWithWebApi.html</link>
        <guid isPermaLink="true">http://wtulloch.github.io/webapi/2014/02/12/WeirdShitWithWebApi.html</guid>
        
        
        <category>WebApi</category>
        
      </item>
    
      <item>
        <title>Unit testing aynomous types</title>
        <description>&lt;p&gt;A colleague had a case where he needed to test the values assigned in an anonymous type returned by a class. With anyonmous types the .Equals() behaves a little a differently from typed objects. To paraphrase &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/bb397696.aspx&quot;&gt;MSDN&lt;/a&gt; if, within the same assembly, two or more anonymous object initialisers define a sequence of properties that are equal in sequence, name and type the compiler treats them as instances of the same type. For example if we wrote the following test you would find it will pass.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;na&quot;&gt;[Fact]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CompareTwoAnonymousTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Cale&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Cale&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;On the other hand if we swapped the properties around on one of the initialisers the test would fail (in fact it would raise a compiler error).&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;   
&lt;span class=&quot;na&quot;&gt;[Fact]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CompareTwoAnonymousTypesWithDifferentPropertySequence&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Cale&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;John&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Cale&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;Assert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;But this not the real issue. As started previously, anonymous must be in the same assembly for them to be considered the same type. Given we have the following class in another assembly:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;    
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TestClass&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetAnonymousType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Lou&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Reed&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;any attempt to validate the return value in a unit test will fail.&lt;/p&gt;

&lt;p&gt;So what the solution?&lt;/p&gt;

&lt;p&gt;A great tool for testing two instances of a given class to ensure that their property values are equal is &lt;a href=&quot;https://github.com/dennisdoomen/fluentassertions&quot;&gt;FluentAssertions&lt;/a&gt;.  FluentAssertions has a method called ShouldBeEquivalentTo() which does an object graph comparison. For example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;na&quot;&gt;[Fact]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CompareTwoInstanceOfPerson&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;James&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Brown&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;James&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Brown&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ShouldBeEquivalentTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This also works for comparing two different classes that have the same properties such as comparing a dto with the source of the data.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;  
&lt;span class=&quot;na&quot;&gt;[Fact]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;PersonDtoShouldEqualPerson&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Lou&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Reed&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;personDto&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PersonDto&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Lou&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Reed&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;personDto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ShouldBeEquivalentTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;So does this help with my colleague’s problem? Will yes it does but with one twist. By convention, with unit tests, we test the actual value against the expected value. For example actual.ShouldBeEquivalentTo(expected). When evaluating anonymous types we need to flip it around and test the expected value.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;na&quot;&gt;[Fact]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ObjectShouldBeEquivalentToReturnValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tester&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;TestClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Ted&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Dancer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tester&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetAnonymousType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ShouldBeEquivalentTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;actual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</description>
        <pubDate>Sat, 01 Feb 2014 10:22:52 +0000</pubDate>
        <link>http://wtulloch.github.io/c%23/2014/02/01/Unit-Testing-Aynonmous-Types.html</link>
        <guid isPermaLink="true">http://wtulloch.github.io/c%23/2014/02/01/Unit-Testing-Aynonmous-Types.html</guid>
        
        
        <category>C#</category>
        
      </item>
    
  </channel>
</rss>
