AppSettings in Xamarin.Forms

If you have used ASP.NET in recent years you will probably be familiar with the appSettings.jsonfile and it’s associated, build-specific transformations, e.g. appSettings.development.json and appSettings.release.json.

Essentially these allow developers to define multiple configuration settings which will be swapped out based on the build configuration in play. Common settings are stored in the main appSettings.json file while, for instance, API Endpoint Urls for development and production deployments are stored in the development and release files.

At compile-time any values specified in the deployment version of the file overwrite those in the common version.

Simple – works well and we use it all the time without thinking about it. But what about Xamarin.Forms – it doesn’t have such a mehanism out of the box so how do we achieve this and prevent accidently publishing an app to the App/Play Stores which are pointing to your development/staging servers?

The Problem

Previously I have tried a number of approaches and while they mainly worked there were always shortcomings which meant that I couldn’t really rely on them.

One used a pre-deployment step in Visual Studio to copy the appropriate file, based on the build configuration, from one location to another where it would be picked up by the applications startup code. This worked fine when running on Windows but not when building on the Mac (using Visual Studio for Mac) because it uses the cp command and not copy.

Yes, I could have created an alias from copy to cp but what about when I want to configure a Continuous Integration build on Azure DevOps?

Another approach had me creating Operating System specific script files, .bat on Windows and .sh on the Mac, and again using a pre-build task to run the appropriate script (executing the extension-less command would run the appropriate version on each platform). But passing arguments for the build configuration was clunky and again Azure DevOps pipelines didn’t really seem to want to play ball – maybe Microsoft is a bit cautious about letting anyone execute scripts on their Azure servers 😉

Well, after deploying and testing the wrong version of an app onto my phone and scratching my head for twenty minutes I decided enough was enough and using the first approach above as a base I have come up with a simple mechanism which does the job.

The (my) Solution

The solution I’m running with requires a configuration file to be created for each build configuration, e.g. Debug and Release (by default), which are configured as ‘Embedded Resources’.

A static property is added to the App class which implements the Singleton pattern to load and return an instance of a class that represents the contents of the configuration file – I’m using Newtonsoft.Json to deserialise the file and hydrate an instance of the class.

Add some Conditional Compilation Symbols to the mix and we are just about there.

If you would rather look at the code in Visual Studio then you can download it here.

Enough talk – let’s get to it 😉

To the Code

I’ve created a basic Xamarin.Forms project using Visual Studio 2019 Community Edition, stripped out all the default stuff and added in a single Content Page, ViewModel, Class and two Configuration Files:

The Solution (in all it’s glory)

The appsettings.debug.json file has the following content:

The appsettings.debug.json file

You probably don’t need any clues to the content of the other version 😉

The only thing to remember here is to ensure that you set the ‘Build Action’ for these files as ‘Embedded Resource’:

Setting Build Action on .json files

The AppSettings.cs class is a simple POCO with a single property which corresponds to the json files:

The AppSettings.cs POCO class file (yes – I could remove the redundant ‘using’ statements!)

Now, when a Xamarin.Forms app starts up the App class is, for all intents and purposes, the entry point and is generally available to the Content Pages throughout the app. So this is a good place to expose our AppSettings:

App.xaml.cs

Notice how the property getter will instantiate the AppSettings instance if it is not already in place.

