Monday, June 08, 2020

Keeping your Secrets Safe in Azure Pipelines

These days, it’s critical that everyone in the delivery team has a security mindset and is vigilant about keeping secrets away from prying eyes. Fortunately, Azure Pipelines have some great features to ensure that your application secrets are not exposed during pipeline execution, but it’s important to adopt some best practices early on to keep things moving smoothly.

Defining Variables

Before we get too far, let’s take a moment to step back and talk about the motivations for variables in Azure Pipelines. We want to use variables for things that might change in the future, but more importantly we want to use variables to prevent secrets like passwords and API Keys from being entered into source control.

Variables can be defined in several different places. They can be placed as meta-data for the pipeline, in variable groups, or dynamically in scripts.

Define Variables in Pipelines

Variables can be scoped to a Pipeline. These values, which are defined through the “Variables” button when editing a Pipeline, live as meta-data outside of the YAML file.

image

Define Variables in Variable Groups

Variable Groups are perhaps the most common mechanism to define variables as they can be reused across multiple pipelines within the same project. Variable Groups also support pulling their values from an Azure KeyVault which makes them an ideal mechanism for sharing secrets across projects.

Variable Groups are defined in the “Library” section of Azure Pipelines. Variables are simply key/value pairs.

image

image

Variables are made available to the Pipeline when it runs, and although there are a few different syntaxes I’m going to focus on using what’s referred to as macro-syntax, which looks like $(VariableName)

variables:
- group: MyVariableGroup

steps:
- bash: |
     echo $(USERNAME)
     printenv | sort

All variables are provided to scripts as Environment Variables. Using printenv dumps the list of environment variables. Both USERNAME and PASSWORD variables are present in the output.

image

Define Variables Dynamically in Scripts

Variables can also be declared using scripts using a special logging syntax.

- script: |
     $token = curl ....
     echo "##vso[task.setvariable variable=accesstoken]$token

Defining Secrets

Clearly, putting a clear text password variable in your pipeline is dangerous because any script in the pipeline has access to it. Fortunately, it’s very easy to lock this down by converting your variable into a secret.

secrets

Just use the lock icon to set it as a secret and then save the variable group to make it effectively irretrievable. Gandalf would be pleased.

Why doesn't JWfan have a secure connection? - Other Topics - JOHN ...

Now, when we run the pipeline we can see that the PASSWORD variable is no longer an Environment variable.

image

Securing Dynamic Variables in Scripts

Secrets can also be declared at runtime using scripts. You should always be mindful as to whether these dynamic variables could be used maliciously if not secured.

$token = curl ...
echo "##vso[task.setvariable variable=accesstoken;isSecret=true]$token"

Using Secrets in Scripts

Now that we know that secrets aren’t made available as Environment variables, we have to explicitly provide the value to the script – effectively “opting in” – by mapping the secret to variable that can be used during script execution:

- script : |
    echo The password is: $password
  env:
    password: $(Password)

The above is a wonderful example of heresy, as you should never output secrets to logs. Thankfully, we don't need to worry too much about this because Azure DevOps automatically masks these values before they make it to the log.

image

Takeaways

We should all do our part to take security concerns seriously. While it’s important to enable secrets early in your pipeline development to prevent leaking information, doing so will also prevent costly troubleshooting efforts when when variables are converted to secrets.

Happy coding.

Saturday, June 06, 2020

Downloading Artifacts from YAML Pipelines

Azure DevOps multi-stage YAML pipelines are pretty darn cool. You can describe a complex continuous integration pipeline that produces an artifact and then describe the continuous delivery workflow to push that artifact through multiple environments in the same YAML file.

In today’s scenario, we’re going to suppose that our quality engineering team is using their own dedicated repository for their automated regression tests. What’s the best way to bring their automated tests into our pipeline? Let’s assume that our test automation team has their own pipeline that compiles their tests and produces an artifact so that we can run these tests with different runtime parameters in different environments.

There are several approaches we can use. I’ll describe them from most-generic to most-awesome.

Download from Azure Artifacts

A common DevOps approach that is evangelized in Jez Humble’s Continuous Delivery book, is pushing binaries to an artifact repository and using those artifacts in ad-hoc manner in your pipelines. Azure DevOps has Azure Artifacts, which can be used for this purpose, but in my opinion it’s not a great fit. Azure Artifacts are better suited for maven, npm and nuget packages that are consumed as part of the build process.

Don’t get me wrong, I’m not calling out a problem with Azure Artifacts that will you require you to find an alternative like JFrog’s Artifactory, my point is that it’s perhaps too generic. If we dumped our compiled assets into the artifactory, how would our pipeline know which version we should use? And how long should we keep these artifacts around? In my opinion, you’d want better metadata about this artifact, like source commits and build that produced it, and you’d want these artifacts to stick-around only if they’re in use. Although decoupling is advantageous, when you strip something of all semantic meaning you put the onus on something else to remember, and that often leads to manual processes that breakdown…

If your artifacts have a predictable version number and you only ever need the latest version, there are tasks for downloading these types of artifacts. Azure Artifacts refers to these loose files as “Universal Packages”:

- task: UniversalPackages@0
  displayName: 'Universal download'
  inputs:
    command: download
    vstsFeed: '<projectName>/<feedName>'
    vstsFeedPackage: '<packageName>'
    vstsPackageVersion: 1.0.0
    downloadDirectory: '$(Build.SourcesDirectory)\someFolder'

Download from Pipeline

Next up: the DownloadPipelineArtifact task is full featured built-in Task that can download artifacts from different sources, such as an artifact produced in an earlier stage, a different pipeline within the project, or other projects within your ADO Organization. You can even download artifacts from projects in other ADO Organizations if you provide the appropriate Service Connection.

- task: DownloadPipelineArtifact@2
  inputs:
    source: 'specific'
    project: 'c7233341-a9ff-4e76-9367-909816bcd16g'
    pipeline: 1
    runVersion: 'latest'
    targetPath: '$(Pipeline.Workspace)'

Note that if you’re downloading an artifact from a different project, you’ll need to adjust the authorization scope of the build agent. This is found in the Project Settings –> Pipelines : Settings. If this setting is disabled, you’ll need to adjust it at the Organization level first.

image

This works exactly as you’d expect it to, and the artifacts are downloaded to $(Pipeline.Workspace). Note in the above I’m using the project guid and pipeline id, which are populated by the Pipeline Editor, but you can specify them by their name as well.

My only concern is there isn’t anything that indicates our pipeline is dependent on another project. The pipeline dependency is silently being consumed… which feels sneaky.

build_download_without_dependencies

Declared as a Resource

The technique I’ve recently been using is declaring the pipeline artifact as a resource in the YAML. This makes the pipeline reference much more obvious in the pipeline code and surfaces the dependency in the build summary.

Although this supports the ability to trigger our pipeline when new builds are available, we’ll skip that for now and only download the latest version of the artifact at runtime.

resources:
 pipelines:
   - pipeline: my_dependent_project
     project: 'ProjectName'
     source: PipelineName
     branch: master

To download artifacts from that pipeline we can use the download alias for DownloadPipelineArtifact. The syntax is more terse and easier to read. This example downloads the published artifact 'myartifact' from the declared pipeline reference. The download alias doesn’t seem to specify the download location. In this example, the artifact is downloaded to $(Pipeline.Workspace)\my_dependent_project\myartifact

- download: my_dependent_project
  artifact: myartifact

With this in place, the artifact shows up and change history appears in the build summary.

build_download_with_pipeline_resource

Update: 2020/06/18! Pipelines now appear as Runtime Resources

At the time this article was written, there was an outstanding defect for referencing pipelines as resources. With this defect resolved, you can now specify the version of the pipeline resource to consume when manually kicking-off a pipeline run.

  1. Start a new pipeline run

    manually-trigger-build-select-resource
  2. Open the list of resources and select the pipeline resource

    manually-trigger-build-select-resource-pipeline
  3. From the list of available versions, pick the version of the pipeline to use:

    manually-trigger-build-select-resource-pipeline-version

