Home

rss

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.

Textboxes Timers and Updatepanels

In a project I'm working on, I had to create a Facebook style notification system. I wanted the user to be able to enter a status and click the add button and have the list of notifications below it update with their most recent post. That is simple enough to do, all I had to do was to add the notification, clear the textbox then call the updateNotifications function in my button_click code behind method. This all had to be very smooth to the eye so i added the usual updatepanel around the textbox, button and div that listed the notifications.

As well as that, I also wanted the notifications system to automatically update with other users notifications within the same group. So I added a Time control to the mix and set it to refresh the notifications list every 10 seconds.

This seemed to work well until I was half way through typing a new notification when the timer triggered and refreshed the notification list. As the textbox was inside the updatepanel it stopped letting me type any text while it refreshed.

So then I thought that I’d move the textbox outside the updatepanel so it wasn’t impacted when the timer refreshed the list.

The only problem now is that because the submit button to add a new notification was inside the updatepanel and the textbox was outside the updatepanel the textbox could no longer be cleared on the partial postback. My txtNotification.Text = String.Empty; was being ignored.

I can’t quite remember the next thing I tried but it obviously didn’t work because now the whole page was refreshing everytime the timer triggered.

In the end I remembered about the UpdateMode property on the update panel. I set the updatemode to conditional around my textbox/button updatepanel and always on the notification list/timer updatepanel. That way the timer triggers updated the notification list without upsetting the textbox and submitting the add button updated the list and cleared the textbox. Perfect result.

ASPX code:

<asp:UpdatePanel ID="updStatusUpdate" runat="server" UpdateMode="Conditional">
    <ContentTemplate>        
        <asp:TextBox ID="txtStatusUpdate" runat="server" TextMode="MultiLine" Rows="2" Width="570">asp:TextBox> <br />        

        <asp:Button ID="btnAddStatusUpdate" runat="server" Text="Update Status" 
            onclick="btnAddStatusUpdate_Click" class="ui-state-default ui-corner-all"/>

    ContentTemplate>
asp:UpdatePanel> 

<asp:UpdatePanel ID="updNotifications" runat="server" UpdateMode="Always">
    <ContentTemplate>        
        <div class="NotificationList">
            <asp:Literal ID="litNotifications" runat="server">asp:Literal>
        div>
        <asp:Timer ID="Timer1" runat="server" ontick="Timer1_Tick" Interval="10000">asp:Timer>
    ContentTemplate>
asp:UpdatePanel>    

A function to convert a TimeSpan to an x minutes ago string

An application I’m working on requires a facebook style status system and I thought it would be good to include the “posted x minutes ago” text after the status.

I’m sure my code is not the most elegant solution but it works so I thought I’d share.

public static String LastUpdatedText(DateTime DateNow, DateTime LastUpdated)
        {
            TimeSpan timeDiff = DateNow.Subtract(LastUpdated);

            if (timeDiff.TotalHours < 1)
            {
                return Math.Round(timeDiff.TotalMinutes,0) + " minutes ago";
            }

            if (timeDiff.TotalHours < 24)
            {
                return Math.Round(timeDiff.TotalHours, 0) + " hours ago";
            }

            if (timeDiff.TotalHours < 48)
            {
                return "yesterday";
            }

            if (timeDiff.TotalHours < 168)
            {
                return Math.Round(timeDiff.TotalDays,0) + " days ago";
            }

            if (timeDiff.TotalDays < 42)
            {
                return Math.Round((timeDiff.TotalDays / 7),0) + " weeks ago";
            }

            if (timeDiff.TotalDays < 365)
            {
                return Math.Round((timeDiff.TotalDays / 30),0) + " months ago";
            }

            return Math.Round((timeDiff.TotalDays / 365),0) + " years ago";
        }