Sprydon

Richard Harding's spot on the web

AspNet Web API 2.2 Odatav4, Swagger, Swashbuckle and Glimpse

Recording this here as I know I’ll hit this again on some other project…

I wanted to add Swagger api documentation to an existing OData v4 API, something I had done a couple of times before using the Swashbuckle and Swashbuckle.OData projects. But for some reason this time it would not work  - the json doc and the SwaggerUI were there but there was no content – the paths collection in the swagger doc was empty – I suspected it had something to do with the way Swashbuckle.OData was building the API descriptions but nothing looked odd in teh way I had configured the OData routes. In the end I cloned out the Swashbuckle.OData project and built locally so I could debug (this was further hampered by the project using Code Contracts – a good thing, but not currently supported in VS2017).

I quickly traced the problem to an extension method:

internal static IEnumerable<ODataRoute> GetODataRoutes(this HttpConfiguration httpConfig)
        {
            Contract.Requires(httpConfig != null);

            return FlattenRoutes(httpConfig.Routes).OfType<ODataRoute>();
        }

The route collection had a count of 12 but the call to select routes of type ODataRoute was returning zero results – when I examined the private field holding the collection the routes were all of type Castle.Proxies.RouteProxy – a quck Google search turned up the answer in this groups message – I had added Glimpse and in the version I had they replaced the routes with proxies  - this has been fixed in versions of Glimpse.AspNet later than 1.8.0 (the version I was on) – updating to a later version fixed my Swagger issues

IIS Express “Access Denied” Cryptographic Exception when creating X509 cert from file

Adding this here so I can find it when it happens again!

After a recent Windows 10 update (I’m in the insider fast ring so who knows what changed) I found that an ASP.Net MVC app no longer ran under IIS Express. As part of the app code it was creating an X509 Certificate by loading a pfx file from the file system

var signingCertPath = @"D:\FooCert.pfx";

var cred = new X509SigningCredentials(new X509Certificate2(signingCertPath, "FooPassword", X509KeyStorageFlags.MachineKeySet));

This was resulting in a Cryptographic exception being thrown with the message “Access Denied” and little else to go on.

I suspected is was permissions on the machine key folder (eg C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys) but adding my account to that folder with full control made no difference however, removing the MachineKeySet flag allowed the cert to be loaded.

I eventually resorted to using procmon (sysinternals procmon) to see what was generating the access error – it turned out to be the C:\ProgramData\Microsoft\Crypto\Keys folder — adding my account with full control on that folder allowed the cert to load (still no idea why an update had changed this)

DotNet Core testing local cli tools

The new xml project file format csproj includes the facility to restore a package for use in the build process (see docs here) it replaces the

When building a tool package that a project could use its not immediately obvious how to test the unpublished local version of the tool

Given an entry like

<ItemGroup>
  <DotNetCliToolReference Include="SpecFlow.NetCore" Version="1.0.0-rc8" />
</ItemGroup>

The build process will restore the SpecFlow.NetCore package from Nuget rather than use a copy on the local file system. The discussion on this issue and here on the cli github repo outlines the option I eventually ended up using

Pack the tool package under development specifying a suitable local area eg

dotnet pack -o ../mynugetcache

Then in the consuming project add a Nuget.Config file to add the local area as an addition feed eg

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="test-packages" value="../mynugetcache" />
  </packageSources>
</configuration>

I found that as my consuming projects had already installed the public version I needed to delete from my local cache

%UserProfile%\.nuget\packages

And also delete the lock files in the projects obj folder

Visual Studio 2017RC Unable to repair or uninstall a fix

Recently while trying to update from RC3 of Visual Studio 2017 to RC4 I managed to get into a loop whereby the installer (which is a vast improvement) could not repair or uninstall  VS2017 – even attempting to remove via the Control Panel – Programs and Features didn’t seem to work – each time I re-ran the installer to try and get the latest version it detected the existing broken install but was unable to repair or remove.

