Changing the product key in Windows Server 2012

We have starting provisioning Windows Server 2012 boxes for us to use internally and for our clients. One of the things that stumped me very early on was that the “Change your product Key” link was missing from the product activation page. I’m not sure why they removed it, but to change the product key now, you can open a powershell prompt and type

slmgr -ipk XXXX-XXXX-XXXX-XXXX-XXXXX

Adding a lookup field to an existing table using Entity Framework code first migrations

As you build out a site using the code first approach, at some point you will most likely need to add an additional lookup field to a class. There are a couple of steps required above what’s automatically done for you by EF code first migrations to make things work happily.

If you consider the following simple class

class Client
    {
        public int ID { get; set; }
        public string ClientName { get; set; }
        public string ClientAddress { get; set; }
    }

If you add a migration at this point you’ll end up with something like

public partial class InitialSetup : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "Clients",
                c => new
                    {
                        ID = c.Int(nullable: false, identity: true),
                        ClientName = c.String(),
                        ClientAddress = c.String(),
                    })
                .PrimaryKey(t => t.ID);

        }

        public override void Down()
        {
            DropTable("Clients");
        }
    }

Once this class has been added to the database and you have existing data, adding another non nullable lookup field can be tricky. When you add your lookup and it tries to add the lookupID field to the existing Clients table, it’ll fail because the existing data will fail referential integrity due to their being no data in the lookup table.

Once we added a lookup named ClientStatus to the model, it would look like

class Client
    {
        public int ID { get; set; }
        public string ClientName { get; set; }
        public string ClientAddress { get; set; }
        public int ClientStatusID { get; set; }

        public virtual ClientStatus ClientStatus { get; set; }
    }

    class ClientStatus
    {
        public int ClientStatusID { get; set; }
        public int ClientStatusText { get; set; }
    }

and our migration code will look like

public override void Up()
        {
            CreateTable(
                "ClientStatus",
                c => new
                    {
                        ClientStatusID = c.Int(nullable: false, identity: true),
                        ClientStatusText = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.ClientStatusID);

            AddColumn("Clients", "ClientStatusID", c => c.Int(nullable: false));
            AddForeignKey("Clients", "ClientStatusID", "ClientStatus", "ClientStatusID", cascadeDelete: true);
            CreateIndex("Clients", "ClientStatusID");
        }

        public override void Down()
        {
            DropIndex("Clients", new[] { "ClientStatusID" });
            DropForeignKey("Clients", "ClientStatusID", "ClientStatus");
            DropColumn("Clients", "ClientStatusID");
            DropTable("ClientStatus");
        }

The problem lies between the CreateTable and the AddColumn commands. The lookup table will be created, but the ClientStatusID non nullable field can’t be added to the Clients table as there are no records on the ClientStatus table.

To get around this in my code, I am tweaking the Up function to insert a default row into the lookup table and assigning the value of 1 to the default value of the ClientStatusID field in the Clients table.

I’m adding

Sql("INSERT INTO ClientStatus (ClientStatusName) VALUES ('Active')");

and updating

AddColumn("Clients", "ClientStatusID", c => c.Int(nullable: false));

to be

AddColumn("Clients", "ClientStatusID", c => c.Int(nullable: false, defaultValue:1));

As we are just creating the ClientStatus Table, we can reasonably assume that the first record created will have an CLientStatusID of 1.

Telerik CSS issues with Windows Azure

There appears to be an issue with the Windows Azure system where the AssemblyResourceLocator does not work correctly when the compiled assemblies of a site is uploaded to Azure from a timezone ahead of the Azure servers timezones. You can read about this issue at http://social.msdn.microsoft.com/Forums/en/windowsazure/thread/751e27a9-4108-4446-9870-411f409d2c08?prof=required&lc=1033

This issue presented itself in my application by failing to load any CSS for any of the Telerik controls I was using. Telerik loads it’s CSS using WebResource.axd. As I’m in Australia and the servers I uploading to are behind the Australian timezones, the call to the WebResource.axd would return a 404 error. Once the time on the server caught up to the compile time of my site assembly files, the CSS would start displaying.

I found 2 workarounds before finding a permanent solution.

Workaround 1: Change my PC’s timezone to Samoa (this first timezone in the list) and deploying my application. Obviously not ideal.

Workaround 2: Deploy the site to Staging and wait until several hours past and the site started working, then Swap VIP to Production. Also no ideal.

The Solution

The solution I found to resolve the issue involved using the touch.exe app found at http://www.touchdotexe.com/ to touch the assembly dll file to update it to the current time on the server after the app had been deployed.

To do this I added the touch.exe file and a setup.cmd file to the root of my app, set the build action on the 2 files to Content and the Copy to Output Directory to Copy always.

image

image

I then added a startup task to the Azure Project’s ServiceDefinition.csdef file to execute the setup.cmd file at role startup.

<Startup priority="1">
      <Task commandLine="setup.cmd" executionContext="elevated" taskType="simple" />
    </Startup>

The setup.cmd file just has one line of code

touch.exe mywebapp.dll

As both of these files are copied to the bin folder, there’s no need to specify a full path the assembly file.