Also notice the use of the conditional compilation statements (#if .. #else .. #endif) in the LoadAppSettings method. This is where the ‘magic’ happens. I know that some people may shy away from this approach but this is the way I’ve gone for now.

Basically the LoadAppSettings method will read in the specified file depending on which build configuration is in play at the time. The file is deserialised into an instance of AppSettings and the local variable updated.

As the .json files are Embedded Resources we can address them using their fully qualified names, noting that the namespace is made up of the overall Namespace (AppSettingsPoc), the folder name containing the files (Configuration) and the actual filenames. Yours will be different for sure – just remember how it’s comprised.

For the conditional compilation to work we need to specify the appropriate symbols (the ‘RELEASE’ text in the above code).

To do this, Right-Click on the shared project (the one with the App.xaml file) and select ‘Properties’:

Project properties for AppSettingsPoc (shared project)

Select the ‘Build’ tab from the left hand side and set the configuration to ‘Release’ if it’s not already.

In the ‘Conditional Compilation Symbols’ field enter ‘RELEASE’ (or whatever you want to call it – just match it up with what you use in the App.xaml.cs file). If there are other values already present then tag this new one to the end, delimiting it with a semi-colon.

So, we have the configuration files, we are loading them and making the available to the Application. Now we just need to consume the data and for this I’m using a ViewModel, HomeViewModel.cs, which will be the Binding Context to our Page.

The ViewModel class is another simple POCO with a single property which reads the WelcomeText from the AppSettings instance via the App class:

The HomeViewModel.cs POCO class – with redundant ‘using’ statements removed 😉

Finally, we just need to bind this property to a UI element on our Page:

HomePage.xaml

Notice that on line 10 in the above markup I’m specifying the BindingContext to an instance of the HomeViewModel. As with many things in Xamarin.Forms, there are numerous ways of acheiving this.

The label has a Text property which I’ve bound to the WelcomeText property (which will be on the ViewModel remember) and that’s about it.

If I run the app in Debug mode I will see the message as read from the appsettings.debug.json file. Run it in Release mode and it will be the message from the appsettings.release.json file:

In Summary

The solution presented above requires a small amount of setup and then it pretty much fire-and-forget. If you need a new setting then update your AppSettings.cs class, add the values to your .json files and you are good to go.

Need a new build configuration, say Staging? No problem. Just create the new .json file (remembering to set it’s build action as ‘Embedded Resource’), add a new ‘STAGING’ symbol to the project properties, update the LoadAppSettings method to check for it and you are done. Simple as that really.

Now, some may say that Conditional Compilation is bad and that using Reflection is the work of the Devil. But frankly – I’m quite pragmatic about these things and if it works and doesn’t have a dreadful code smell then I’m not going to lose too much sleep over that.

Getting to grips with OzCode

When I was at NDC London in January I watched a demonstration of the OzCode extension for Visual Studio. Not only was it well presented but it highlighted some of the pinch points we all have to tolerate while debugging.

In return for a scan of my conference pass, i.e. my contact details, I received a whopping 35% discount off a licence and without completing the 30 day trial I was so impressed that I pulled out my wallet (actually the company wallet!).

While I don’t use all of the features every day there are a few that I use all the time – the first one is called ‘Reveal‘.

Consider the following situation:

But I already knew this was a list of view models!

At this breakpoint I’m looking at collection of View Models – but I knew that already what value am I getting from this window? There are over 600 records here – do I have to expand each one to find what I’m looking for? What if one has a null value that is causing my problem – how will I find it?

Well, I could obviously write a new line after the breakpoint which will give me all of the items with a null value for say the name property. But to do that I need to stop the debugging session, write the new line, restart the application and perform whatever steps I need to perform to get back to the above scenario.

Ok, that’s not going to kill me but it’s wasted time and I have to remember to remove the debugging line once I’m done with it.

Using the OzCode Reveal feature I can specify which properties I was to be displayed instead of the actual, fully qualified, class name.

By expanding any of the records to view the actual property data it is possible to select which ones I want to see – which are important to me at this time – by clicking the star.

Select the properties you want to see

Now when I expand the list I see this instead:

Much more useful

These selections are persisted across sessions and can be changed whenever – maybe I want the email addresses, cities or countries next time – not a problem.

But what about nested properties? Well, that’s not a problem either – just drill in an star the properties you want to see and they will be displayed at the appropriate level in the tree as below:

Here the users first and last names are selected as well as the start date of their subscription

There’s a lot more to OzCode than this and as it becomes more embedded in the way I work I’ll post more about how it has helped me.

Parsing Console Application Arguments using CommandLineParser

When we open Visual Studio and click File > New we are greeted with a huge list of project templates to choose from. Now and then we may opt for a simple Console Application for a quick one off utility, e.g. post processing some .csv files or images.

Similarly we have all used command line utilities which require numerous arguments and switches to ‘tune’ exactly what we want it to do, e.g. git or tar.

Well I’m looking to create a Command Line utility that will allow users to encrypt and decrypt textual messages.

Why? I hear you ask – well check out my thoughts on the UK Governments attempts to get WhatsApp to create a backdoor.

The utility will allow users to

  • Generate Public/Private Key Pairs
  • Encrypt textual messages, packaging them for sending to the intended recipient
  • Decrypt packaged messages

Each action will require/allow a number of parameters to be set to specified key bit lengths, key names, output locations and of course the message to be encrypted or decrypted.

Something like this:

C:Encryptor generateKeys -n Daves -o C:UsersDaveMyKeys

which would create a key pair files called DavesPrivateKey.xml and DavesPublicKey.xml in C:UsersDaveMyKeys

But what is the best way to do this?

We could handle it in the Program.Main method by locating arguments and setting their values, like this
https://gist.github.com/OnTheFenceDevelopment/d08bb935661c91d3a11dac50daacbb09.js

But that’s a bit nasty and relies on each parameter having a value and that it’s been specified in the correct way to allow casting etc. There has to be a better way .. well there is and it comes in the form of a nuget package called, suitably enough, CommandLineParser.

Now, I didn’t find the documentation (the ReadMe.md on the projects Github page) that helpful and it took a lot of trial and error to work out how to use it for my needs. When I got to grips with it though – I was impressed.

After installing the CommandLineParser via nuget I needed to create a new class to define each operation, i.e. GenerateKeys, Encrypt and Decrypt.

Each class is decorated with a ‘Verb’ attribute – this defines the action – while the properties are decorated with ‘Option’ attributes.
https://gist.github.com/OnTheFenceDevelopment/30640f89914a961bf0d2f81995e36c19.js

So the above code defines the Generate Keys action and provides options for Key Length, Name and Output Folder. Notice that the Key Length will default to 2048 bits if not specified by the user. It is also possible to make options mandatory and the operation will fail if they are not specified.

When the Console Application project was created a Program.cs class was added containing a single method called Main. I’ve modified the signature to return an integer instead of a void as I think it is good practice to return exit codes from command line utility.

https://gist.github.com/OnTheFenceDevelopment/2725e47e2482535a681e2b794901fcc0.js

To test the configuration I can right-click on the project file, open the Properties page and click on the ‘Debug’ option. Enter suitable values into the ‘Command Line Arguments’ as below

and then run the application (I had a breakpoint on the return statement within the GenerateKeyPair method).

If the parser fails for any reason then it will automatically generate the required output and error ‘gracefully’.

Try dropping the value for one of the options and rerunning the application – below I dropped the DavesMessage value from the -n parameter:

Obviously I want to add another couple of Option configurations and this is easy enough to do – take a look at the sample app in the github repo, in particular the Program.cs file, to see how this is done. Alternatively you can keep track of this application when it hits GitHub as I will be open sourcing the code.

Starting Development of FillLPG v3.x

Overview

With the most recent update to the FillLPG application (v2.0.28.2) rolling out I will be ceasing all development of this version (unless some horrible bug raises it’s ugly head). But fear not loyal LPG users – that doesn’t mean the the app will be going away – far from it.

Technology moves on at pace and over time new skills are acquired and lessons are learned. The ‘problem’ is that to implement all of this it is easier to start over again – taking advantage of the new framework features, applying the new skills and remembering those sometimes painful lessons.

So, what’s on the horizon?

I suppose the ‘headline’ news is that an iOS version will soon be a reality! After years of focusing solely on the Android version our Apple-using LPG’ers will be getting some love too.

The aim will be to develop an iOS application with feature parity to the current Android version.

Now, don’t fret if you are an Android user – I’m not abandoning all of you who have helped make the app what it is today. The fact that I can essentially develop for two platforms at the same time is due to the advances made in the underlying framework used to develop the app. Previous versions didn’t really lend themselves to the type of mapping that is required for the FillLPG app – but that’s all changed now and mapping is now fairly straightforward to achieve on both platforms whilst sharing the maximum amount of code – which is good for maintainability (fix a bug in one place and it’s fixed for Android and iOS).

With the rest of the application mainly consisting of ‘Forms and Lists’ and these can easily be shared between the new platforms.

The result will be a more modern UI, lower impact on battery life and data usage.

Other planned features include:

  • Offline price updates (updates will be pushed when your device next has internet access)
  • “Route Planning” – display stations along a particular route allowing you to plan stops
  • Enable/Disable update alerts for favorite stations

But there’s more…

The webmaster of the FillLPG website is currently developing a new version with a new and improved webservice – which is how the app communicates with the site. This will expose a lot more data to the app, including:

  • Station notes
  • Opening Times
  • Flags such as ‘Disabled Friendly’ and ‘SafeFill Capable’
  • Ability to specify price currency
  • and more

Obviously I have no control over the timescales for the new website functionality but as soon as it is available I will be including it into the application as quickly as I can.

Please remember though that the FillLPG website and the mobile apps are ‘labours of love’ and that both myself and the site webmaster have other commitments. The website and apps are provided free of charge and with no ads.

 

Stackify Prefix – first thoughts

Listening to one of my favorite podcast (.Net Rocks) I heard a plug for the Stackify Prefix tool which claims to help the developer fix problems before anyone else sees them – a bold claim. Well as I am currently working on a greenfield development project I decided to give is a whirl – it’s free after all so why not.

Now I was not expecting to find too much wrong with the application and thankfully I was right – but I was getting errors.

The highlighted call is to a WebAPI method from an AngularJS controller (a JavaScript file on the client) and as you can see from the right hand pane it does succeed. In fact the data is returned as I’d expect and the application works without any issue. So why is Prefix flagging this?

Well, looking at the stack trace a little more carefully I see that the exception is being raised by the XmlMediaTypeFormatter when it is creating it’s default serializer. But the WebAPI is returning JSON so why it is spinning up an XML serialiser?

Well, my WebAPI endpoint took this form:

https://gist.github.com/OnTheFenceDevelopment/c8bc6729ad09d3b60579f191ffafeec7.js

The problem is on line 8 where I’m returning the OK status with the required content – which is an anonymous object that I’ve just put together on the fly. The WebAPI is configured to accept the ‘application/json’ header and to use an appropriate JSON Formatter – which it does.

The problem is that I still have the default XML Formatter in the list and for some reason the framework is trying to use it to serialize my anonymous object – and failing (silently).

So all I need to do is to remove the Formatter during the WebAPI registration – within WebApiConfig.cs in the App_Start folder (see line 12 below).

https://gist.github.com/OnTheFenceDevelopment/5441c335465d87e2c9addb19d29eed2c.js

Now this was fairly trivial but a bug is a bug and as we know – exceptions are expensive. They take time to raise while they pull the required information together and work their way through to the calling code – which in this instance appeared to simply discard it. A small performance hit but if this scaled then it could have become a bigger problem in the future – and probably harder to find.

Prefix highlighted it straight away and the issue is now fixed. It never made it to production, in fact it never made if off my desk – it was Pre-Fixed!

Unable to deploy Xamarin Android app to GenyMotion emulator

We all know that when you are developing mobile apps there is nothing better than running on an actual device. This is especially useful when wanting to access the device sensors such as GPS and the accelerometer. But we also all know that we have to test against a wider variety of devices than we have in our drawer. That’s where emulators come in – and where the trouble starts in some cases, but I won’t go into Hyper-V here!

Well I’ve been using GenyMotion for a little while and am very happy with it – to the point that I was about to put my hand in my pocket to buy a licence (which I may well still do). However, today I ran into a problem where Visual Studio would refuse to deploy to the emulator.

With the emulator running I selected it as the deployment target in Visual Studio and pressed F5, the build completed successfully and then, just before deployment the emulator disappeared from the list of targets and the deployment failed. I made sure I had the latest version of Genymotion installed (which I did) and that everything else was up to date (which it was).

While I was badgering Xamarin in the forums and via the support email I thought to fire up the Android Debug Bridge (adb) command prompt from within Visual Studio to check what devices the Debug Bridge was actually connected to:

Well, there you have it – it’s a problem with the adb versions ….. wait a minute, how many do I have?

My understanding was that I should only have one – the one that Visual Studio connects to so that it can access the Android devices & emulators. And (I think) I was right on that score – I should only have on running. So what’s with the version clash?

As it happens, Genymotion also ships with a version of the Android Debug Bridge and as it turns out, right now that one and the one shipped with the Xamarin toolset are not the same version.

Comparing versions of adb.exe (from Genymotion and the Android SDK) I found that Genymotion was currently at version 1.0.32 while the Android SDK has 1.0.36.

So what to do?

I suppose I could copy the adb files from the Android SDK into the Genymotion installation – but that frankly smells a bit to me and as it turns out it’s unnecessary.

It is possible, within Genymotion, to set which ADB instance to use for each individual emulator. Simply select the emulator instance and click Settings. Select the ADB tab, click ‘Use Custom Android SDK Tools’ and browse to the SDK location on your system.

Note that the SDK will be in a folder called ‘Android’ within C:Program Files (x86) or C:Users<user>AppDataLocal

Setting this resolved my issues and I am once again enjoying the flexibility of Genymotion and will be buying a licence very shortly.

Xamarin for Visual Studio won’t Update?

I’ve been developing with Xamarin for a few years now and most of the time I do so using Visual Studio. Now, as with most technologies, Xamarin is constantly evolving and therefore updates are pushed out fairly frequently – that’s all good, we all like new stuff don’t we?

Well, I’ve always had a problem whereby Visual Studio would prompt me to say that there was an update available and that I should ‘Click Here to Update’ – the only problem being that this doesn’t actually do anything!

In the past I’ve simply opened up Xamarin Studio, checked for and installed updates and then reopened Visual Studio – simple it’s a bit irritating.

Well with Xamarin now being part of Microsoft and after rebuilding my development workstation I find that Xamarin Studio is no longer installed with the rest of the Xamarin components when Visual Studio is installed. So how do I install the updates now?

Well, after posting that very question in the Xamarin Forums I was guided to the answer which seems so obvious now (that’s sarcasm by the way). I simply needed to navigate to: Tools > Options > Xamarin > Other > Check Now

Don’t know how I missed that 😉

Anyway – the bug with the notification looks like it’s fixed now but just in case I thought I’d post this here for the unwary.

Visual Studio 2015 – Package Installation Error [Failed to initialize the PowerShell host]

Well today I decided to start a new Xamarin.Forms project in Visual Studio 2015 but fell at the first hurdle – you would have thought File > New Project would be simpler than this really.

After clicking through all the errors I tried to build the solution which failed as badly as I expected it to – only 28 errors but all pretty severe.

Opening the Package Manager Console resulted in another error which seemed to indicate that a file was missing (nuget.psm1) but it was present, accessible and appeared to be intact.

So what’s the problem here? Well, it’s not actually Xamarin.Forms at fault – if I open Visual Studio with no solution loaded and then open the Package Manager Console I get the same error. I checked for updates and compared all the version numbers against the installation on my laptop (which didn’t have the same issue) and everything seemed in order.

Well after a look (and I mean, a lot!) of Googling I found a cure for the symptom but not for the root cause.

When you open Visual Studio 2015 an instance of the devenv.exe.config file is generated in the following location: C:Users<username>AppDataLocalMicrosoftVisualStudio14.0 with a nice comment header indicating that modifications were subject to being overwritten. Now that’s a bit of a pain because only by editing that file can I get the workstation to open the Package Manager Console correctly and hence generate a Xamarin.Forms project.

Add the following within the assembly binding section of the config file:

<dependentAssembly>
    <assemblyIdentity name="System.Management.Automation" publicKeyToken="31bf3856ad364e35" />
    <publisherPolicy apply="no" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="Microsoft.PowerShell.Commands.Utility" publicKeyToken="31bf3856ad364e35" />
  <publisherPolicy apply="no" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="Microsoft.PowerShell.ConsoleHost" publicKeyToken="31bf3856ad364e35" />
  <publisherPolicy apply="no" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="Microsoft.PowerShell.Commands.Management" publicKeyToken="31bf3856ad364e35" />
  <publisherPolicy apply="no" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="Microsoft.PowerShell.Security" publicKeyToken="31bf3856ad364e35" />
  <publisherPolicy apply="no" />
</dependentAssembly>
<dependentAssembly>
  <assemblyIdentity name="Microsoft.PowerShell.Commands.Diagnostics" publicKeyToken="31bf3856ad364e35" />
  <publisherPolicy apply="no" />
</dependentAssembly>

Now, the laptop does not have those lines in it’s version of the file and it runs just fine so why the workstation is choking I have no idea – this is a quick and (very) dirty fix at best. From time to time you may need to reedit the file but at least you will be able to continue working.

The thing is I plan to pave this workstation soon and perform a clean installation so I’m not really looking to spend a great deal more time trawling the internet to find which obscure setting is flipped the wrong way and is causing this issue.