With this capability, we now have full traceability and flexibility to specify which pipeline resource we want!

Conclusion

So there you go. Three different ways to consume artifacts.

Happy coding!

Monday, February 10, 2020

Challenges with Parallel Tests on Azure DevOps

As I wrote about last week, Adventures in Code Spelunking, relentlessly digging into problems can be a time-consuming but rewarding task.

That post centers around a tweet I made while I was struggling with an issue with VSTest on my Azure DevOps Pipeline. I'm feel I'm doing something interesting here: I've associated my automated tests to my test cases and I'm asking the VSTest task to run all the tests in the Plan; this is considerably different than just running the tests that are contained in the test assemblies. The challenge at the time was that the test runner wasn't finding any of my tests. My spelunking exercise revealed that the runner required an array of test suites despite the fact that the user interface restricts you to pick only one. I modified my yaml pipeline to contain a comma-delimited list of suites. Done!

Next challenge, unlocked!

Unfortunately, this would turn out to be a short victory, as I quickly discovered that although the VSTest task was able to find the test cases, the test run would simply hang with no meaningful insight as to why.

[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit .NET Core 3.1.1)
[xUnit.net 00:00:00.52]   Discovering: MyTests
[xUnit.net 00:00:00.57]   Discovered: MyTests
[xUnit.net 00:00:00.57]   Starting: MyTests
-> Loading plugin D:\a\1\a\SpecFlow.Console.FunctionalTests\TechTalk.SpecFlow.xUnit.SpecFlowPlugin.dll
-> Using default config

So, on a wild hunch I changed my test plan so that only a single test case was automated, and it worked. What gives?

Is it me, or you? (it’s probably you)

The tests work great on my local machine, so it’s easy to fall into a trap that the problem isn’t me. But to truly understand the problem is to be able to recreate it locally. And to do that, I’d need to strip away all the unique elements until I had the most basic setup.

My first assumption was that it might actually be the VSTest runner -- a possible issue with the “Run Test Plan” option I was using. So I modified my build pipeline to just run my unit tests like normal regression tests. And surprisingly, the results were the same. So, maybe it’s my tests.

Under a hunch that I might have a threading deadlock somewhere in my tests, I hunted through my solution looking for rogue asynchronous methods and notorious deadlock maker Task.Result. There were none that I could see. So, maybe there’s a mismatch in the environment setup somehow?

Sure enough, I had some mismatches. My test runner from the command-prompt was an old version. The server build agent was using a different version of the test framework than what I had referenced in my project. After upgrading nuget packages, Visual Studio versions and fixing the pipeline to exactly match my environment – I still was unable to reproduce the problem locally.

I have a fever, and the only prescription is more logging

Well, if it’s a deadlock in my code, maybe I can introduce some logging into my tests to put a spotlight on the issue. After some initial futzing around (I’m amazing futzing wasn’t caught by spellcheck, btw), I was unable to get any of these log messages to appear in my output. Maybe xUnit has a setting for this?

Turns out, xUnit has a great logging capability but requires a the magical presence of the xunit.runner.json file in the working directory.

{
  "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
  "diagnosticMessages": true
}

The presence of this file reveals this simple truth:

[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit .NET Core 3.1.1)
[xUnit.net 00:00:00.52]   Discovering: MyTests (method display = ClassAndMethod, method display options = None)
[xUnit.net 00:00:00.57]   Discovered: MyTests (found 10 test cases)
[xUnit.net 00:00:00.57]   Starting: MyTests (parallel test collection = on, max threads = 8)
-> Loading plugin D:\a\1\a\SpecFlow.Console.FunctionalTests\TechTalk.SpecFlow.xUnit.SpecFlowPlugin.dll
-> Using default config

And when compared to the server:

