Monthly Archives: February 2015

The Beauty of Anonymity

No, not the kind commonly found on the Internet, which is often anything but. Rather, C#’s Anonymous types, introduced way back in 2007 with C# 3.0 and more often than not ignored by me until now.

I used to avoid JSON. Its syntax seemed just like every other delimited format I’d ever seen. In short, a headache to parse. XML is more verbose. Yet (at least for me) more humanly readable. That was until I found two things:

  1. XML parsing across different browsers is an even bigger headache
  2. With JSON I can create almost identical classes on both a C# server and a Javascript client

Later, the relationship was strengthened by the discovery of services like http://json2csharp.com/, which will create a C# class for you out of a JSON sample, as will more recent versions of Visual Studio. That’s great for dealing with someone else’s API output.

But sometimes a class seems like overkill. What if you have just one place where you really, really need to send just a bit of JSON to the client? For example, in one of my SignalR hubs, I need to send three things:

  1. brief message
  2. start time
  3. end time

SignalR, by the way, always sends JSON so all you need is some way to package (enclassulate?)  your data. Enter the Anonymous type, which if you use Linq you’ve probably already seen many times, e.g:

var productQuery =
    from prod in products
    select new { prod.Color, prod.Price };

foreach (var v in productQuery)
{
    Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}

With a var, the usage is basic: “var foo = new { someData = “something” };” Anonymous types support nesting too, so I was able to tidily separate my message data from my duration data. Here’s a sample method in the SignalR hub on the server:

public void AnonTypeDemo(string groupID)
{
    var startTime = DateTime.UtcNow;

    var endTime = startTime + TimeSpan.FromMinutes(10);

    // the anonymous type
    var data = new { message = "started", duration = new { startTime, endTime } };

    Clients.Group(groupID).anonTypeDemo(data);
}

The method sends a JSON string that looks like this:

{
    "message": "started",
    "duration": {
        "startTime": "2015-02-24T18:19:48.8008904Z",
        "endTime": "2015-02-24T18:29:48.8008904Z"
    }
}

On the client side, a Javascript method will be called by the SignalR client to process the received data:


myHub.client.anonTypeDemo = function (data) {

    console.log(data);

    var message = data.message;

    var startTime = data.duration.startTime;
    var endTime = data.duration.endTime;
}

And that’s all he wrote.

Ah, the Suspense

Unless you’re going for pinpoint animation timings it’s really pretty straightforward to create timers on a web page…or so I thought. I threw one together – a simple countdown timer that would get passed a duration, a DIV in which to display the time, a formatter function to make the time pretty, and a callback. It worked well. That is, until I tried it on my Windows Phone and happened to exit the browser while the timer was running.

I came back to the test page and the timer picked up where it left off. In some situations, this would be fine. But in my use the timer is meant to be triggered (more or less) at the same time for a group of users (via SignalR). It would be bad if one user got a text message during a 5-minute session, suspended the browser temporarily to check it, and then got an additional 30 seconds or whatever to keep on entering items after the session ended.

Was this just a Windows Phone issue? Nope. I tried it on an iPhone 5S and had the same issue. It makes sense. Phones need to conserve power whenever possible so suspending running code in a browser tab when it’s invisible is logical. I fixed this issue by setting an initiated time, using Math.round(new Date().getTime() / 1000. Each time the timer interval is called (once per second) the current time is gotten (also in seconds) and then the difference is compared to the elapsed time. And, if necessary, the timer’s remaining time is adjusted (by subtracting the suspended time span from the overall duration).

I ran into another minor issue: Hitting the test button that triggered the timer again would result in multiple intervals running. I needed to clear the current interval first. In this case, I decided to store the current interval ID in the display element, using the jQuery data function. After all, it’s the element being affected by the code.

This is the sort of thing that might be papered over easily by manipulating the UI so the triggering mechanism, e.g. a button, can’t be used more than once. But baking this little fail-safe right into the code heads off any unanticipated uses down the road. For example, perhaps the timer might be reset every time a user guesses the correct answer in a game and moves on to another question.

Here’s the complete code for the timer:

See the Pen zxWwOM by Jon Nehring (@stonetip) on CodePen.