ipona

What in heavens name am I doing?

April 27, 2012
0 comments

NewtonSoft Json Deserialization and inner objects

My current project uses SignalR for its network comms, which uses Newtonsoft.Json as its serialiser. After a bit of refactoring, in which everything seemed to work, I suddenly realised I had a couple of failing tests. That’s right kids, testing actually works. The problem was that the refactor changed a type from a simple string to a complex object. Well, a simple object, with just two properties. Here’s what I have:

public class TopSecretHardware
{
    public int ID { get; set; }
    public string Name { get; set; }
    public IPAddressAndPort IPAddress { get; set; }
}

The IPAddress property was previously a string, but now needed to encapsulate the IP address and the port number. Given that this is used elsewhere in the project, I created a separate class to encapsulate the functionality (parsing, validation, etc):

public class IPAddressAndPort
{
    public string Address { get; private set; }
    public int Port { get; private set; }

    public IPAddressAndPort(string address)
    {
        string[] IPParts = address.Split(new char[] { ':' });
        if (IPParts.Length > 1)
        {
            Address = IPParts[0];
            Port = int.Parse(IPParts[1]);
        }
    }

    public override string ToString()
    {
        return string.Format("{0}:{1}", Address, Port);
    }
}

There’s a little more to the validation, but I’ve removed it for brevity.

This all seemed fine until my tests pointed out that the IP address and port weren’t persisting through my application. A simple Console project confirmed that:

var hardware = new TopSecretHardware()
{
    ID = 1,
    Name = "box 1",
    IPAddress = new IPAddressAndPort("192.168.1.71:123")
};

string json = JsonConvert.SerializeObject(hardware);

Console.WriteLine(json);

TopSecretHardware dehardware = JsonConvert.DeserializeObject<TopSecretHardware>(json);

Console.WriteLine("{0} - {1} - {2}", dehardware.ID, dehardware.Name, dehardware.IPAddress);

The output wasn’t what I expected

{"ID":1,"Name":"box 1","IPAddress":{"Address":"192.168.1.71","Port":123}}
1 - box 1 - :0

The serialization seemed OK, but what was happening when the object was deserialised? A bit of digging leads to some properties you can add to your objects to help with serialization, so I decorate my properties:

[JsonProperty("Address")]
public string Address { get; private set; }
[JsonProperty("Port")]
public int Port { get; private set; }

The output of this is even weirder:

{"ID":1,"Name":"box 1","IPAddress":{"Address":"192.168.1.71","Port":123}}
1 - box 1 - :123

Again the serialisation is fine, but not the reverse. The port number comes across, but no address? Confused I put a breakpoint on the constructor and find that when deserialising, only the address is passed in, not the address and port. Aha. Here we have an object with two properties; how does the serialiser know that these should be combined in “address:port” form to pass into the constructor? It doesn’t, of course. So there are two solutions:

  1. Add a default constructor. The serialiser will use that to construct the object, then fill in the properties based upon the JsonProperty attribute.
  2. Don’t use the JsonProperty attributes and create a constructor with a signature that matches the number and type of arguments that are serialised, then decorate it with the JsonConstructor attribute. That way the serialiser knows which constructor to use.

So my class is now:

public class IPAddressAndPort
{
    public string Address { get; private set; }
    public int Port { get; private set; }

    public IPAddressAndPort(string address)
    {
        string[] IPParts = address.Split(new char[] { ':' });
        if (IPParts.Length > 1)
        {
            Address = IPParts[0];
            Port = int.Parse(IPParts[1]);
        }
    }

    [JsonConstructor()]
    public IPAddressAndPort(string address, int port)
    {
        Address = address;
        Port = port;
    }

    public override string ToString()
    {
        return string.Format("{0}:{1}", Address, Port);
    }
}

And everything works fine. The lesson here is that when using external libraries you have to learn about them, even if they often just work out of the box. In all this took an hour or two to dig into and solve, but I’m now much more aware of the problems that can arise and that can only be a good thing.