[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.4.1 (64-bit .NET Core 3.1.1)
[xUnit.net 00:00:00.52]   Discovering: MyTests (method display = ClassAndMethod, method display options = None)
[xUnit.net 00:00:00.57]   Discovered: MyTests (found 10 test cases)
[xUnit.net 00:00:00.57]   Starting: MyTests (parallel test collection = on, max threads = 2)
-> Loading plugin D:\a\1\a\SpecFlow.Console.FunctionalTests\TechTalk.SpecFlow.xUnit.SpecFlowPlugin.dll
-> Using default config

Yes, Virginia, there is a thread contention problem

The build agent on the server has only 2 virtual CPUs allocated and both executing tests are likely trying to spawn additional threads to perform the asynchronous operations. By setting the maxParallelThreads to “2” I am able to completely reproduce the problem from the server.

I can disable parallel execution in the tests by adding the following to the assembly:

[assembly: CollectionBehavior(DisableTestParallelization = true)]

…or by disabling parallel execution in the xunit.runner.json:

{
  "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
  "diagnosticMessages": true,
  "parallelizeTestCollections": false
}

submit to reddit

Friday, February 07, 2020

Adventures in Code Spelunking

image

It started innocently enough. I had an Azure DevOps Test Plan that I wanted to associate some automation to. I’d wager that there are only a handful of people on the planet who’d be interested by this, and I’m one of them, but the online walk-throughs from Microsoft’s online documentation seemed compatible with my setup – so why not? So, with some time in my Saturday afternoon and some horrible weather outside, I decided to try it out. And after going through all the motions, my first attempt failed spectacularly with no meaningful errors.

I re-read the documentation, verified my setup and it failed a dozen more times. Google and StackOverflow yielded no helpful suggestions. None.

It’s the sort of problem that would drive most developers crazy. We’ve grown accustomed to having all the answers a simple search away. Surely others have already had this problem and solved it. But when the oracle of all human knowledge comes back with a fat goose egg you start to worry that we’ve all become a group of truly lazy developers that can only find ready-made code snippets from StackOverflow.

When you are faced with this challenge, don’t give up. Don’t throw up your hands and walk away. Surely there’s an answer, and if there isn’t, you can make one. I want to walk you through my process.

Read the logs

If the devil is in the details, surely he’ll be found in the log file. You’ve probably already scanned the logs for obvious errors, it’s okay to go back and look again. If it seems the log file is gibberish at first glance, it often is. But sometimes the log contains some gems that give clues as to what’s missing. Maybe the log warns that a default value is missing, maybe you’ll discover a typo in a parameter.

Read the logs, again

Amp up the verbosity on the logs if possible and try again. Often developers use the verbose logging to diagnose problems that happen in the field, so maybe the hidden detail in the verbose log may reveal further gems.

Now’s a good moment for some developer insight. Are these log messages helpful? Would someone reading the logs from your program be as delighted or frustrated with the quality of these output messages?

Keep an eye out for references to class names or methods that appear in the log or stack traces. These could lead to further clues or give you a starting point for the next stage.

Find the source

Microsoft is the largest contributor to open-source projects on Github than anyone else, so it makes sense that they bought them. Just watching the culture shift within Microsoft in the last decade has been astounding and now it seems that almost all of their properties have their source code freely available for public viewing. Some sleuthing may be required to find the right repository. Sometimes it’s as easy as Googling “<name-of-class> github” or following the link on a nuget or maven repository.

But once you’ve found the source, you enter a world of magic. Best case scenario, you immediately find the control logic in the code that relates to your problem. Worse case scenario, you learn more about this component than anyone you know. Maybe you’ll discover they parse inputs as case sensitive strings, or some conditional logic requires the presence of a parameter you’re not using.

Within Github, your secret weapon is the ability to search within the repository, as you can find the implementation and usages in a single search. Recent changes within Github’s web-interface allows you to navigate through the code by clicking on class and method names – support is limited to specific programming languages but I’ll be in heaven when this capability expands. The point is to find a place to start and keep digging. It’ll seem weird not being able to set a breakpoint and simply run the app, but the ability to mentally trace through the code is invaluable. Practice makes perfect.

If you’re lucky, the output from the log file will help guide you. Go back and read it again.

As another developer insight – this code might be beautiful or make you want to vomit. Exposure to other approaches can validate and grow your opinions on what makes good software. I encourage all developers to read as much code that isn’t theirs.

After spending some time looking at the source, check out their issues list. You might discover your problem is known by a different name that is only familiar to those that wrote it. Alternative suitable workarounds might appear from other problems.

Roadblocks are just obstacles you haven’t overcome

If you hit a roadblock, it helps to step back and think of other ways of looking at the problem. What alternative approaches could you explore? And above all else, never start from a position where you assume everything on your end is correct. Years ago when I worked part-time at the local computer repair shop, I learnt the hard way that the easiest and most blatantly obvious step, checking to see if it was plugged in, was the most important step to not skip. When you keep an open-mind, you will never run out of options.

As evidenced by the tweet above, the error message I was experiencing was something that had no corresponding source-code online and all of my problems were baked into a black-box that only exists on the build server when the build runs. When the build runs… on the build server. When the build runs on the build agent… that I can install on my machine. Within minutes of installing a local build agent, I had the mysterious black-box gift wrapped on my machine.

No source code? No problem. JetBrain’s dotPeek is a free utility that allows you to decompile and review any .net executable.

Just dig until you hit the next obstacle. Step back, reflect. Dig differently. As I sit in a coffee shop looking out at the harsh cold of our Canadian winter, I reflect that we have it so easy compared to the original pioneers who forged their path here. That’s who you are, a pioneer cutting a path that no one has tread before. It isn’t easy, but the payoff is worth it.

Happy coding.

Thursday, February 06, 2020

GoodReads 2019 Recap

Hey Folks, like all posts that start in January, I’m starting my posts with the traditional …it’s been a while opener. Last year marks a first for this blog where I simply did not blog at all, which feels really strange. The usual suspects apply: busy at work, busy with kids, etc. However, in July of 2018 I started a new habit of taking a break from writing and focusing on reading more. I had planned to read 12 books in 2018 but read 20. Then I planned to read 24 in 2019 but read 41. I’ll probably have finished reading another book while I was writing this.

Maybe your New Year’s Resolution is to read more books. So, here are some highlights of book I read last year that you might enjoy:


The Murderbot Diaries

The Murderbot Diaries

Love, love, love Murderbot! By far, my favourite new literary character. The Murderbot diaries is set in the future where mankind has begun to explore planets beyond our solar system. If you were planning on exploring a planet, you’d hire a company to provide you with the assets to get there and as part of that contract, they’d provide you with a security detail to keep their assets you safe. Among that security detail is our protagonist, a security android that who has hacked his own governor module so it no longer needs to follow orders. What does a highly dangerous artificial intelligence with computer hacking skills and weapons embedded in its arms do with it’s own free will? Watch downloaded media and pretend to follow your orders. So. freaking. good.


The Broken Earth Series

The Broken Earth

The Fifth Season is strange mix of fantasy meets apocalypse survival, this series is so brilliantly written that I got emotional when it ended. The world-building is vast and revealed appropriately as the story progresses but this attention to creativity does not overwhelm the characters’ depth or story arcs. The world, perhaps our own, is a distant future where history is lost. Artifacts of dead-civilizations, like the crystal obelisks that float aimlessly in the sky have no explanation and every few hundred years, the earth undergoes a geological disaster known as a Season. Seasons may last for years. This one, may last for centuries.

Magic exists, but its source is a connection to the earth – an ability to delve, harness and channel the earth’s energy as a destructive force. For obvious reasons, those that are born with this ability are feared and thus rounded up and controlled by a ruling class. Our story involves a woman who secretly hides her ability and her kidnapped daughter who might be more powerful.

Recursion

Recursion: A Novel by [Crouch, Blake]

Blake Crouch blew me away in 2018 with Dark Matter, Recursion follows the story of a detective who investigates the suicide of a woman who suffers from a disease that creates a disconnect between their memories and reality. Is it an epidemic or a conspiracy?


The Southern Reach Trilogy (Annihilation, Authority, Acceptance)

Area X Three-Book Bundle: Annihilation; Authority; Acceptance (Southern Reach Trilogy) by [VanderMeer, Jeff]

I first heard of the book Annihilation from a CBC review of the bizarre and stunning visuals of the Annihilation movie starring Natalie Portman. The CBC review of the movie suggested that the director (Alex Garland) started the production of the movie before the 2nd and 3rd book of the series was written. Garland had support from the author, but it’s not surprising that the movie’s ending is radically different than the source material. I loved the movie, but needed to understand. The movie is a Kubrik mind-altering attempt to bring an unfilmable novel to the big screen, but the novel is so much more. The plot of the entire movie happens within the first few chapters, so if you liked the film the novel goes much further off the deep end. For example, the psychologist on the exhibition uses hypnosis and suggestive triggers on the rest of the exhibition to force compliance.  It’s not until our protagonist, the biologist, is infected by the effects of Area X does she become immune to the illusion.

The insidious aspect is the villain is a mysterious environment with no face, presence or motive. How do you defeat an environment? (spoiler: you can’t.  The invasive species wins (annihilation), the people in charge that are hiding the conspiracy have no idea how to stop it (authority), and the sooner you come to terms with it the better you’ll be (acceptance) – and maybe, given what we’ve done to the environment in the past, we deserve the outcome)

Sunday, March 11, 2018

On Code Reviews

Recently, a colleague reached out looking for advise on documentation for code reviews. It was a simple question, like so many others that arrive in my inbox phrased as a “quick question” yet don’t seem to have a “quick answer”. It struck me as odd that we didn’t have a template for this sort of thing. Why would we need this and under what circumstances would a template help?

After some careful contemplation, I landed on two scenarios for code review. One definitely needs a template, the other does not.

Detailed Code Analysis

If you’ve been tasked with writing up a detailed analysis of a code-base, I can see benefit for a structured document template. Strangely, I don’t have a template but I’ve done this task many different times. The interesting part of this task is that the need for the document is often to support a business case for change or to provide evidence to squash or validate business concerns. Understanding the driving need for the document will shape how you approach the task. For example, you may be asked to review the code to identify performance improvements. Or perhaps the business has lost confidence in their team’s ability to estimate and they want an outside party to validate that the code follows sound development practices (and isn’t a hot mess).

In general, a detailed analysis is usually painted in broad-strokes with high-level findings. Eg, classes with too many dependencies, insufficient error handling, lack of unit tests, insecure coding practices. As some of these can be perceived as the opinion of the author it’s imperative that you have hard evidence to support your findings. This is where tools like SonarCube shine as they can highlight design and security flaws, potential defects and even suggest how many hours of technical debt a solution has. Some tools like NDepend or JArchitect allow you to write SQL-like queries to find areas that need the most attention. For example, a query to “find highly used methods that have high cyclomatic complexity and low test coverage” can identify high yield pain points.

If I was to have a template for this sort of analysis, it would have:

  • An executive summary that provides an overview of the analysis and how it was achieved
  • A list of the top 3-5 key concerns where each concern has a short concise paragraph with a focus on the business impact
  • A breakdown of findings in key areas:
    • Security
    • Operational Support and Diagnostics
    • Performance
    • Maintainability Concerns (code-quality, consistency, test automation and continuous delivery).

Peer Code Review

If we’re talking about code-review for a pull-request, my approach is very different. A template might be useful here, but it’s likely less needed.

First, a number of linting tools such as FXCop, JSLint, etc can be included in the build pipeline so warnings and potential issues with the code are identified during the CI build and can be measured over time. Members of the team that are aware of these rules will call them out where appropriate in a code-reviews or they’ll set targets on reducing these warnings over time.

Secondly, it’s best to let the team establish stylistic rules and formatting rather than trying to enforce a standard from above. The reasoning for this should be obvious: code style can be a religious war where there is no right answer. If you set a standard from above, you’ll spend your dying breath policing a codebase where developers don’t agree with you. In the end, consistency throughout the codebase should trump personal preference, so if the team can decide like adults which rules they feel are important then they’re less likely to act like children when reviewing each other’s work.

With linting and stylistic concerns out of the way, what should remain is a process that requires all changes to be reviewed by one or more peers, and they should be reading the code to understand what it does or alternative ways that the author hadn’t considered. I’ve always seen code-review as a discussion, rather than policing, which is always more enjoyable.

Thursday, October 19, 2017

Xamarin.Forms with Caliburn.Micro walk-through

As of this morning, I posted a new version of my Xamarin.Forms with Caliburn.Micro Starter Kit on the Visual Studio Marketplace.

This video provides a quick walk-through of using the template.

submit to reddit

Monday, October 16, 2017

Jump start your next project with Xamarin.Forms Caliburn.Micro Starter Kit

Hey all! I’ve bundled my walkthrough of setting up a Xamarin.Forms to use Caliburn.Micro for Android, iOS and UWP into a Visual Studio Project Template and made it available in the Visual Studio Extensions Gallery

You can download it directly here, or from within Visual Studio: Tools –> Extensions and Updates –> Online.

Update 10/18/2017:

  • I had to republish the package as a “Tool” because it includes a few code snippets. The VS Gallery doesn’t allow you to change the classification of the VSIX, so I had to republish under a new identifier. You’ll need to uninstall and reinstall the new template.

image

As a multi-project, it’s very straight forward to use, simply choose File –> New and select “Xamarin.Forms with Caliburn.Micro”

image

Will create a project with the following structure:

image

Which, when run (on your platform of choosing) looks like this screenshot below. This is right where we left off from my walk-through earlier this year and is a great starting point for prototyping or building your next app.

image

Known Issues

  • Windows does not automatically create a signing key and identity for your app. Be sure to edit the UWP manifest and associate with your signing identity.

The source code for the starter kit can be found here. Let me know what you think!

submit to reddit

Tuesday, October 10, 2017

Bundle your Visual Studio Solution as a Multi-Project Template

Earlier this year I provided a walkthrough of setting up a Xamarin.Forms project that leveraged Caliburn.Micro for Android, iOS and UWP. I had big plans for extracting the contents of that walkthrough and providing it as a NuGet package. Plans changed however, and I’ve decided to package the entire solution as a Multi-Project Template and provide it as an add-on to Visual Studio (VSIX). This post introduces provides a walk-through on how to create multi-project templates.

Wait, why not NuGet?

First off, as an aside, let’s go back and look what I wanted to do. I wanted to provide a starter-kit of files that would jump start your efforts and allow you to modify my provided files as you see fit. As a NuGet package, I can deliver these files to any project simply by adding these loose code files in the content folder of the NuGet package. Two things that are really awesome about this: the code files can be treated as source code transforms by changing their extension to *.pp, and through platform targeting I could deliver different content files per platform (Xamarin.iOS10, Xamarin.Android10, uap10.0, etc). With this approach, you would simply create a new Xamarin.Forms project then add the NuGet package to all projects. Bam. Easy.

But there are a few problems with this approach:

  • Existing files. My NuGet package would certainly be replacing existing files in your solution. I’d want to overwrite key parts of the initial template (App.xaml, AppDelegate, Activity, etc) and in some cases delete files (MainPage.xaml). Technically, I can overcome these side-effects by modifying the project through a NuGet install script (install.ps1). However, you would be prompted during the install about the replacements and if you clicked ‘No’ when prompted to replace these files… my template wouldn’t work.
  • Delivering Updates. This is the funny thing about this approach -- it is really intended as a one time deal. You would add the starter files to your project and then begin to modify and extend to your hearts’ content. However, as the package author, no doubt I would find an issue or improvement for the package and publish it. If you were to update the package, it would repeat its initialization process and nuke your customizations. I would prefer not to see you when you’re angry.
  • Not guaranteed. Lastly, you could try and add the NuGet package to only one of your projects, or to a library that isn’t intended as a Xamarin.Forms project.

Above all else, the NuGet documentation clearly states that these files should be treated immutable and not intended to be modified by the consuming project. And since the best place to add the package is immediately after you create the project using a Visual Studio Template, why not just make a Template?

Creating a Multi-Project Template

While Multi-Project Templates have been around for a while, their tooling has improved considerably over the last few releases of Visual Studio. Although there isn’t a feature to export an entire solution as a multi-project, they conceptually work the same way as creating a single project template and then tweaking it slightly.

There are two ways to create a Project Template. The first and easiest is simply to select Project –> Export Template. The wizard that appears will prompt you for a Project and places your template in the My Exported Templates folder.

The second approach requires you to install the Visual Studio SDK, which can be found as an option in the initial installer. When you have the SDK installed, you can create a Project Template as an item in your solution. This project includes the necessary vstemplate files and produces the packaged template every time you build.

image

Effectively, a Project Template is just a zip file with a .vstemplate file in it. A Multi-Project Template has a single .vstemplate that points to templates in subfolders. Here’s how I created mine:

1. Create a Project Template project

Using the Visual Studio SDK, I created a Project Template project to my solution and modified the VSTemplate file with the appropriate details:

<VSTemplate Version="2.0.0" Type="ProjectGroup"
    xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
  <TemplateData>
    <Name>Xamarin.Forms with Caliburn.Micro</Name>
    <Description>Xamarin.Forms project with PCL library.</Description>
    <ProjectType>CSharp</ProjectType>
    <Icon>_icon.ico</Icon>
    <DefaultName>App</DefaultName>
    <ProvideDefaultName>true</ProvideDefaultName>
    <CreateNewFolder>true</CreateNewFolder>
    <RequiredFrameworkVersion>2.0</RequiredFrameworkVersion>
    <SortOrder>1000</SortOrder>
    <TemplateID>Your ID HERE</TemplateID>
  </TemplateData>
  <TemplateContent/>
</VSTemplate>


2. Export Projects and Add to the Project Template project

Next, simply export all the projects in your solution that you want to include in your template. The Project –> Export Template dialog looks like this:

image

Once you’ve exported the projects as templates take each of the zip files and extract them into a subfolder of your Template Project. Then, in Visual Studio, include these extracted subfolders as part of the project. Note that Visual Studio will assign a default Action for each file, so code files will be set to Compile, images will be set as EmbeddedResource, etc. You’ll have to go through each of these files and change the default action to Content, copy if newer. It’s a pain, and I found it easier to unload the project and manually edit the csproj file directly.

3. Configure the Template to include the embedded Projects

Now that we have the embedded projects included in the output, we need to modify the template to point to these embedded templates. Visual Studio has a set of reserved keywords that can be used in the vstemplate and code transforms; $safeprojectname$ is a reserved keyword that represents the name of the current project. My vstemplate names the referenced templates after the name that was provided by the user:

<VSTemplate Version="2.0.0" Type="ProjectGroup"
    xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
  <TemplateData>
    ...
  </TemplateData>
  <TemplateContent>
    <ProjectCollection>
      <ProjectTemplateLink ProjectName="$safeprojectname$" CopyParameters="true">XF\MyTemplate.vstemplate</ProjectTemplateLink>
      <ProjectTemplateLink ProjectName="$safeprojectname$.Android" CopyParameters="true">XF.Android\MyTemplate.vstemplate</ProjectTemplateLink>
      <ProjectTemplateLink ProjectName="$safeprojectname$.UWP" CopyParameters="true">XF.UWP\MyTemplate.vstemplate</ProjectTemplateLink>
      <ProjectTemplateLink ProjectName="$safeprojectname$.iOS" CopyParameters="true">XF.iOS\MyTemplate.vstemplate</ProjectTemplateLink>
    </ProjectCollection>
  </TemplateContent>  
</VSTemplate>

If the ProjectName is omitted, it will use the name within the embedded template.

4. Fix Project References

To ensure the project compiles, we must fix the project references to the PCL library in the iOS, Android and UWP projects. Here we leverage an interesting feature of Multi-Project templates – Visual Studio provides special reserved keywords for accessing properties of the root template project. In this case, we can reference the safeprojectname of the root project using the $ext_safeprojectname$ reserved keyword. And because project references use a GUID to refer to the referenced project, we can provide the PCL project with a GUID that will be known to all the child projects – in this case, we can use $ext_guid1$.

The <ProjectGuid> element in the PCL Project must be configured to use the shared GUID:

<PropertyGroup>
  <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
  <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
  <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
  <ProjectGuid>{$ext_guid1$}</ProjectGuid>
  <OutputType>Library</OutputType>
  <AppDesignerFolder>Properties</AppDesignerFolder>
  <RootNamespace>$safeprojectname$</RootNamespace>
  <AssemblyName>$safeprojectname$</AssemblyName>
  <FileAlignment>512</FileAlignment>
  <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
  <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
  <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
  <NuGetPackageImportStamp>
  </NuGetPackageImportStamp>
</PropertyGroup>

In the projects that reference the PCL, the path to the project, project GUID and Name must be also be modified:

<ItemGroup>
  <ProjectReference Include="..\$ext_safeprojectname$\$ext_safeprojectname$.csproj">
    <Project>{$ext_guid1$}</Project>
    <Name>$ext_projectname$</Name>
  </ProjectReference>
</ItemGroup>

5. Fix-ups

Lastly, there will be some other fix-ups you will need to apply. These are things like original project names that appear in manifest files, etc. The templating engine can make changes to any type of file, but you may need to verify that these files have the ReplaceParameters attribute set to True in the .vstemplate file.

Build and Deploy!

With this in place, you can simply compile the Project Template and copy the zip to ProjectTemplates folder. Optionally, you can add a VSIX project to the solution that you can use to bundle our Project Template as an installer that you can distribute to users via the Visual Studio Extensions Gallery.

Happy coding!

submit to reddit

Thursday, September 28, 2017

Unit testing Xamarin.Forms Behaviors

So in my last post, I outlined how I’m unit testing my Xamarin.Forms projects. Today, I want to highlight a practical example of unit testing a Behavior.

Let’s take a simple behavior that prevents item selection in a ListView:

public class DisableListViewSelection : Behavior<ListView>
{
    private ListView _attached;

    protected override void OnAttachedTo(ListView bindable)
    {
        _attached = bindable;

        if (_attached != null)
        {
            _attached.ItemSelected += Bindable_ItemSelected;
        }
    }


    protected override void OnDetachingFrom(ListView bindable)
    {
        if (_attached != null)
        {
            _attached.ItemSelected -= Bindable_ItemSelected;
        }
    }

    private void Bindable_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        _attached.SelectedItem = null;
    }
}