I found the answer on the forums here  - there is a tool InstallCleanup.exe which lives in C:\Program Files (x86)\Microsoft Visual Studio\Installer\resources\app\layout

I needed to run it as administrator  - the first attempt didn’t seem to work  - it seems to fail silently if it doesn’t have sufficient privileges to remove packages and registry keys. Once I ran it I could start the installer and carry out a clean install of RC4 – since RC3 I’ve been using it as my main IDE and seems pretty stable

Custom activity to tag sources in git from TFS

The problem

I want to be able to trace an assembly back to the source that was used to build it, the way I usually accomplish this is to have the continuous integration server set the assembly version (including file version) based on some auto incrementing build number and incorporate that same build number in a source control label. Then given an assembly I can use its version to pull the source that built it.

However while there is a built in activity to label workspace files for the TFS Source control repository it doesn’t seem to support the Git repository option which seems like a strange omission.

The TFS Community extensions don’t have anything suitable either

The Solution – Custom Activity & Libgit2sharp

I took a look at the source of the built in activities that interact with Git – especially the InitializeEnvironment activity that clones the repository. They all use the libgit2sharp library to interact with the TFS git repository, so using the examples on project wiki I put together a quick test to check I could apply and push a tag

   1:  using (var repo = new Repository(@"c:\repos\MyTestRepo"))
   2:              {
   3:                  var tagName = "MyTagName";
   4:                  var tag = repo.ApplyTag(tagName);
   5:                  var remote = repo.Network.Remotes["origin"];
   6:                  var pushOptions = new PushOptions { Credentials = new DefaultCredentials() };
   7:                  repo.Network.Push(remote, string.Format("refs/tags/{0}:refs/tags/{0}", tagName, pushOptions));
   8:              }

 

That worked, so the next step was to build a custom activity that I could add to a build template - Martin Hinshelwood has a great blog post that helped me to get started with the custom activity and again referring to the source of the built in activities helped with extracting some of the arguments like source directory paths and build numbers.

Once you have your activity you need to get it deployed to the build agents, the process is to add the assembly and any dependencies (in this case the libgit2sharp.dll and the native binaries it uses) to a Git repository and configure the Custom Assemblies property of the build agents – this process is well documented on the Community TFS Extensions codeplex site.

Logging

This of course did not work first time….so I needed to add some logging I copied the example shown in this forum post 

context.Track(new BuildInformationRecord<BuildMessage>
                              {
                                  Value = new BuildMessage
                                              {
                                                  Importance = BuildMessageImportance.High,
                                                  Message = message
                                              }
                              });

This threw up an odd situation  - its possible for the call to Network.Push method to fail and not throw an exception – in my case it was because the service account that the TFS Build agent was running under did not have the necessary Write permission to create the tag – the PushOption object has an event handler to catch errors  - use this to see these kinds of issues and log them to the diagnostics log for the build.

I’ve put together a sample activity and the source is on my GitHub

Working with AChartEngine and Xamarain Android

I’m starting a new mobile project on android using Xamarin and needed a charting engine to display some data, there are a few existing component choices in the Xamarin component store one free one – bar chart but it (as the name suggests) only does bar charts and as far as I can tell can’t display multiple series at the same time. The other choices look great but cost real money and I needed to spike something without investing too much cash. A quick search for any open source options revealed a few options but none with any xamarin bindings as part of the existing code base leaving a final option of building a binding library myself.

According to the docs creating a binding library should be a fairly simple process but they do hint at having to fix up issues by hand which is where I ended up with AChartEngine – I downloaded the 1.1.0 jar file, created a new bindling library project, added the jar and build

At first it looked like I almost got away with it as I only had a single error

C:\Users\richard\Documents\GitHub\AChartEngine.Xamarin\AChartEngine.Xamarin\obj\Debug\generated\src\Org.Achartengine.Tools.Pan.cs(29,29): Error CS0542: 'Pan': member names cannot be the same as their enclosing type (CS0542) (AChartEngine.Xamarin)