April 25, 2012
0 comments

TreeView as Menu and highlight

In a follow up to my tab-style menus post along comes a similar query about highlighting the parent path when using a TreeView control as your menu. The TreeView has a similar event to the Menu allowing you to check each node as it’s bound with data. So with a UI like:

<asp:SiteMapDataSource ID="menuData" runat="server" />
<asp:TreeView ID="tv1" runat="server"
    DataSourceID="menuData"
    ontreenodedatabound="tv1_TreeNodeDataBound" />

You can have the following event code:

protected void tv1_TreeNodeDataBound(object sender, TreeNodeEventArgs e)
{
    SiteMapNode node = e.Node.DataItem as SiteMapNode;

    if (SiteMap.CurrentNode.IsDescendantOf(node))
    {
        e.Node.Text = String.Format("<span class='parentselected'>{0}</span>", e.Node.Text);
    }

    if (node.Url == SiteMap.CurrentNode.Url)
    {
        e.Node.Text = String.Format("<span class='selected'>{0}</span>", e.Node.Text);
    }
}

Add in the appropriate styles and now not only is the current item highlighted, but the path back to the parent is highlighted too.

April 24, 2012
0 comments

Online storage–do as I say

I’m all for online storage; you can never have too many backups. Frankly if you’re not using some form of online backup you’re bordering on madness; you can get enough free storage to cover most data scenarios (movies aside), so not taking up the option seems plain stupid to me. I’ve been using Microsoft mesh (now LiveSync) since it’s first betas and it’s been excellent; just select a folder and add it to your Mesh, and you can sync it to the cloud and selected other machines. It’s a simple sync between me, the cloud and my laptop. I also have a paid Mozy account because, well, discs are evil and crash when you most need them.

 

I’ve also got a DropBox account, which I setup because a client was using it and it just made things easy to share files. But I hate the central folder – the one true place – that their methodology forces you to adopt. “Here”, they say, “have some free storage, we’ll synchronise it automatically for you. You want multiple folders? No, sorry, we only support a single folder. Move all of your folders into that one. It’s free, what more do you want?” Yeah, right, that’s what I want, to be forced to organise my files under your folder. I suck it up because that’s what the client used, and it’s a great price, but I have my own structure – clients, projects, etc – so now I copy between them, my local folder structure and DropBox, which kinda ruins the seamless experience.

 

Now Microsoft release a SkyDrive application, which synchronises with free 25gb of storage online. Ooh, nice; I already use SkyDrive too, so that’ll fit nicely, thinks I. But no, it’s the same as the DropBox model, a single folder and one that’s not even integrated with LiveSync. Really, I just don’t get it. You’ve this sweet sync technology that allows you to select folders to synchronise and to which machines and you force me to use a single folder. I’ve already got a folder structure, neatly set out in my anal OCD way, but no, that’s not good enough, I now have to have everything I want synchronised under a single folder. Really? A single folder? You didn’t think that, maybe, I’d have files and folders scattered around my disc? You didn’t think that a good way to differentiate yourself is to do something different rather than copy the competition? You’ve already got a multi-folder sync technology, one that’s been working happily for years, but no, let’s not use that, let’s pick the restrictive way of doing things.

 

And while I’m ranting, why can’t LiveSync and SkyDrive be combined? I get that SkyDrive is the consumer friendly model, but it seems odd, wasteful even, that you have two technologies providing almost the same features, but not the same enough to combine them. There seems to be a lack of vision here, the view that since people already accept the single folder view, that’s good enough for everyone.

April 20, 2012
0 comments

Overriding the universal selector

Here’s a weird issue that came up in a forum post, which left me scratching my head. The poster was using themes and had a CSS file in the theme folder, one rule of which was overriding some defaults set in the universal selector defined in another CSS file. The hierarchy seemed fine; the theme CSS file was loaded after the main one, but something was amiss.

 