Unit testing the behavior should be straight forward but there are a few gotchas.

The first concern is that we're testing a visual that requires Xamarin.Forms to be initialized using Xamarin.Forms.Forms.Init();. This is easily addressed using the Xamarin.Forms.Mocks nuget package I mentioned in my last post.

The second concern is that the Behavior<T> implementation explicitly implements the IAttachedObject interface which is marked as internal. We can address this with some Reflection hackery.

I’ve addressed both concerns with the following base test fixture:

public abstract class BaseBehaviorTests<TSubjectBehavior, TTargetElement> : INotifyPropertyChanged
    where TSubjectBehavior : Behavior<TTargetElement>, new() 
    where TTargetElement : BindableObject, new()
{
    private BindingFlags _bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;

    public TTargetElement ContainingElement { get; set; }
    public TSubjectBehavior Subject { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public virtual void Setup()
    {
        Xamarin.Forms.Mocks.MockForms.Init();

        Subject = new TSubjectBehavior();
        ContainingElement = new TTargetElement();
    }

    protected virtual void Attach()
    {
        Subject.GetType().GetMethod("Xamarin.Forms.IAttachedObject.AttachTo", _bindingFlags).Invoke(Subject, new object[] { ContainingElement });
    }

    protected virtual void Detach()
    {
        Subject.GetType().GetMethod("Xamarin.Forms.IAttachedObject.DetachFrom", _bindingFlags).Invoke(Subject, new object[] { ContainingElement });
    }

    protected void NotifyPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Take a quick peek at the Attach/Detach methods. The IAttachedObject.AttachTo method is explicitly implemented on the class so we have to use the full namespace of the method to resolve it. If it was implicitly implemented, we could simply use "AttachTo".

Now that we have this test fixture capability, writing a test for our DisableListViewSelectionBehavior is dead simple:

[TestClass]
public class DisableListViewSelectionBehaviorTests : BaseBehaviorTests<DisableListViewSelection, ListView>
{
    List<object> _list = new List<object>();

    [TestInitialize]
    public override void Setup()
    {
        _list.Add(new object());

        base.Setup();
    }

    [TestMethod]
    public void WhenSelectingItem_AndAttachedToBehavior_ShouldUnselectedItem()
    {
	// arrange
	Attach();
        ContainingElement.ItemsSource = _list;

	// act
        ContainingElement.SelectedItem = _list.First();

	// assert
        ContainingElement.SelectedItem.ShouldBeNull();
    }

    [TestMethod]
    public void WhenSelectingItem_AndDetachedFromBehavior_ShouldKeepSelectedItem()
    {
	// arrange
        Detach();
        ContainingElement.ItemsSource = _list;

	// act
        ContainingElement.SelectedItem = _list.First();

	// assert
        ContainingElement.SelectedItem.ShouldNotBeNull();
    }
}


Well, that's all for now. My next post will look at behaviors with data binding.

Happy coding!

submit to reddit

Wednesday, September 27, 2017

Unit testing Xamarin.Forms

As a TDD Evangelist, I’m well aware of the dichotomy between desired and actual testing practices. It can be hard to write tests when we’re rapid prototyping, and we can convince ourselves that we’re writing testable code, but at some point, you need to establish some testing practices before things scale beyond your reach. This week I’ve been looking at some code where I supported the engineering team but unit testing wasn’t our top priority. I’m glad that I helped shape the code with testability in mind, but now that I’m writing unit tests for the code I’m discovering fallacies in our thinking and areas that are proving difficult to test.

Still, I’ve managed to go from 0% to 50% code coverage in about 10 days which is promising. I’m also hopeful that there’ll be lots more code in testable areas so this number should only trend upward. These last few days I’ve been looking at squeezing out a few extra tests for some of the custom behaviors and I quickly discovered that testing code for visual elements is challenging. Here’s a breakdown of how I’m approaching testing for Xamarin.Forms.

Project Setup

First off, since 90% of my logic resides within the shared PCL layer my focus is on writing unit tests for ViewModels, Services and Behaviors. Some services are platform specific and for those I will likely need to test using Xamarin.iOS or Xamarin.Android, but for the PCL layer I’m using MSTest and .NET 4.6. The choice for using a .NET library instead of Xamarin.iOS or Xamarin.Android is largely for convience and speed of running the tests as they don’t require an emulator or device, and I’m also targetting UWP so I have to compile on a windows machine regardless. I also want to leverage a mocking framework like Moq which won’t work correctly on Mono.

Mocking

For unit testing my ViewModels, I wrote a simple extension to Caliburn.Micro’s dependency container that can automatically fill my viewmodels with fake dependencies.

public class TestContainer : SimpleContainer
{
    public T CreateSubject<T>()
    {
        Type targetType = typeof(T);

        var greedyConstructor = targetType
            .GetConstructors()
            .OrderByDescending(i => i.GetParameters().Length)
            .FirstOrDefault();

        foreach(var arg in greedyConstructor.GetParameters())
        {
            // handle IEnumerable<T> in constructor
            if (typeof(IEnumerable).IsAssignableFrom(arg.ParameterType))
            {
                var genericType = arg.ParameterType.GenericTypeArguments[0];

                // ensure we have at least one item in the array
                if (!HasHandler(genericType, null))
                {
                    CreateAndInsertMock(genericType);
                }
            }
            else
            {
                if (!HasHandler(arg.ParameterType, null))
                {
                    CreateAndInsertMock(arg.ParameterType);
                }
            }
        }

        this.PerRequest<T>();

        return this.GetInstance<T>();
    }
    
    public Mock<T> GetMock<T>() where T : class
    {
        var obj = this.GetInstance<T>();
        if (obj == null)
        {
            throw new InvalidOperationException("Mock is not directly used by the subject.");
        }

        return Mock.Get(obj);
    }

    public Mock<T> GetMock<T>(int index) where T : class
    {
        var instances = this.GetAllInstances<T>();

        return Mock.Get(instances.ToArray()[index]);
    }

    public Mock<T> AddMock<T>(params Type[] interfaces) where T : class
    {
        var mock = new Mock<T>();
        mock.SetupAllProperties();

        if (interfaces.Length > 0)
        {
            var asMethodInfo = mock.GetType().GetMethod("As");
            foreach(var def in interfaces)
            {
                var method = asMethodInfo.MakeGenericMethod(def);
                method.Invoke(mock, null);
            }
        }

        var instance = mock.Object;

        RegisterInstance(typeof(T), null, instance);
        foreach (var def in interfaces)
        {
            RegisterHandler(def, null, container => instance);
        }            

        return mock;
    }        

    private Mock CreateAndInsertMock(Type targetType)
    {
        var method = this.GetType().GetMethod("AddMock").MakeGenericMethod(targetType);
        return (Mock)method.Invoke(this, new object[] { new Type[] { } } );
    }
}

This coupled with a base test fixture really helped to get my viewmodels under the test microscope quickly.

public abstract class BaseViewModelTest<T> where T : BaseScreen
{
    private TestContainer _container;    

    protected T Subject { get; set; }

    public virtual void Setup()
    {
        _container = new TestContainer();
        Subject = _container.CreateSubject<T>();
    }

    protected Mock<TDependency> Get<TDependency>() where TDependency : class
    {
        reutnr _container.GetMock<TDependency>();
    }

    protected Mock<TDependency> Set<TDependency>() where TDependency : class
    {
        return _container.AddMock<TDependency>();
    }

    protected void Activate()
    {
        var activatable = Subject as Caliburn.Micro.IActivate;
        if (activatable != null)
        {
            activatable.Activate();
        }
    }
}

[TestClass]
public class HomeScreenTests : BaseViewModelTest<HomeScreenViewModel>
{
    [TestInitialize]
    public override void Setup()
    {
        base.Setup();

        // additional setup
    }

    // Tests...
}

Testing UI Elements

As I started writing unit tests for controls and behaviors, I realized that any Xamarin.Forms UI element was going to require the Xamarin.Forms.Forms.Init() method to be invoked, which would not work for my test project. Further investigation revealed that most of the plumbing within Xamarin is marked as internal or with the [EditorBrowsable(EditorBrowsableState.Never)] which makes it impossible for us to initialize with mocks …externally. The only way to get at these internals is through the InternalsVisibleTo attribute.

Fortunately, Xamarin MVP Jon Peppers has discovered the same issue and realized a small security flaw in Xamarin’s usage of [InternalsVisibleTo]. Since their usage doesn’t require the use of a public key, anyone can access these internals if they name their assembly a certain way. Jon has published a nuget package that contains Xamarin.Forms.Core.UnitTests.dll assembly. His dummy versions act as a great stand-in for bypassing the platform dependencies allowing us to write tests for simple functionality instead of platform behavior.

My next few posts will cover a few practical examples.

submit to reddit

Monday, September 18, 2017

Extension methods for Caliburn.Micro SimpleContainer

Caliburn.Micro ships with an aptly named basic inversion of control container called SimpleContainer. The container satisfies most scenarios, but I’ve discovered a few minor concerns when registering classes that support more than one interface.

Suppose I have a class that implements two interfaces: IApplicationService and IMetricsProvider:

public class MetricsService : IApplicationService, IMetricsProvider
{
    #region IApplicationService
    public void Initialize()
    {
        // initialize metrics...
    }
    #endregion

    #region IMetricsProvider
    public void IncrementMetric(string metricName)
    {
        // do something with metrics...
    }
    #endregion
}

The IApplicationService is a pattern I usually implement where I want to configure a bunch of background services during application startup, and the IMetricsProvider is a class that will be consumed elsewhere in the system. It's not a perfect example, but it'll do for our conversation...

The SimpleContainer implementation doesn't have a good way of registering this class twice without registering them as separate instances. I really want the same instance to be used for both of these interfaces. Typically, to work around this issue, I might do something like this:

var container = new SimpleContainer();

container.Singleton<IMetricsProvider,MetricsService>();

var metrics = container.GetInstance<IMetricsProvider>();
container.Instance<IApplicationService>(metrics);

This isn't ideal though it will work in trivial examples. Unfortunately, this approach can fail if the class has additional constructor dependencies. In that scenario, the order in which I register and resolve dependencies becomes critical. If you resolve in the wrong order, the container injects null instances.

To work around this issue, here's a simple extension method:

public static class SimpleContainerExtensions
{
    public static SimpleContainerRegistration RegisterSingleton<TImplementation>(this SimpleContainer container, string key = null)
    {
        container.Singleton<TImplementation>(key);
        return new SimpleContainerRegistration(container, typeof(TImplementation), key);
    }
    
    class SimpleContainerRegistration
    {
        private readonly SimpleContainer _container;
        private readonly Type _implementationType;
        private readonly string _key;
    
        public SimpleContainerRegistration(SimpleContainer container, Type type, string key)
        {
            _container = container;
            _implementationType = type;
            _key = key;
        }
    
        public SimpleContainerRegistration AlsoAs<TInterface>()
        {
            container.RegisterHandler(typeof(TInterface), key, container => container.GetInstance(_implementationType, _key));
            return this;
        }
    }
}

This registers the class as a singleton and allows me to chain additional handlers for each required interface. Like so:

var container = new SimpleContainer();

container.RegisterSingleton<MetricsService>()
    .AlsoAs<IApplicationService>()
    .AlsoAs<IMetricsProvider>();

Happy coding!

submit to reddit

Tuesday, September 05, 2017

Dynamically hiding Cells in a TableView

Suppose you have a fixed list of items that you want to display in a Xamarin.Forms TableView, but you want some rows and sections of that table to be hidden. Unfortunately, there isn’t a convenient IsVisible property on the TableSection or Cell elements that we can bind to, and the only way to manipulate them is through code. Here’s a quick look on how to collapse our Cells and Sections using an Attached Property.

Take this example layout:

<ContentPage>

    <Grid>
        <TableView Intent="Settings">
            <TableRoot>
                <TableSection Title="Group 1">
                    <SwitchCell Title="Setting 1" />
                    <SwitchCell Title="Setting 2" />
                </TableSection>
                <TableSection Title="Group 2">
                    <SwitchCell Title="Setting 3" />
                    <SwitchCell Title="Setting 4" />
                </TableSection>
            </TableRoot>
        </TableView>
    </Grid>

</ContentPage>

In the above, I have two TableSection elements that contain two very simple SwitchCell elements. A lot of the detail has been omitted for clarity, but let's assume that I want the ability to only show certain settings to the user. Perhaps each setting is controlled by a special backend entitlement logic, and I want to bind that visibility for each cell through my ViewModel.

We'll create an attached property that can hide our cells:

public class CellEx
{

    public static BindableProperty CollapsedProperty =
        BindableProperty.CreateAttached(
            "Collapsed",
            typeof(bool?),
            typeof(CellEx),
            default(bool?),
            defaultBindingMode: BindingMode.OneWay,
            propertyChanged: OnCollapsedChanged);

    public static bool GetCollapsed(BindableObject target)
    {
        return (bool)target.GetValue(CollapsedProperty);
    }

    public static void SetCollapsed(BindableObject target, bool value)
    {
        target.SetValue(CollapsedProperty, value);
    }

    private static void OnCollapsedChanged(BindableObject sender, object oldValue, object newValue)
    {
        // do work with cell
    }
}

The OnCollapsedChanged event handler is called when the bound value of the BindableProperty is first set and we’ll use it to obtain a reference to the Cell. As the binding is potentially invoked before the UI is fully initialized we’ll need to defer our changes until it’s ready:

private static void OnCollapsedChanged(BindableObject sender, object oldValue, object newValue)
{
    var view = sender as Cell;
    bool isVisible = (bool)newValue;
    if (view != null)
    {
        // the parent isn't available until the page has loaded.
        if (view.Parent == null)
        {
            view.Appearing += (o,e) => 
            {
                ToggleViewCellCollapsedState(view, isVisible);
            };
        }
        else
        {
            ToggleViewCellCollapsedState(view, isVisible);
        }
    }
}

Once we have an initialized Cell, we need to obtain a reference to the containing TableSection. As a twist, the Parent of the Cell is the root TableView, so we must traverse the entire table downward to find the correct TableSection. Since a TableView only contains a fixed list of cells, scanning the entire table shouldn't be too troublesome at all:

private static void ToggleViewCellCollapsedState(Cell cell, bool isVisible)
{
    var table = (TableView)cell.Parent;
    TableSection container = FindContainingTableSection(table, cell);
    if (container != null)
    {
        if (!isVisible)
        {
            // do work to hide cell
        }
    }
}

private static TableSection FindContainingTableSection(TableView table, Cell cell)
{
    foreach(var section in table.Root)
    {
        foreach(var child in section)
        {
            if (child == cell)
            {
                return section;
            }
        }
    }

    return null;
}

Lastly, once we've obtained the necessary references, we can simply manipulate the TableSection contents. To ensure this works on all platforms, this code must execute on the UI thread:

if (!isVisible)
{

    Device.BeginInvokeOnMainThread(() => 
    {
        // remove the cell from the section
        container.Remove(cell);

        // remove the section from the table if it's empty
        if (container.Count == 0)
        {
            table.Root.Remove(container);
        }
    });
}

We can then bind the visibility of our cells to the attached property:

<ContentPage
    xmlns:ex="clr-namespace:MyNamespace.Behaviors"
    >

    <Grid>
        <TableView>
            <TableRoot>
                <TableSection Title="Group 1">
                    <SwitchCell Title="Setting 1" ex:CellEx.Collapsed={Binding IsSetting1Visible}" />
                    <SwitchCell Title="Setting 2" ex:CellEx.Collapsed={Binding IsSetting2Visible}" />
                </TableSection>
                <TableSection Title="Group 2">
                    <SwitchCell Title="Setting 3" ex:CellEx.Collapsed={Binding IsSetting3Visible}" />
                    <SwitchCell Title="Setting 4" ex:CellEx.Collapsed={Binding IsSetting4Visible}" />
                </TableSection>
            </TableRoot>
        </TableView>
    </Grid>

</ContentPage>

This works great and can dynamically hide individual cells or an entire section if needed. The largest caveat to this approach is that it only hides cells and won’t re-introduce them into the view when the binding changes. This is entirely plausible as you could cache the cells in a local variable and re-insert them programmatically, but you’d need to remember the containing section and appropriate indexes. I’d leave that to you dear reader, or I may rise to the challenge if I determine I really want to re-activate these cells in my app.

Happy coding!

submit to reddit

Monday, July 03, 2017

Troubleshooting Xamarin iPhoneSimulator errors from Visual Studio

I’m using the Xamarin Mac BuildAgent to compile my Xamarin.Forms app from Visual Studio and test it using the device simulator on my Mac. This solution was working really well for me until one day, it wasn’t. I could compile and deploy to the Simulator fine, but I was seeing errors at runtime that simply weren’t there on Android or UWP. To make matters worse, my colleagues weren’t seeing this problem when compiling and deploying to an actual device.

The problem started when we added Azure Mobile Services to our project. The errors we were seeing weren’t very helpful at all, either a TypeLoadException or NullReferenceException and they appear when trying to invoke calls that were part of the Mobile Services client. These errors are frustrating because the error detail in Visual Studio provides little guidance as to why these calls aren’t working, especially when the same calls were working before adding the reference.

The forums and usage for Azure Mobile Services recommends that you must invoke CurrentPlatform.Init() to ensure that some of the extended assemblies that are dynamically loaded at runtime are linked into the output during compilation. I’ve seen similar problems before in WPF where the compilation process would optimize away assemblies that contain only DataTemplates and Styles – effectively, if they don’t contain byte-code then the compiler will not list the reference as a dependency.

Unfortunately our team was already using CurrentPlatform.Init() in our code, and since the error was only specific to the iPhoneSimulator it suggested an issue with the Linking used for the Debug_iPhoneSimulator configuration. Although the Linker Behavior is set to Don’t link – which effectively takes all assemblies without attempting to optimize – we added the –linkskip arguments to both the main Azure Mobile Service assembly and its platform equivalent (Microsoft.WindowsAzure.Mobile.Ext).

image

This strangely seemed to resolve the issue, at least partially. We could get further along in our app initialization before the app would hang.

Inspecting the Logs

Often, the errors from Xamarin will recommend checking the logs. There are two logs to check:

  • Xamarin Logs. These logs are found through Visual Studio: Help –> Xamarin –> Open Logs. They show diagnostics for Xamarin within Visual Studio and are especially useful for understanding deployment errors such as connectivity with the Mac BuildAgent.
  • Device Logs. These logs can be found on the Mac. Simulator: Debug –> Open System Log. These logs contain the paydirt of what’s happening with the logs and provides insights into the inner exceptions that don’t bubble up into Visual Studio.

In my case, looking at the Simulator’s Device Log showed the critical missing piece of information. I was missing a reference to a reference. I was missing a reference to System.Net.Http!

Jul 2 13:35:15 Bryans-MacBook-Pro MyAppiOS[24157]: Could not find `System.Net.Http` referenced by assembly `Xamarin.Forms.Platform.iOS, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null`. 
Jul 2 13:35:15 Bryans-MacBook-Pro MyAppiOS[24157]: Could not find `System.Net.Http` referenced by assembly `Microsoft.WindowsAzure.Mobile, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35`. 
Jul 2 13:35:15 Bryans-MacBook-Pro MyAppiOS[24157]: Could not find `System.Net.Http` referenced by assembly `Xamarin.Auth, Version=1.3.0.0, Culture=neutral, PublicKeyToken=null`. 
Jul 2 13:35:15 Bryans-MacBook-Pro MyAppiOS[24157]: Could not find `System.Net.Http` referenced by assembly `Microsoft.WindowsAzure.Storage, Version=7.1.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35`.

The logs contain .NET StackTraces and Exception details, which provide excellent supporting information for errors that occur in the IDE. And now that the simulator actually works it’ll be used a great deal more often.

Monday, May 01, 2017

Xamarin + Parallels for Mac

Well, it took the better half of a Saturday installing updates for what seems like everything, but I managed to my MacBook Pro running Visual Studio 2015 and able to deploy to the iPhone Simulator through the Xamarin Mac Agent. I was surprised at how easy it was and only one minor caveat I had to work through…

My Saturday began with starting my Windows 10 virtual machine on my Mac and being greeted with a warning regarding a conflict between Parallels for Mac 11 and the Windows 10 Creator’s Update. I hadn’t installed the Creators Update yet, so I decided there was no better time than the present to update my Parallels installation. The installation was quick and painless.

When I started my Windows 10 virtual machine, it was a bit unresponsive so I decided to restart it. However, my only options were to “Update and Shutdown” or “Update and Restart”. Sigh. Ok, let’s update this too.

Sure enough, the update was the Windows 10 Creators Update. Well, at least I updated Parallels first.

While I was waiting for this to complete, a notification from my Mac popped up: that update that required me to be connected to power didn’t run last night. It seems like my Mac has been nagging me for a while now to perform this update and I always choose “Later”. “Later” usually means the next day I’m warned about not being connected to a power source. Sigh. Ok, fine. I’m updating Windows, why not update the Mac?

Crap. That update was for Mac Sierra which I thought I had already installed. Maybe it’ll be quick. Wishful thinking for an OS update I suppose.

Both the Mac and Windows seemed to update around the same time, almost like they were in competition of completing before the other. Finally. Let’s do this.

When I booted up Visual Studio 2015 I was surprised that the usual Xamarin menu options weren’t available. I launched the Extensions and Updates option and realized that Visual Studio Update 2 wasn’t installed. I’d forgotten that I wasn’t using my Parallels for this (hence this post) and I’d been using my PC to do most of my builds and only using the Mac for the Xamarin Mac Agent. I started the Update 3 wizard and selected the 13 GBs of features that I needed. Let’s grab some lunch while this completes.

When I came back to my Mac, Visual Studio 2015 was already running and waiting for me. I launched the Xamarin Mac Agent and it immediately found my Mac. I logged in without issues. Brilliant. I decided to tempt fate and create a new Xamarin.Forms Portable application, compile and run on my iOS simulator. After creating the solution, Xamarin informed me that there was an update available. The rate things were going, I might as well do this now, right?

While I was updating the Xamarin NuGet package, I toggled back to my Mac and checked to see if there was an update for my Xamarin Studio. Yeah, I’m pretty sure you knew there’d be one too. Lots of downloads and updates.

OK FINE. Everything’s good now. Let’s compile this bad boy and try out deploying to my mac from Visual Studio.

Sadly, I was presented with a wack of compilation errors. Turns out, parts of my Xamarin.Android weren’t being resolved during compilation. The workaround appears in Xamarin’s troubleshooting section, so it must be somewhat common. I had to download a ~200Mb file, rename it and place it a specific folder and I was back in business. Compiling took 20 minutes while everything re-unpacked and initialized.

Everything compiles! Life is good. It’s about time we deploy to my mac from Visual Studio? Sweet Christmas, now it’s complaining that my version of Xamarin requires an update to XCode 8.3.

Fortunately, XCode 8.3 is only 2.5 GB and I must really want to compile and deploy. I fire-up Fantastic Beasts and where to find them while I wait.

About half way through the movie, I check out my Mac. I reboot and had to force a reboot on my windows 10 virtual machine.

I compiled. It worked. I clicked deploy. It worked. Hopefully the benefits of only having to carry around a single device provides enough productivity gains to outweigh this productivity disaster.

Oh – I mentioned a caveat. I wasn’t able to compile the solution using the default parallels mapped folder location \\Mac\\Home\\Documents. I changed this to a different folder on the machine.

Well, there you go. I think this post was more of a rant than any helpful tip. If you made it to the end, a cookie for you, I guess. Hope you enjoyed reading my adventure. Do you think Dumbledore will battle Grindlewald in the next movie?

Monday, April 24, 2017

My favourite Visual Studio Snippets

It happens a fair bit: there’s a small identical piece of code that you have to need to include in each project you work on. Sometimes you can copy and paste from an old project or you simply write it from scratch. You do this over and over so much that you get used to writing it.

Fortunately, Visual Studio “snippets” can tame this monster. Simply type a keyword and hit tab twice and – bam! – code magically appears. But if you’re like me, the thought of deviating from your project to write a snippet can seem tedious. Lucky for you, you don’t have to write them, you can just borrow my favourite snippets.

vmbase

My vmbase snippet includes some common boilerplate code for INotifyPropertyChanged. It includes the SetField<T> method you may see in a few of my posts. After adding this snippet, be sure to decorate your class with INotifyPropertyChanged.

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Base ViewModel implementation</Title>
            <Shortcut>vmbase</Shortcut>
            <Description>Inserts SetField and NotifyPropertyChanged</Description>
            <Author>BCook</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Imports>
                <Import>
                    <Namespace>System.Collections.Generic</Namespace>
                </Import>
                <Import>
                    <Namespace>System.ComponentModel</Namespace>
                </Import>
                <Import>
                    <Namespace>System.Runtime.CompilerServices</Namespace>
                </Import>

            </Imports>
            <Declarations>
            </Declarations>
            <Code Language="csharp"><![CDATA[
            protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
            {
                if (!EqualityComparer<T>.Default.Equals(field, value))
                {
                    field = value;
                    NotifyPropertyChanged(propertyName);
                    return true;
                }
                
                return false;
            }
            
            protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
            {
                var handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyName));
                }
            }
$end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

propvm

The propvm snippet is similar to other “prop” snippets. It creates a property with a backing field and uses the SetField<T> method for raising property change notifications.

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Define a Property with SetField</Title>
            <Shortcut>propvm</Shortcut>
            <Description>Code snippet for a ViewModel property</Description>
            <Author>Bryan Cook</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Property Type</ToolTip>
                    <Default>string</Default>
                </Literal>
                <Literal>
                    <ID>property</ID>
                    <ToolTip>Property Name</ToolTip>
                    <Default>MyProperty</Default>
                </Literal>
                <Literal>
                    <ID>field</ID>
                    <ToolTip>Field Name</ToolTip>
                    <Default>myProperty</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[
private $type$ _$field$;

public $type$ $property$
{
    get { return _$field$; }
    set { SetField(ref _$field$, value); }
}
$end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

propbp

Similar to the propdp snippet which creates WPF dependency properties, propbp creates a Xamarin.Form BindableProperty.

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Define a Xamarin.Forms Bindable Property</Title>
            <Shortcut>propbp</Shortcut>
            <Description>Code snippet for Xamarin.Forms Bindable Property</Description>
            <Author>Bryan Cook</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Imports>
                <Import>
                    <Namespace>Xamarin.Forms</Namespace>
                </Import>
            </Imports>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Property Type</ToolTip>
                    <Default>string</Default>
                </Literal>
                <Literal>
                    <ID>property</ID>
                    <ToolTip>Property Name</ToolTip>
                    <Default>MyProperty</Default>
                </Literal>
                <Literal>
                    <ID>owner</ID>
                    <ToolTip>Owner Type for the BindableProperty</ToolTip>
                    <Default>object</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[
#region $property$
public static BindableProperty $property$Property =
    BindableProperty.Create(
        "$property$",
        typeof($type$),
        typeof($owner$),
        default($type$),
        defaultBindingMode: BindingMode.OneWay,
        propertyChanged: On$property$Changed);
        
private static void On$property$Changed(BindableObject sender, object oldValue, object newValue)
{
}
#endregion

public $type$ $property$
{
    get { return ($type$)GetValue($property$Property); }
    set { SetValue($property$Property, value); }
}

$end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

testma

Visual Studio ships with a super helpful testm snippet which generates a MSTest test method for you. My simple testma snippet creates an asynchronous test method.

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>Async Test Method</Title>
            <Shortcut>testma</Shortcut>
            <Description>Inserts Test Method with async keyword</Description>
            <Author>BCook</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Imports>
                <Import>
                    <Namespace>Microsoft.VisualStudio.TestTools.UnitTesting</Namespace>
                </Import>
                <Import>
                    <Namespace>System.Threading.Tasks</Namespace>
                </Import>
            </Imports>
            <References>
                <Reference>
                    <Assembly>Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll</Assembly>
                </Reference>
            </References>        
            <Declarations>
                <Literal>
                    <ID>method</ID>
                    <ToolTip>MethodName</ToolTip>
                    <Default>TestMethodName</Default>
                </Literal>
                <Literal Editable="false">
                    <ID>TestMethod</ID>
                    <Function>SimpleTypeName(global::Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod)</Function>
                </Literal>                
            </Declarations>
            <Code Language="csharp"><![CDATA[
            [$TestMethod$]
            public async Task $method$()
            {
                // await ...
                Assert.Fail();
            }
            
$end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

Installing Snippets

To install the snippets:

  1. Copy/paste each snippet into a dedicated file on your hard-drive, eg propbp.snippet
  2. In Visual Studio, select Tools –> Code Snippets Manager
  3. Click the Import button
  4. Navigate to the location where you put the snippets
  5. Select one or more snippet files.
  6. Click Open and Ok.

To use them, simply type the keyword for the snippet (as defined in the ShortCut element in the snippet) and press the tab key twice.

Note: If you have resharper installed, the default tab/tab keyboard shortcut might not be enabled.

Any feedback is greatly welcomed.

Enjoy.

submit to reddit