So according to the docs I needed to do a bit of renaming using the metadata.xml file in the transforms folder so I added the following to the metadata mapping file to rename the event handler

<attr path="/api/package[@name='org.achartengine.tools']/class[@name='Pan']/method[@name='addPanListener']" name="eventName">PanEvent</attr>

and it turns out this is going to be an iterative process as it just allowed the compile to move into the next errors

obj\Debug\generated\src\Org.Achartengine.Renderer.XYSeriesRenderer.cs(206,9,206,46): error CS0019: Operator '!=' cannot be applied to operands of type 'Org.Achartengine.Renderer.XYSeriesRenderer.FillOutsideLine.Type' and 'System.Type'

    obj\Debug\generated\src\Org.Achartengine.Renderer.XYSeriesRenderer.cs(208,8,208,160): error CS1502: The best overloaded method match for 'Android.Runtime.JNIEnv.StartCreateInstance(System.IntPtr, System.IntPtr, params Android.Runtime.JValue[])' has some invalid arguments

    obj\Debug\generated\src\Org.Achartengine.Renderer.XYSeriesRenderer.cs(208,60,208,70): error CS1503: Argument 1: cannot convert from 'Org.Achartengine.Renderer.XYSeriesRenderer.FillOutsideLine.Type' to 'System.IntPtr'

    obj\Debug\generated\src\Org.Achartengine.Renderer.XYSeriesRenderer.cs(208,72,208,142): error CS1503: Argument 2: cannot convert from 'string' to 'System.IntPtr'

    obj\Debug\generated\src\Org.Achartengine.Renderer.XYSeriesRenderer.cs(208,144,208,159): error CS1503: Argument 3: cannot convert from 'Android.Runtime.JValue' to 'Android.Runtime.JValue[]'

    obj\Debug\generated\src\Org.Achartengine.Renderer.XYSeriesRenderer.cs(263,10,263,37): error CS0019: Operator '==' cannot be applied to operands of type 'Org.Achartengine.Renderer.XYSeriesRenderer.FillOutsideLine.Type' and 'System.Type'

    obj\Debug\generated\src\Org.Achartengine.Renderer.XYSeriesRenderer.cs(274,10,274,37): error CS0019: Operator '==' cannot be applied to operands of type 'Org.Achartengine.Renderer.XYSeriesRenderer.FillOutsideLine.Type' and 'System.Type'

    obj\Debug\generated\src\Org.Achartengine.Renderer.XYSeriesRenderer.cs(305,9,305,36): error CS0019: Operator '==' cannot be applied to operands of type 'Org.Achartengine.Renderer.XYSeriesRenderer.FillOutsideLine.Type' and 'System.Type'

    obj\Debug\generated\src\Org.Achartengine.Renderer.XYSeriesRenderer.cs(335,9,335,36): error CS0019: Operator '==' cannot be applied to operands of type 'Org.Achartengine.Renderer.XYSeriesRenderer.FillOutsideLine.Type' and 'System.Type'

    obj\Debug\generated\src\Org.Achartengine.Renderer.XYSeriesRenderer.cs(369,9,369,36): error CS0019: Operator '==' cannot be applied to operands of type 'Org.Achartengine.Renderer.XYSeriesRenderer.FillOutsideLine.Type' and 'System.Type'

 

So after a bit of googling looks like all I need to do is remove the offending types from the binding library (at this stage I’m not sure whether I’ll need to instantiate these types from the c# side but I hope not) so I added a few more lines to the metadata

<remove-node path="/api/package[@name='org.achartengine.renderer']/class[@name='XYSeriesRenderer.FillOutsideLine']"/>

And this time it compiles with no errors – I ran a quick test project to prove I could make use of the library and it worked, its not clear yet whether I’m going to need that class exposed in the binding or if there was a better way to resolve the binding errors.

Find the source on github