Friday 18 May 2018

Getting Docker for Windows running on a Lenovo laptop

Today I installed Docker For Windows on my Lenovo ThinkPad (running Windows 10 Enterprise). Something that should have been pretty straight forward turned out to require a little bit of extra effort. Here are the steps that I took to get things working. The commands below assume that when you have installed Docker For Windows CE you receive a message prompting you that Hyper V is required and that you should restart your machine to enable Hyper V.

 1. Restart the laptop and press F1 to boot into the BIOS
2. Under Security > Virtualization > Mark both options as Enabled (Then Save and Exit)
3. When the machine has booted back into Windows open the command prompt in Administrator mode (windows key, then type cmd, right click on "Command Prompt" and select Run as Administrator
4. Run the following command: SC config trustedinstaller start=auto
5. Restart the laptop ... again
6. Open Powershell as and admin and run:
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All

 That should do it.

Friday 17 July 2015

Entity Framework 6 - mapping keys of different types

I came across an interesting problem the other day.  I was creating and entity model over an existing database.  In the database the Primary Key on one table in the relationship is a Decimal and the related Foreign Key is an Int with no enforced referential integrity on the database.

My first attempt at mapping my entities to the database was not successful and I ended up with the following Exception : "The specified cast from a materialized 'System.Decimal' type to the 'System.Int32' type is not valid."


Here is what my original entities and mapping files looked like:
public class JobMap : EntityTypeCategoryuration
{
    public JobMap()
    {
        // Primary Key
        this.HasKey(p => p.JobId);

        // Properties

        // table and column mappings
        this.ToTable("job");
        this.Property(p => p.JobId).HasColumnName("job_id");
        this.Property(p => p.JobCategoryId).HasColumnName("job_category_id");
        this.Property(p => p.JobCode).HasColumnName("job_code");


        this.HasRequired(t => t.JobCategory) 
            .WithMany(t => t.Jobs)
            .HasForeignKey(d => new { d.JobCategoryId }); 
    }
}

public class Job
{
    public decimal JobId { get; set; }
    public int JobCategoryId { get; set; }
    public string JobCode { get; set; }
}

public class JobCategoryMap : EntityTypeCategoryuration
{
 public JobCategoryMap()
 {
  // Primary Key
  this.HasKey(s => s.JobCategoryId);

  // Properties
  // Table and Column mappings
  this.ToTable("job_category");

  this.Property(p => p.JobCategoryId).HasColumnName("job_category_id");
  this.Property(p => p.Name).HasColumnName("name");
  this.HasOptional(p => p.Jobs).WithRequired()
                    .Map(x => x.MapKey("job_category_id"));
 }
}

public class JobCategory
{
    public int JobCategoryId { get; set; }
    public int Name { get; set; }
    public virtual ICollection Jobs { get; set; }
}


It took a fair bit of bashing of the head to figure out how to get things to work, but in the end the solution turned out to be very simple. A small change to one of the mapping classes.

public class JobCategoryMap : EntityTypeCategoryuration
{
 public JobCategoryMap()
 {
  // Primary Key
  this.HasKey(s => s.JobCategoryId);

  // Properties
  // Table and Column mappings
  this.ToTable("job_category");

  this.Property(p => p.JobCategoryId).HasColumnName("job_category_id")
                    .HasColumnType("decimal");
  this.Property(p => p.Name).HasColumnName("name");
  this.HasOptional(p => p.Jobs).WithRequired()
                    .Map(x => x.MapKey("job_category_id"));
 }
}


Notice the addition of the
.HasColumnType("decimal")
. It took me a while to figure this out so I thought I'd blog about it in the off chance someone else is looking to solve the same problem.

Tuesday 28 April 2015

Create a Visual Studio 2013 solution from Windows Explorer's New Context Menu

I have always found the workflow for creating a new Visual Studio solution from within Visual Studio to be somewhat inefficient.  I never seem to get the project and solution in the folders I want them in and just about always end up closing Visual Studio after creating a new solution just so I can move the solution file to where I wanted it in the first place.

For me a much better workflow is to navigate to the location where I want to create my solution in Windows Explorer and then to right-click and from the New Context menu select "Microsoft Visual Studio Solution".

The problem is that this functionality isn't available out of the box.

Good news is that it's not too tricky to set up.  Here are the steps to add the ability to create a Visual Studio solution to your New Context menu.


  • In Visual Studio, create a new Visual Studio Solution and name it VisualStudioTemplate.sln
  • Close Visual Studio and then copy the VisualStudioTemplate.sln to c:\Windows\ShellNew
  • Open RegEdit and navigate to HKEY_CLASSES_ROOT\.sln\
  • Create a new Key called ShellNew
  • Click in the right hand pane and create a new string value and enter "FileName"
  • Right click on the newly created "FileName" string value and select Modify...
  • Enter VisualStudioTemplate.sln into the Value data field and hit enter
  • Close regedit

That's it you should now be able to create a new Visual Studio solution from the Windows Explorer New Context menu.



Tuesday 25 November 2014

Multi-Device Hybrid Applications - Upgrading to CTP3

To upgrade to CTP 3 you need to first uninstall CTP 2.

To uninstall:

Step 1
  • Open Visual Studio 2013
  • Select Tools > Extensions and Updates,  "Multi-Device Hybrid Apps for Visual Studio"
  • Click Uninstall
Step 2
  • Open Programs and Features
  • Search for "Multi Device...
  • Right Click Uninstall
Step 3

Follow the steps in this Microsoft KB.

Finally CTP 2 is gone...

You should now be able to install CTP 3.

Just a note about the uninstall process.  On my work machine I uninstalled from within Visual Studio 2013 only and then upgraded to Visual Studio 2013 update 4.  I then tried to install CTP 3 and was prompted to remove CTP 2.  I tried to remove CTP 2 via Programs and Features and then had to follow the steps in the KB.  On my home machine, I followed Steps 1 and 2 above and CTP 2 uninstalled properly the first time.

Wednesday 12 November 2014

Multi-Device Hybrid Applications - Side load your application

I have reach the point in my current project where I needed to get my application up and running on a device for testing.  There are a number of articles out there on how to side load a Windows Store application, but I didn't find any that specifically dealt with multi-device hybrid applications.

The first device I managed to get my hands on for testing purposes is the Windows Surface RT running Windows 8.1 so the steps for side loading in this post are what worked for me on the RT, but should be the same for any other Windows 8.1 tablet.

The steps for side loading are as follows (assuming your multi-device project name is myProj):

Create the deployment package
  • Build your solution
  • Navigate to MyProj/bld/Debug/platforms/windows8/
  • Copy the AppPackages folder to your memory stick
  • Copy the AppPackages folder to your device
THE SHORT
  • In Window Explorer: Navigate to AppPackages\CordovaApp_1.0.0.0_AnyCPU_Debug_Test
  • Press on the Add-AppxDevPackage.ps1 and release. A context menu should appear.
  • Tap the "Run with Powershell" menu item
  • A powershell window should open
  • Type:Add-AppxDevPackage.ps1
  • Hit Enter and your application should install
If for whatever reason this is not the case continue reading.

THE LONG

Install the certificate
  • On the device navigate to the AppPackages\CordovaApp_1.0.0.0_AnyCPU_Debug_Test folder
  • Double tap on the CordovaApp_1.0.0.0_AnyCPU_Debug.cer security certificate
  • The Certificate installation dialog should appear
  • Tap on Install Certificate...
  • Under Store Location select Local Machine
  • Tap Next
  • Select place all certificates in the following store
  • Tap Browse...
  • Select Trusted People
  • Tap Ok, Tap Next, Tap Finish
  • You should get a popup with the message "The import was successful."
Run Powershell as an administrator
  • Tap the Windows key
  • From the Windows 8 start screen type: powershell
  • Press on the Windows Powershell application link that appears below the search box
  • Let go after a brief pause and a context menu should appear
  • Tap run as administrator
Ensure you have a developer license installed on the device
  • Type: Show-WindowsDeveloperLicenseRegistration
  • A window will appear and you will be prompted to enter your user name and password that is associated with your Microsoft developers license
  • Enter your user name and password
  • If you have the correct developers license you should be granted a developers license on the device.

Install the Appx package
  • In the powershell window navigate to the AppPackages\CordovaApp_1.0.0.0_AnyCPU_Debug_Test folder
  • Type: Add-AppDevPackage.ps1
  • Hit enter
  • If you receive and error about "running scripts is disabled"
  • Type: Set-ExecutionPolicy RemoteSigned
  • Type: Y
  • Hit Enter
  • Type: Add-AppDevPackage.ps1
NOTE: If you are installing your application on a device where the current user is not an administrator and after installation you can't find the application, open a new powershell session, but not as an administrator and then Type: Add-AppDevPackage.ps1

NOTE2: If you open the Add-AppDevPackage.ps1 in your favorite text editor, the comments in the file give you an idea of what

That should be it.





Tuesday 11 November 2014

Multi-Device Hybrid Applications - The certificate specified has expired exception

I ran into a rather nasty little problem when trying to build my multi-device hybrid application yesterday. Out of the blue the build started to fail with the following exception message:

Error 3 The certificate specified has expired. For more information about renewing certificates, see http://go.microsoft.com/fwlink/?LinkID=241478. [D:\dev\client\source\myApp\bld\Debug\platforms\windows8\CordovaApp.jsproj] C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\AppxPackage\Microsoft.AppXPackage.Targets 1772

I had just been trying to deploy the application to a device for the first time and thought I may have done something to mess up the certificate when I deployed to my local machine and then uninstalled the deployment. As it turns out this wasn't the case. I eventually posted a question on stackoverflow and was surprised to get a response with the answer so quickly.

Apparently, due to some coding error, the Windows Cordova platform has a temporary key that expired on 11/11/2014.  Microsoft is actively working on resolving the issue.

In the interim, the solution as explained in the answer to my question on stackoverflow is to create a new key and use this in your multi-device hybrid application.  To create a new key simply create a new Windows Store project in Visual Studio.  You will find the key in the root directory of the project. It's the file ending _TemporaryKey.pfx.  At this point the answer on stackoverflow wasn't immediately clear to me.  So just to clarify if you also found the answer a little bit confusing.  What you need to do is.


  • Rename the key from the Windows Store application (the _TemporaryKey.pfx) to Cordova_TemporaryKey.pfx.
  • In your multi-device hybrid application project navigate to the res/cert folder and add a folder windows8 (CTP1 and CTP2, see stackoverflow answer for CTP3 folder location).
  • Copy the Cordova_TemporaryKey.pfx into the res/cert/windows8 folder.
That should be all you need to do.  Now when you build you application this temporary key will be used when creating the certificate.


Monday 24 February 2014

TDD - Improving your test names

I have been doing a fair amount of TDD training recently.  The developers attending the courses are generally fairly experienced developers, but tend to have little or no experience of TDD.
A challenge with training is that you are forced to think about ideas and concepts on a whole new level as you have to relay this to your audience in a way in which they can understand.

If you are new to TDD and it seems like a pretty complicated strange world, be aware TDD does come with a fairly steep learning curve. Writing a test method with an assert is relatively straight forward. Writing a full test suit that contains a set of fast, reliable, clean, loosely coupled and readable tests is a whole lot harder. TDD is a pretty in depth subject and learning how to do it right takes a fair amount of time and practice.

One very important aspect of writing tests is test naming. Tests tend to live for the lifetime of the application and are a form of living documentation. As developers spend a far larger portion of their time reading code than actually writing code it's important that what they are reading makes sense. Tests with names that do not make sense can make a developers job a whole lot harder when they have to work with these tests later.

In this blog post I want to share my thoughts on what a good test name is and how to find these good test names. Here is a statement that summarizes my current thinking on test naming:
"A test name should show your intent, the test body should be a clear example of this intent."

One thing to note, although it's not the aim of this blog post, when naming your tests you want to find a test naming convention that you are happy with and stick with it.
I tend to use the following convention.

<SUT>_Given<Context/Scenario>_Should<Expected Outcome>

Where:
SUT - is the system under test.  This is generally any public method or property on a class that contains logic.
Context/Scenario - describes what you are trying to achieve with this test.
Expected Outcome - did you achieve the result you expected once the SUT has run.

Now that we got that out the way back to test naming. I like find to get the best names for your tests you really need to think of the names in terms of the domain that you are dealing with. The best names may not come to mind initially, but as you get to know your domain better it, will become easier to find the names. If your name isn't perfect when you initially write the test that's fine. Remember you should always be thinking about refactoring your code and this applies as much to your tests and test names at to the actual production code you are writing.

What I find tends to happen when you try to name a test around a concept you are unfamiliar with, your names tend to be very specific.

I'll demonstrate this with an example:

Let's say you are writing a method to calculate a person's age. You may start with a method like this

[Test]
public void CalculateAge_Given_DateOfBirth_20Jan2014_And_CurrentDate_20Jan2014_ShouldReturn_0()
{
  -- Arrange
  var expectedAge = 0;
  var dob = "2014-01-20";
  var currentDate = "2014-01-20";

  -- Act
  var age = CalculateAge(currentDate, dob);

  -- Assert
  Assert.AreEqual(expectedAge, age); 
  
}
The test above isn't a bad starting test. I am testing on an interesting boundary and the code shows a good example of what I am trying to do. The test name however, describes my example as opposed to describing my intent. So what is it that I am actually trying to test here. If I consider the domain can I rename this test to more accurately describe my intent? How about this:

[Test]
public void CalculateAge_GivenItsTheDayThePersonIsBorn_ShouldReturn_0()
{
  -- Arrange
  var expectedAge = 0;
  var dob = "2014-01-20";
  var currentDate = "2014-01-20";

  -- Act
  var age = CalculateAge(currentDate, dob);

  -- Assert
  Assert.AreEqual(expectedAge, age); 
  
}
I think you will agree with me that the second test name makes a whole lot more sense. The first test name is very specific to the problem, but with the second test name I have generalized just a bit. It's had a huge impact on the readability of the test and now clearly shows my intent. You could of course generalize further :

[TestCase("2014-01-20", "2014-01-20", 0)]
[TestCase("2014-01-20", "2015-01-20", 1)]
[TestCase("2014-01-20", "2015-01-19", 0)]
public void CalculateAge_Given_DateOfBirth_And_CurrentDate_ShouldReturn_Age(datetime dob, datetime currentDate, int expectedAge)
{
  -- Arrange

  -- Act
  var age = CalculateAge(currentDate, dob);

  -- Assert
  Assert.AreEqual(expectedAge, age); 
  
}

At this point we have a general purpose test that has test cases (examples) of what we are testing. Once again this test is not clearly showing your intent. You are forced to look at the examples to try to work out the intent. If you considered tests names on a continuum from very specific to very general, you want to try to find a name that hits the sweet spot. It's not so specific that you need to look at the code to work the intent and it's not so general that you are looking at the test cases to work out the intent.