One of the properties being overridden was the colour of a grid view header; other properties were set fine, but the colour for the header wasn’t set. Firebug showed the hierarchy was correct too; the colour was set – it even had !important – but it just wasn’t taking effect. This stumped me and a quick search came up with a SO post that had a working solution, which is to add the universal selector to the overriding rule. So instead of:

 

.table_title {

 

You have:

 

.table_title * {

 

The style now takes effect. Weird, huh?

 

So the real question is why doesn’t the overriding take place in the first instance? The answer is that the universal selector bypasses the inheritance chain, so nothing overrides it, unless you actually override the universal selector again. Eric has a full description of the universal selector and a read through shows you how confusing it can be. It’s powerful, but does lead you to situations like this where the expected rules don’t work.

April 18, 2012
0 comments

CSS adapters appear to stop working

This just hit me, remoting in to a client who was remoting in to an end user, setting up a web application I wrote. It’s an ASP.NET 2.0 application and uses the CSS Friendly Adapters to produce cleaner HTML, but it appeared those adapters weren’t working, first noticed by the menu not rendering. Or rather it was rendering, but the CSS wasn’t being applied so you couldn’t see it. Inspecting the page load showed the CSS files were being loaded, but somehow not being applied. A quick search came up with a solution, which is to remove the compiled browser capabilities file and everything appears correctly.

April 18, 2012
1 Comment

ASP.NET Tab-Style Menus with parent highlight

A long time ago I posted about tab-style menus, and one thing that I didn’t talk about, but that is a common request, is how does the parent menu remain highlighted when a child menu is selected. Since these are two separate menus, there’s no real connection, so you have to drop to a bit of code. The secret is to hook into the MenuItemDataBound event of the parent menu, with code like this:

 

protected void topMenu_MenuItemDataBound(object sender, MenuEventArgs e)
{
    SiteMapNode node = e.Item.DataItem as SiteMapNode;

    if (SiteMap.CurrentNode.IsDescendantOf(node))
    {
        e.Item.Text = String.Format("<span class='staticSelectedStyle'>{0}</span>", e.Item.Text);
    }
}

 

This simply checks if the current node (ie, the current page) is a descendent of the node being rendered (the parent node). Unfortunately the MenuItem doesn’t expose the attributes, so you can’t directly modify the style or class, so the rather hacky trick is to add an additional element with the appropriate class set. Doing so might mean you have to change some of the CSS, to ensure that the anchor is full width. I changed the the bottom border of the staticMenuItemStyle and changed staticSelectedStyle to display as a block element.

April 10, 2012
0 comments

The time has come, the Walrus said …

… to redo my site and move my blog. Or something like that.

I’ve taken the decision to switch both my site and the old blog to a single platform, so have been looking at the CMS ecosystem. I tried WordPress, probably the most popular CMS, and while it’s simple, has loads of plugins, it just never felt easy to setup and configure on Windows, despite the Web Platform Installer. There were always additional Windows permissions to set, and then errors which made no sense. The next look was Orchard, which was certainly easier to install, but did give me grief in a number of areas and some things just didn’t work as I expected. I hit one show-stopping bug that took the entire site down (hint: don’t disable the Feeds module) and had to dig around for a long time to work out how to get the site back. As part of that digging I downloaded the source and wow, confusing. It’s clearly very flexible, but to my simple desires appears massively over-engineered. Maybe it needs that to get flexibility, but it just feels more complex. But, I stuck with it for a while and even switched my site over to it, then decided to switch back to WordPress because it’s much simpler and just feels easier to work with. I may play with themes over the next few weeks – I’ve already tweaked this one a little – but essentially I think I’m going to stick with it.

October 24, 2011
0 comments

GiveCamp UK 2011

This weekend was GiveCamp, a global weekend of charitable software development, organised in the UK by Rachel Hawley and Paul Stack. No one really knew what to expect, least of all Rachel and Paul, who’ve put in a monumental amount of effort of the last few weeks to pull this event off. It’s a simple concept; talk to some charities to find out what software they need, get a bunch of geeks together and code for 48 hours solid to produce that software. Easy in concept, right?

It all started rather chaotically; Andy & I turned up early at UCL to help Paul, but he was caught up in traffic after having to go collect the T-shirts after a delivery screw up. We managed to get a name for our local contact at UCL, who knew as much as us – almost nothing; she knew where we’d be and what time we were allowed into set rooms, but beyond that most of the information was stuck in Paul’s head. But things did start happening over the afternoon; people drifted in, the tea arrived and a fridge for the drinks. Then Paul arrived with a car full of soft drinks, and disappeared again for another cash and carry run and we had enough drinks for most of UCL. In the end we had stacks left over, much of which went to a local homeless shelter; yet more giving.

The room gradually began to fill, and then everyone decamped to the lecture theatre for the opening, then came back and coalesced into working groups for the projects. It was interesting to see how well this worked – order from chaos – with people spreading fairly evenly between the projects; 115 people, 9 projects. Herding cats has always been a phrase associated with getting developers organised, but this self-assembling worked and within an hour the project teams were formed; the team leads had been set before hand and knew a bit about their projects, but it was only during Friday night that everyone really found out the requirements. And this is the hardest thing, working with the charity representatives and setting only those requirements that could be achieved in 48 hours.

I was originally a roving agent, free to help out on anything, but was royally stitched up by Phil who introduced me the Latin American Women’s Aid team, whose project was going to be Microsoft Access based, trying to replicate their entirely manual process of filling in complex paper forms. And not only was it Access based, but the backend database was going to be MySQL, to ensure the data was safe in their one Linux server. My history of Access development had re-surfaced, like an ex-lover who you look on fondly, but then realise why you left them. Still, good cause so dig in I did. The technology choices proved to be a major hurdle in a project like this; Access is good at many things, but multi-user development isn’t one of them. To solved this, PDD was used – Plate Based Development – (s)he who holds the plate has control of the master database. It was particularly difficult going back to a product I hadn’t used in 10 years. It was frustrating trying to bend Access to do things it just isn’t really designed for. At 12am I gave in and headed back to the hotel – I’m too old to be kipping on floors – but despite the tiredness I couldn’t sleep, so got the laptop out and carried on, then realised how much I’d forgotten.

Back at the venue at 8am a few hardy soles were still coding, but sausage and bacon butties along with tea and coffee fuelled an influx of devs back to work and coding continued. We continued to fight Access and MySQL; we laughed, banged our heads in frustration and carried on. I even ended up remoting into my home server and downloading the original chapters from my old Access book so I could read up on how to do things, that’s how desperate it got. I made it until 1am.

Sunday started much as Saturday had; tiredness and an overwhelming feeling of despair that we wouldn’t get our project finished. The challenges were just too much, but we carried on so that at least we’d have a start of something and LAWA would have a way forward. We didn’t finish and didn’t deliver; the only team to do so; it hurt. Code freeze was at mid-day and we were nowhere near.

After a great hog roast in the sunlit quad, we had the wrap-up presentations where the teams showed their projects; some had yet to show what they’d done to their charity representatives, so it was nervous time for both sides. I sat and watched these with awe – really, it was awesome – seeing how much had been achieved within so little time. One charity representative started crying; they have three people and the web application they were presented with will save them a day per week of time. A day per week. Think about how much time that is and how important it is for a small charity. All the other projects were equally impressive – one was even already live – and one is a starting point for an open source CRM designed for charities; they delivered the first part and there’s a plan for future features. Go contribute.

So what have we learned over this weekend, the first GiveCamp in the UK.

  • There are a large number of people willing to give their time and effort into helping others.
  • It’s amazing what can be achieved in a short amount of time. None of these projects had much planning, features were defined quickly and coding started. No fuss, no arguments – well, none that really mattered – we just got on with it.
  • Charities have little in the way of resources; money, hardware, skills. Every little bit we do can have a big impact.

Would I do it again? Hell, yes. It was tiring, hugely frustrating, but exhilarating and fun. And it’s going to change lives. I think Paul and Rachel deserve a huge amount of thanks (Rachel will probably settle for Haribo) for pulling this off; no one knew how it was going to work, or indeed, if it would work at all, but work it did and very successfully so. Well done all.

My photos for the day are on Flickr.

October 21, 2011
0 comments

Xunit and Moles

This is more a reminder to myself, but I hope it’s useful to others. If you’re using xunit for unit testing and Moles for isolation/mocking then you may run into a problem using the moles test runner, whereby you receive an error stating “error: missing filename”.

For example, consider the following in the build file:

moles.runner /x86
  /runner:"d:\tools\xunit\xunit.console.clr4.x86.exe"
  "d:\project\foo.dll"
  /args:"xml d:\project\foo.xml"

While a similar command works at the command line, in the runner it fails. The answer, as supplied by Heather, is to supply the arguments separately:

moles.runner /x86
  /runner:"d:\tools\xunit\xunit.console.clr4.x86.exe"
  "d:\project\foo.dll"
  /args:"xml" /args:"d:\project\foo.xml"

September 29, 2011
0 comments

Simple.Data is Simple; type conversion isn’t

I’ve recently started using Mark Rendle’s rather lovely data framework Simple.Data. There’s a really big clue in the name; it’s very simple to use. Eg:

var db = Database.OpenConnection(ConnectionString);
db.Zones.FindByZoneID(ZoneID);

That’s it; everything is dynamic and database columns are mapped to properties automatically. Searching by columns is easy as FindBy can be followed by any column (or multiple columns, just put And between them) or using lambdas. Dead easy.

The one downside Simple.Data has is a lack of a way to define how the types are mapped; there is plenty of built-in intelligence, but what, for example, if you need a char column mapped to a byte array? As yet, Simple.Data doesn’t have a way of doing this (char columns are mapped to strings), although there’s an issue raised suggesting a way it could be done. For the moment though it can’t be done within Simple.Data.

If you’re in this situation with POCOs that have types different from the underlying data store (or more accurately, different from the standard type conversion), then you could pick the solution I’ve chosen to get me over this, which is to create two POCOs: one with the Simple.Data types and one with the custom types. I then use AutoMapper to map from one type to another, using a custom type converter to convert the appropriate columns. It’s a bit more work, but is fairly simple to achieve; first set up the mappings:

Mapper.CreateMap<string, byte[]>().ConvertUsing<StringToByteArrayTypeConverter>();
Mapper.CreateMap<byte[], string>().ConvertUsing<ByteArrayToStringTypeConverter>();
Mapper.CreateMap<PanelSD, Panel>();
Mapper.CreateMap<Panel, PanelSD>();

The type converters are simple, as AutoMapper provides an interface to implement:

public class StringToByteArrayTypeConverter : ITypeConverter<string, byte[]>
{
     public byte[] Convert(ResolutionContext context)
     {
         return Encoding.ASCII.GetBytes((string)context.SourceValue);
     }
}

public class ByteArrayToStringTypeConverter : ITypeConverter<byte[], string>
{
     public string Convert(ResolutionContext context)
     {
         return Encoding.ASCII.GetString((byte[])context.SourceValue);
     }
}

And yes, I’m aware I’m using ASCII encoding here; in my case I know my data is ASCII; your mileage may vary.

Then fetch the data and map it:

List<PanelSD> panelssd = Database.Default.Panels.All().ToList<PanelSD>();
<Panel> panels = Mapper.Map<List<PanelSD>, List<Panel>>(panelssd);

I’ll obviously map the other way around when writing to the database. In my case both the read write can easily be abstracted and there’s actually only one object where I need the mapping, so it’s of minimal impact.