.NET Geographic Searches

I recently had to implement a localised search mechanism on an API.  Maths and Trigonometry aren’t my strengths it has to be said.  So I started looking online for pointers and background info.

Initially it might seem like you have to do some complicated maths to work out things like the size of the circle you’re dealing with etc.  But really the solution is very simple.  You know the starting points latitude and longitude and you also have a radius in a known unit, such as miles, meters or kilometers.  You’ll also have a dataset of potential target locations complete with their latitude and longitude points.

The only measurement you need is the distance from your starting point to a potential target location.  If that distance is less than or equal to the target location it’s within the circle designated by the radius.

The most accurate and popular algorithm for working this out is the Haversine algorithum.  The .NET framework has this built in.  The GeoCoordinate class inside the System.Device.Location namespace.

To use this:

var startingPoint = new GeoCoordinate(51.212213,-2.122312);
var targetPoint = new GeoCoordinate(52.212213,-1.122312);
var distanceInMeters = startingPoint.GetDistanceTo(targetPoint);

You can then convert the number of meters into whatever unit you would like to work with. Pretty simple really. The Haversine algorithm accounts for the curvature of the planet as well and has a very small margin of error.

You can find lots of implementations of this online, such as this one:

public static class Haversine {
  public static double calculate(double lat1, double lon1, double lat2, double lon2) {
    var R = 6372.8; // In kilometers
    var dLat = toRadians(lat2 - lat1);
    var dLon = toRadians(lon2 - lon1);
    lat1 = toRadians(lat1);
    lat2 = toRadians(lat2);
    var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Sin(dLon / 2) * Math.Sin(dLon / 2) * Math.Cos(lat1) * Math.Cos(lat2);
    var c = 2 * Math.Asin(Math.Sqrt(a));
    return R * 2 * Math.Asin(Math.Sqrt(a));
  public static double toRadians(double angle) {
    return Math.PI * angle / 180.0;
void Main() {
  Console.WriteLine(String.Format("The distance between coordinates {0},{1} and {2},{3} is: {4}", 36.12, -86.67, 33.94, -118.40, Haversine.calculate(36.12, -86.67, 33.94, -118.40)));
// Returns: The distance between coordinates 36.12,-86.67 and 33.94,-118.4 is: 2887.25995060711

I would definitely recommend using the .NET version though as this will be thoroughly battle tested.


Xamarin iOS TeamCity Build

So this turned into a complete nightmare for a while.

TeamCity Mac Agent Push Installation

I started by trying to get TeamCity to do a push install of a new agent on my MacBook Pro and very quickly things got very, very ugly.  First off it couldn’t find a JDK (which was installed) so I was using bash to update my ~/.bash_profile with the JAVA_HOME variable, but nothing seemed to work.  I fixed that by simply downloading the latest JDK release package and installing it.

Once the JDK errors and my /.bash_profile were fixed I then got the error (this is it in its entirety) “su: Sorry” … at that point I threw in the towel.  I’ve got better things to do that battle with this crap.  I abandoned the plan to push install the agent as I simply couldn’t figure out what was wrong with no information, the error text above was all that appeared in the agents log file as well so its  anyones guess as to what the problem really was.

NOTE: Make sure you can browse to the TeamCity site on your network using the agent machine

So I dialed into my TeamCity server, grabbed the zip installer and did it all manually.  This worked first time (after amending the buildAgent properties file) so what ever the issues were with the push installation I don’t know and frankly I don’t care, JetBrains have some tiding up to do both on this.

Build Steps

Since the build for the iOS application is now happening using Xamarin Studio installed on the Mac the build process is much simpler.  At the moment my unit tests are all run during debug builds only and these occur on a PC running another build agent.  I will revisit this to start executing test runs on the Mac agent to make for a more holistic testing process.

Updating Plist Files

There are a number of ways you can update the plist data on OSX.  Some people seem to suggest using the termainal DEFAULTS command but I found that didn’t work when presented with an iOS style Info.plist.  Chiefly it seemed to be confused by the internal layouts having arrays and a dict element.

By far the simplest way I found was making use of the standard OSX tool PlistBuddy which can deal with our iOS plist data.  So I added a new build step (executed before the compile step) and have configured it to allow me to update it’s internal version numbers and bundle identifiers based on the build configuration.

I normally use a 4 element version number for .NET (major).(minor).(build).(revision) which gives full traceability back to the source control for an individual release.  But if you use this in all cases you’ll have problems as iOS uses the semantic version number format (major).(minor).(build) for the “CFBundleShortVersionString” version number.

But you can also use arbitrary values in the “CFBundleVersion”.  Lots of people seem to ignore the AssemblyInformationalVersionAttribute in .NET but this is a great feature as you can use arbitrary strings as well as the more formal version format when using it in .NET assemblies.

$ /usr/libexec/PlistBuddy -c "Set :CFBundleIndentifier (yourbundleid)" Info.plist
$ /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString %build.number%" Info.plist
$ /usr/libexec/PlistBuddy -c "Set :CFBundleVersion %build.number%.%build.vcs.number%" Info.plist

Compile – Obsolete

The build step for compiling the iOS configuration is executed using a CommandLine build runner with a simple command like this:

/Applications/Xamarin\ Studio.app/Contents/MacOS/mdtool build "--configuration:Debug|iPhone" /path/to/solution.sln

Archiving Builds – Obsolete

Once the build is complete you’ll want to automatically create your archive. When you come to distribute your application to the App Store or to TestFlight via the XCode you’ll want to use xcarchive. You can use IPA files from the Build step with the Application Loader but as far as I can tell there is no way to upload dSYM files for any symbolicate processes which is a bit crazy (unless I’ve missed something)

Create another build step and use:

/Applications/Xamarin\ Studio.app/Contents/MacOS/mdtool -v archive "--configuration:Debug|iPhone" /path/to/solution.sln

This will place an xcarchive file into ~/Library/Developer/XCode/Archives/.  You can then validate this archive via XCode -> Window -> Organizer on the Archives panel.


So, it seems the recent versions of Xamarin Studio and the MDTOOL method of compiling and archiving have become problematic.  I started to see builds failing with some odd errors relating to my Droid project inside the build logs of the iOS builds.  Hugely confusing.  I never got to the bottom of why this was occurring and decided to review the whole process.  Both the compile and archive steps are now combined into one step and one command.  The command I’m now using is:

/Library/Frameworks/Mono.framework/Commands/xbuild /p:Configuration=AppStore /p:Platform=iPhone /p:BuildIpa=true /p:ArchiveOnBuild=true /target:Build /path/to/solution.sln

Obviously you can change any of the configuration or platform parameters to suit your requirements / project setup.

As I work through the next steps of this process I’ll keep this blog post updated – you can read the Android version here.


Abstracting APIs – Abstract Potentially Insane?

There’s no doubt about it, things that help are good.  This topic of abstraction came up in a chatroom the other day and I found myself advocating not abstracting in the client.  Having had more time to think about it I finally realised my own thoughts about it.  Just crept up from my subconscious.

At the moment I’m writing my own mobile apps, consuming an API that I’ve also written and maintain for use by mobile apps and web sites.  So naturally looking at anything to help is always worth considering.  The basic premise of my thinking is that in my particular situation, where I’m developing the API, dogfooding is the way to go.

Having to manually integrate with the API could be beneficial in a number of ways.  Having to deal with its security, data and inevitable idiosyncrasies can all potentially reveal design improvements.  If you immediately abstract your API behind someone else’s logic and expectations you’ll miss these opportunities during development.  You could argue the reverse is also true.  If Refit has troubles integrating with your API that could also reveal other problems or design improvements.

The particular client abstraction we were discussing is Refit.  It’s really very cool and if you aren’t in control of the API you’re interacting with it’s ideal, I’ll definitely be using it.  But I’m sure the authors of that API are at least testing that API if not also manually integrating with it at some point for some of the reasons outlines above.


View Model Value Change Tracking in MvvmCross & Xamarin

Change tracking object contents at first might seem like an easy or straightforward task but there are lots of pitfalls and potential issues with many solutions.  What works in your situation might not work in other situations due to implementation details.

The most obvious use of change tracking is at the heart of many ORM frameworks.  These frameworks manage data, often through proxy classes, in order to track what needs to be written to the data store when inserts or updates are applied.  These are often very granular and can be significant performance drains if misused or used in situations when not really required.

Most solutions you’ll find simply add an IsDirty property on a base class or interface and then just set that to true in any property setters in order to mark the class as dirty.  Other solutions maybe a little smarter and have a SetProperty() method that compares the new value to the current value and only executes the set if the value is new or unequal.  Whilst this isn’t change tracking it is at least efficient in view models when bound to interfaces.  An example method might look like this:

protected void SetProperty<T>(ref T backingfield, T value, Expression<Func<T>> property)
    if (Equals(backingfield, value))

    var mem = property.Body as MemberExpression;
    if (mem != null)
        var prop = mem.Member as PropertyInfo;
        if (prop != null && prop.CanWrite)
            // take advantage of any setter logic
            prop.SetValue(this, value);
            // update backing store
            backingfield = value;


If you’re trying to compare to original values you could start tracking each change to each property and working out if the current value has been used at any point in past.  This could very easily become a very bloated object graph.  You’re also still left in a situation where developers have to remember to call the SetProperty() method and not just set a property either directly or miss the public class API altogether and set the private backing field and negating any setter logic anyway.  If you don’t want to have property changed code in all your setters this can be a good approach if a little more expensive.

Negating all of these issues in one solution is extremely hard but minimising them is a must.

My Solution

I wanted a fairly simple IsDirty semantics at the class level.  I wanted my solution to just take care of itself and I didn’t want to have to do too much work in order to get this reliably functioning.  I also want it to be efficient and smart enough to accurately report that the class data really had changed and also wasn’t the same as the original values. My requirements where:

  • Entirely PCL (Portable Class Library) based implementation
  • Behaves in data binding situations
  • Attribute-driven Opt-In
  • Complex reference & value types included in object graph
  • Public only tracking (this is a view model after all!)
  • Filtering properties on Type or Name (string fuzzy matched)
  • iOS, Android, WP & MvvmCross friendly
  • As performance & memory efficient as possible
  • Class level monitoring only
  • Minimal extra library dependencies

So given these change tracking requirements I have coded my solution and I’m going to include all the code in a GitHub GIST below.


I wanted this to be as simple as possible pollute the code as little as possible.  I think it’s OK at the moment but will no doubt change and hopefully get better.

Property Attribute Example

If you use the attribute only those properties will be monitored, all other properties will be ignored.

public class PersonViewModel : MvxViewModel
    // ignored
    public string Name { get; set; }
    public string DisplayName { get; set; }

IsMonitoring Example

To start the monitoring, at some point after you can guarantee that all the values you regard as “clean” available in the object set Ismonitoring to true.  This forces a the calculation of an MD5 value for all the properties, now any subsequent calls to the IsDirty getter will compare this hash value to a newly created one with the current data.

You can reset the clean hash at any point by simply setting IsMonitoring to true again.

public sync void Init(int id)
    var data = await _myapiClient.GetPersonAsync(id);
    Mapper.Map(data, this);
    IsMonitoring = true;

Dependencies & PCL

The basic design has two dependencies.  Since I already had Newtonsoft.Json used in my project I have made use of parts of this and in order to implement the MD5 object hashing I have had to add a library – the xBrainLab.Security.Cryptography library available on codeplex.  Weighing in at 9,728 bytes this isn’t really much of a concern.

Basic Change Tracking Design

The basic design is that when IsMonitoring is set to true an object immediately generates an MD5 hash of all the relevant properties (default minus filters or explicitly opted in).  Then each subsequent call to IsDirty will first generate a new MD5 hash of the current values and compares that to the stored “clean hash”.

Hash Values (MD5)

Hashing in PCLs isn’t the norm so we have to use a library.  When generating the hash the object is first serialised to a memory stream using a JSON.NET serialiser.  This is then MD5 hashed and either stored or compared in order to calculate if an object has changes since monitoring began.

You can also set a newly minted clean hash by simply setting IsMonitoring to true on live objects.

Class Serialisation

The serialisation is all handled my JSON.NET and it’s built in serialiser.  I did try using the BSON serialiser as this may have a performance gain but it seemed to be erroring too often so I may have to revisit this.  There is a custom contract resolver that controls what is or isn’t to be tracked.  If a class has any properties marked with the IsDirtMonitoringAttribute then only these marked properties will be tracked.  If none of the properties are marked with the attribute then all public properties will be included in the change tracking minus any properties of the same type as the filter types or property name masks in the name filter.


It’s not particularly scientific or probably that accurate but I have added a unit test that monitors it’s execution time.  The test performs 100,000 IsDirty calls in a loop and will fail if it takes more than a second to complete based on the built in StopWatch class in System.Diagnostics it’s about as accurate as I’m needing.  Considering this will be called pretty infrequently and usually on a background thread this performance doesn’t concern me.  I have now implemented this on a few classes in an iOS application and I haven’t noticed any runtime issue (as yet!).

Anyway, enough wibbling as I should be out Christmas shopping … here’s the code … any comments or improvements really welcome.


Whitelist SSL Certificates in .NET for Xamarin / MvvmCross Apps

I have a fairly complex development environment for my current project and needed to allow some self-signed certificates to pass through the SSL certificate chaining process when calling from mobile platforms.  Obviously, this is potentially breaking a major security feature and need to be done safely.

In a ‘normal’ MvvmCross or Xamarin.Forms application you want to include as much in the core PCL project as possible for portability and code-sharing.  Unfortunately there is no PCL implementation of the ServicePointManager class, but this is defined in both Xamarin.iOS and Xamarin.Android.  Strangely, another instance where Windows Phone is problematic as this isn’t defined at all in WP.

Given that I have another shared library that hosts my API client that is compiled into a platform specific version I can do this here and have that shared.  Otherwise your best options are including this code in the platform specific projects somewhere in the Setup.cs class for instance.

Bypass Certificate Checking

ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(
    (sender, certificate, chain, policyErrors) =>
        if (policyErrors == SslPolicyErrors.None)
            return true;

        var certThumprint = string.Join("", certificate.GetCertHash().Select(h => h.ToString("X2")));
        var thumbprint = "<YOUR CERT THUMBPRINT>";
        if (certThumprint == thumbprint)
            return true;

        return false;

MvvmCross Beta5 & SidePanel Navigation Sample

There is a new release of MvvmCross yesterday that takes the platform to v4 beta 5 that was released yesterday.  I’ve also contributed a new v4 sample project which provides cross platform side panel navigation to iOS and Android application.  You can check out the new version here and the sample is here.

You can see some screen shots of the sample applications below:

droid_menu_closed droid_menu_open ios_menu_closed ios_menu_open


Xamarin Android Automated CI Publishing Using MSBuild & JetBrains TeamCity

I love automating processes and making things consistently repeatable.  Continuous integration is your friend, yes it can take time to setup but if you take that effort hit upfront it will pay off in an immeasurable way through your development process and during the entire lifetime of the your development.

For my continuous integration I use JetBrains TeamCity.  I love this CI system, granted I’ve not used them all but comparing them to TFS and Jenkins it is like an oasis of calm in comparison and without doubt the cleanest UX design by a very long margin.  Anyway … I digress.  If you want to automate the process of producing your ready to distribute Xamarin .apk Android application packages, this is the basic process you need to follow:

Creating Your Keystore

The first step is to create your own personal keystore that will contain the information used to digitally sign your Android package files.  You can do this with the following command:

"C:\Program Files (x86)\Java\jre1.8.0_45\bin\keytool.exe" -genkey -v -keystore myandroid.keystore" -alias myaliasdroidpub -keyalg RSA -keysize 2048 -validity 30000

Before you run this command make a note a few parameters first.  I did all of this in a batch file so I can refer to it later, this does include some sensitive data so beware what you do with this file.  The 30000 at the end of the command denote the length of validity of the certificates and Google require this to be past 2033.  You’ll need the following info:

REM — Password – <yourpassword>
REM — name —– <yourname>
REM — OU ——- <organisationunit> eg: JamSoft
REM — Orgname — <organisationame> eg: JamSoft
REM — Local —- <locality> eg: Frome
REM — State —- <state> eg: Somerset
REM — Country — <2lettercountrycode> eg: UK

Visual Studio Android Project

Now that we have our Java keystore ready and prepped for use we can look at the Visual Studio project.  In order to make this automated in the build system we need to configure the project to use our keystore credentials.  This is spreading sensitive information around but since our keystore is probably going to be checked into our repository it’s most likely going to spend it’s life being treated in a sensitive fashion anyway, so no real concerns.  I personally make lots of backups of things in large .RAR files and store these in various places but these are also password protected and treated as confidential.

In Visual Studio edit the Android application .csproj file and add another PropertyGroup element as per the code below:

  <PropertyGroup Condition="'$(Configuration)' == 'Release'">

Now our .csproj file knows how to use our keystore unattended. We can tie into the Xamarin build process from within our automated builds and produce the base Android package.

You can test that this is working using the following command:

msbuild.exe HelloWorld.csproj /p:Configuration=Release /t:PackageForAndroid

This will execute MSBuild against your Android project file and you’ll now find your .apk file in your bin\Release directory.

Signing The Package

Now that we have our packaged application we can apply the signing processes.  To sign the package created in the previous step we need to execute the following command:

"C:\Program Files (x86)\Java\jdk1.7.0_71\bin\jarsigner.exe" -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore myandroid.keystore -storepass yourpassword -keypass yourpassword -signedjar \bin\Release\packagename-signed.apk \bin\Release\packagename.apk myaliasdroidpub

This package is now digitally signed using your certificate from the keystore we made earlier. Personally I still have a couple of questions around why this needs to be done again considering that the details for this keystore are in the csproj file but I’m still waiting on a response from Xamarin on this.

ZipAligning the Signed Android Package

Now that we have a signed package we can zip align this package and then publish this as an artifact of our TeamCity build process.  This command makes use of the Android SDK zipalign.exe program.  You’ll have to find where this is on your machine as there are many potential locations.  The command you need will look something like this:

“C:\Users\<name>\AppData\Local\Android\android-sdk\build-tools\<version>\zipalign.exe” -f -v 4 packagename-signed.apk packagename-zipaligned.apk

You don’t need to follow this naming convention used here this is just for illustration purposes.

You can now set this as a published artifact of your TeamCity build configuration.  Yay!

MSBuild Project

To kick off the process in your MSBuild project you can add TeamCity Step that executes an additional Target in your build script like this:

  <Target Name="PackageAndroidApk">
    <MSBuild Projects="$(MSBuildProjectDirectory)\..\src\path\MyProject.Droid.csproj" Targets="PackageForAndroid" Properties="Configuration=Release">

This target will create the base APK package that you can sign and zipalign.

Once you have all these commands working you can add all the required build steps.


And voila!  Automated.  Nice 🙂


Xamarin iOS Build Server is Too Old

This is silly message really.

If you’re getting this error (or something similar) but you also know that you’re running the latest version of the iOS build host:

Build server with address is too old to be used with this version of Xamarin.iOS extension. Double click here to select a new server.    Xamarin.iOS Extension

It’s most likely that you have a manual proxy configured in your Windows development machine

The Solution

Go to your Manual Proxy configuration settings and turn off your manual proxy.  Once you’ve done this just double click on the message in Visual Studio and it should connect to your iOS build machine and run fine.


Learning MvvmCross

Learning a new technology can sometimes be a very time consuming and error prone process.  The more complex the technology the longer this process can go on for.  When I was first getting my head wrapped around WPF and using the MVVM pattern this was a long process.  WPF is massive and very complex.  MvvmCross whilst not nearly as large is a very complex framework in itself.

Having said that I’m literally amazed at just how much Stuart Lodge manages to produce in terms of tutorials, write-ups, videos and code.  For that reason alone it’s worth your time to investigate.  Below I’m starting to compile a list of resources that I find useful along my own journey of using this framework.


MvvmCross Source



This is a series of really good videos produced that demos how to achieve a very large number of basic and advanced scenarios using Xamarin and the MvvmCross libraries.  Stuart has put a lot of time and effort into producing this and it’s well worth your time to dive in from time to time to learn about the various features and options available on how to structure your code and applications.

MvvmCross NPlus1DaysofMvvmCross Tutorial Videos

Blog Posts

This is a partner to the code and videos and contains a lot of very good examples and tutorials.

NPlug1 Blogs Table of Contents


The Apple Developer Clique

I’m genuinely gobsmacked by this.

I applied for the Apple Developer program a couple of weeks ago on behalf of the company I co-founded.  I was amazed to find out that I had to provide them with details about myself, details about my company including things like our DUNS number.

In addition to this I had to wait for them to call me … yes, CALL me.  Just so that I can get a set of digital keys to sign anything I build.  So I waited for the call which took a little over a week.  The checks they did in this call were frankly pathetic:

Them: “Hi Apple here, you applied for the developer program on behalf of <company>?”

Me: “Hi, yes I did”

Them: “Can you confirm you are <name> and can you sign things for your company?”

Me: “Yes I can”

Them: “OK, thanks.  I’ll update your application now, bye.”

I mean seriously Apple what is the FUCKING use of “check” like that??  I could have been bloody anyone on the end of that phone connection.

So, I then had to wait for that to filter through the system.  I got distracted as busy business types generally do and got on with other things to make better use of my time.  An email arrived on the 10th June saying that I could now finish the application.  So today (20th June) I’m in a position to get it paid for (I’ve got to PAY Apple to make their eco-system more attractive??? WTF??  I won’t go into how offensive I find that here).

BOOM!!  Because I didn’t cough up my cash quick enough (within 7 days) I now have to go through this laughable application/wait/phone call process again.  I have to apply again, giving all the same details AGAIN, wait for another impossibly stupid phone call and another email.

Just so that I can hand over the stirling equivilent of £110 (not $99) so that I can spend my time making an app for my company.

Seriously, Go fuck yourselves Apple.  Take about a little clique!

“Ohhh, you didn’t respond quick enough, oooh, oooh … you need to be faster than that … Oooh, join our little club you want do you?  It’ll cost ya.”

Yeah, well I’ve already paid a massive premium for the bloody laptop I’m using.


PCL Profile 259 in Visual Studio 2012 on Windows 7, Xamarin, MvvmCross & ReSharper 7.1

Well, today was a lot of fun.  You can tell just how much fun from the ridiculous title of this blog post.

I’ve lost most of a productive day to this set of issues.  I was seeing some errors being reported by ReSharper 7.1 in my PCL and Xamarin Android solutions and couldn’t work out what the issues were.   They compiled without any compiler issues being returned and ran on the various emulators as expected, again without any issues or exceptions.  Consdering the error reported by ReSharper was Module ‘System, Version=, culture-neutral’ should be referenced.  An error of that sort, if “real” should mean an application would have trouble even starting up let alone running.


I’ve basically been round the houses trying to sort this out.

Considering the problem centered about MvvmCross I decided to have a look at the source for that so cloned the repository and started having a poke around.  Now the first problem you’re going to encounter given the VS2012 and Windows 7 constraints is that Windows Phone requires Windows 8 for development.  The WP8 SDKs won’t even install onto Windows 7 so those projects are dead in the water.  This target .NETPortable Profile259 which cannot be installed on Windows 7.

So when I opened the MvvmCross solutions on my machine I was seeing some very odd behaviours.  You can see some of the weirdness in the following screenshots:


The Cirrious.CrossCore solution targets Profile 259 (the new Profile78 basically with Windows Phone 8.1 support thrown in – unavailable on Windows 7).  So what has been happening is any of my own projects that link to this library are trying to resolve system.dll v4.0.0.0 through Profile259.  Since I don’t have this profile ReSharper was correctly informing me of an issue but incorrectly informing that I’ll get a compiler error as a result.

In order to arrive at this solution I had upgraded ReShaper from 7.1 to 9.1 only to still see the issue.  Reinstalled all of Xamarin and even contemplated a fresh Windows install (not a small task).

The Solution

The solution turned out to be fairly simple.  Kid the system into thinking that my operating system DOES have Profile259 by copying the XML files from:

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile78\SupportedFrameworks


C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile259\SupportedFrameworks

This doesn’t fix the issues I see when opening the MvvmCross solutions, they still compain about not finding system.dll but it has meant that my solutions that reference Cirrious.CrossCore do not throw up the problem of highlighting “non-issues” in my own projects.

So that was a hell of a learning experience.  And I did pull the trigger on an update to ReSharper 9.1 after complaining to JetBrains that 7.1 cost £110 and an upgrade to 9.1 cost £122!  So they gave me a 25% discount!  Yay!

Thanks JetBrains.