JSON, .NET and NSDate

If you’re trying to access a JSON web service created using .NET from an iOS device, you’ve probably discovered that dates are produced in a less than useful format:


The rationale for the date format can be found here, but it’s basically a call to the JavaScript Date object constructor. The numeric value represents the number of milliseconds since 1970-01-01.

Below I’ve added a handy Objective-C function that will extract the value and return an NSDate object. Note that we’re losing accuracy by magnitudes as we translate from .NET DateTime objects (which measure time in ticks) to JavaScript Date objects (which measure time in milliseconds) and finally to iOS NSDate objects (which measure time in seconds).

 * Converts a .NET JSON date in the format "/Date(x)/" to an NSDate object.
 * @param string The NSString to convert.
 * @return the NSDate object.
(NSDate*)jsonStringToNSDate(NSString* string) {

    // Extract the numeric part of the date.  Dates should be in the format
    // "/Date(x)/", where x is a number.  This format is supplied automatically
    // by JSON serialisers in .NET.
    NSRange range = NSMakeRange(6, [string length] - 8);
    NSString* substring = [string substringWithRange:range];

    // Have to use a number formatter to extract the value from the string into
    // a long long as the longLongValue method of the string doesn't seem to
    // return anything useful - it is always grossly incorrect.
    NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
    NSNumber* milliseconds = [formatter numberFromString:substring];

    [formatter release];

    // NSTimeInterval is specified in seconds.  The value we get back from the
    // web service is specified in milliseconds.  Both values are since 1st Jan
    // 1970 (epoch).
    NSTimeInterval seconds = [milliseconds longLongValue] / 1000;

    return [NSDate dateWithTimeIntervalSince1970:seconds];


Enterprise iOS Apps

Recently I’ve been looking into the potential of iOS devices in the enterprise, which is surprisingly zeitgeisty. Computer users in enterprises typically have to deal with laptops that take 10 minutes to boot because they’re old, running Windows XP and laden with crufty enterprise junk. Users can’t install anything because they don’t have admin rights, and the IT department doesn’t want to spend its time uninstalling the Bing toolbar and Bonzi Buddy from the computers of techno-illiterates who, like magpies, are attracted by anything that blinks, flashes, glows or moves. They have to deal with IE6 and a virus killer that saps their CPU time and their will to live in equal measure.

A few people within enterprises have bought iPads or iPhones and suddenly find themselves with a computer that doesn’t have IE, doesn’t have viruses, allows them to install whatever they want and is always ready to use. They’ve realised that they can do most of their work with nothing more than an iPad and a Bluetooth keyboard. If only there was “an enterprise app for that” they could dump their bottom-of-the-range Dells with their oversized bag and carry around their iPads instead; hence the need for enterprise iOS applications.

The average enterprise application consists of:

  • An enormous, badly-designed database written by guys who didn’t know how to make databases but who once met the brother of a friend of an acquaintance who’d seen a SQL query a few years ago, didn’t really understand it, but thought it was pretty neat;
  • A vile, enterprisey “business logic” layer, with interfaces that describe factory classes that produce factories that produce classes that aren’t used anywhere in the codebase, because all of that clever planning and abstraction was a counterproductive waste of time;
  • A dumb web UI that allows CRUD operations on the database, cunningly designed to be 100% compatible with Internet Explorer 5 and 6 and utterly unusable in anything else, possibly even implemented as an ActiveX control masquerading as a website for marketing purposes.

Enterprise iOS apps will typically replace this last tier of the application stack. At the very least, apps need to be able to interact with the business logic layer to perform CRUD operations.

If you’ve been smart when putting together your existing systems, you’ll have followed Steve Yegge’s advice and built everything as a service. Want to know which user has the network ID “elb”? Point your web browser at your RESTful HR web service and query /employees/elb. The user’s details will be output in easy-to-parse JSON format.

In that case, you can give yourself a congratulatory pat on the back and go grab copies of ASIHTTPRequest and JSONKit. All of your systems are already set up in such a way that you can interact with them from pretty much any device that supports HTTP. It’s even easier if they can perform asynchronous requests and parse JSON.

If you haven’t built a service-oriented architecture, or were misguided enough to use WCF and SOAP - perhaps because you wanted to add a piquant dash of vendor lock-in to an architecture designed for heterogeneity - you could do far worse than take a look at Nancy. This is a micro web framework for C# based on Ruby’s Sinatra that will allow you to create RESTful web services, and indeed full websites, with astonishing ease.

The next issue you’ll have is security. What you really don’t want to do is expose your databases to the internet, particularly if those databases contain sensitive data such as employee details, client data, etc. If your iPhone needs to interact with a web service behind a firewall, what can you do?

You have 3 options:

  • Ignore the security issues and expose your web services to the internet;
  • Only allow the app to work when the iPhone is connected to the corporate network;
  • Connect the iPhone to the corporate network via a VPN.

I like to think of the first option as “the Sony approach”. If you don’t particularly value the privacy of your employees or your clients, don’t mind months of downtime when you try to shoehorn security features into a live system and aren’t embarrassed by publically demonstrating your astounding ineptness, this is a very worthwhile choice. On the other hand, you might recognise it as a security disaster waiting to happen.

The second option introduces some complexities. The whole point of a mobile app is that it’s, well, mobile. A mobile app that can only be used at a single location is obviously not amazingly useful. One possible workaround would be to cache relevant chunks of the database’s data on the iPhone. All CRUD would be performed on the cache. Any changes would get replicated to the master database when the device next connected to the corporate network. Obvious downsides are the need to deal with conflicting edits, either by automatic/manual merging or by asking the user if he wants to overwrite the remotely-edited version with his own changes.

It’s a tidy solution, but it introduces another security risk - your sensitive data is now stored on a highly desirable and easily mislaid phone. You could consider encrypting data stored on the iPhone. More extreme possibilities for securing the data include requiring a username and password to start the app (which would be a massive detriment to usability) or setting up the device in Exchange so that it can be remotely wiped if lost.

The third option is the best tradeoff between usefulness and security. VPN traffic will be encrypted, there’s no need to punch holes in the corporate firewall, and the VPN can be accessed from any location with internet connectivity. The iPhone has an excellent built-in VPN client that appears to offer identical functionality to the client in OSX. This solution obviously relies on the company having an existing VPN infrastructure or being open to the idea of implementing one.

The downside is that a lost device now has access to not only any enterprise apps but the VPN too. The risk associated with this can be mitigated by using a username/password combo to authenticate with the VPN instead of using a certificate. Certificate-based authentication happens automatically, whereas username/password-based authentication requires the user to type in his password every time he tries to connect. This might be the most appropriate approach to adopt anyway, as corporations are fond of implementing expiry policies that would necessitate the creation of new VPN certificates every few months. However, the user would need to manually sign on to the VPN each time they used the app. Worse, the iPhone has a habit of dropping VPN connections whenever it feels like it. How often do you want your users to enter their passwords?

The best approach is probably a mixture of the above:

  • Encrypt all local data
  • Set up all iOS devices in Exchange so that they can be remotely wiped
  • Allow read-only access offline by caching data on the device
  • Require a VPN connection for editing data

The VPN can authenticate via certificate for ease of use or via username/password for heightened security/to appease the password policy patrol.

Our enterprise iOS app architecture now looks like this:

  • MSSQL database used as storage
  • .NET-based business logic layer
  • RESTful Nancy web service exposing CRUD operations of business logic layer
  • VPN connection for encrypted, authenticated communication with the web service
  • iOS UI app that caches data locally for offline browsing and allows the user to interact with the web service via ASIHTTPRequest and JSONKit

Vaguely related to this, I’ve added a simple website/web service for distributing enterprise iOS apps to my BitBucket page:

It presents a list of iOS apps in an iOS-friendly website and allows them to be downloaded straight to the device. It can also be used by apps to determine the latest version number should they want to update themselves automatically.


Unicode Complete

Woopsi is now 100% unicode. Except for anything in the “bonus” folder, which I’ll get around to at some point.

I’ve tidied up the WoopsiString, removing redundant methods and sorting out which should be public and which shouldn’t. To cater for iteration, rather than trying to redesign the string, I’ve added a new StringIterator class. The WoopsiString can produce instances of these (in the same way that Gadgets produce instances of the GraphicsPort class) that can iterate over the string. It has some cunning optimisations so that it will always choose the optimal way of moving to a new character index.

On top of that, I’ve moved the FileRequester and associated classes into the main codebase. Lakedaemon pointed out that, unless you use any libfat features, it isn’t included in the final ROM. A quick test revealed that this was indeed the case, so there’s really no reason not to enable libfat in the makefile by default and include the FileRequester in the main library.

I’ve fixed a few problems in the FileRequester. Its background was transparent in places, which was caused by one of the gadgets in its children not having a draw() method. The sorting was broken - I thought I’d fixed this - so although the items were sorted alphabetically, directories were intermingled with files. Lastly, it doesn’t try to draw before the rest of Woopsi has been drawn, a problem which caused some graphical corruption.

The Bmp2Font .NET utility for converting BMP files to Woopsi fonts now creates working Font subclasses. I’ve removed four fonts from Woopsi as they didn’t seem to be converted properly by Jeff’s original process - they either had glyphs with missing sections or the vertical positioning of some of the glyphs was off.


Creating Fonts and Bitmaps

More work on fonts. Jeff’s solution for creating PackedFont fonts is fantastic - instead of mucking around with u16 arrays, he subclasses the fonts and does all of the work for you. Instead of this:

PackedFont1* myFont = new PackedFont(somearray, somewidth, someheight, blah, blah);

…you have this:

NewTopaz* myFont = new NewTopaz();

So much easier.

I’ve shamelessly stolen this idea and reworked the existing “FontBitPacker” application so that it follows this pattern. I’ve heavily modified it so that the app will convert BMP files to either MonoFont, Font, PackedFont1 or PackedFont16 font classes. As long as they have version 3.5 of the .NET framework, Windows users no longer need to faff about with PAGfx or the bmp2font Python script. The new “bmp2font” .NET console application (which the FontBitPacker has become) will do all of the font conversion work needed for Woopsi.

This pattern seemed like such a good idea I’ve used it for bitmaps, too. Instead of converting BMP files with PAGfx, then using the “all_gfx” files to include the bitmap data before wrapping them up in a BitmapWrapper class, it is now possible to use a new “bmp2bitmap” .NET app to convert straight from a BMP file to a BitmapWrapper subclass.

These new programs have enabled me to delete the PAGfx binary and the files it converted from the Woopsi demo folder. I’ve replaced the converted files with classes converted with bmp2bitmap.


ALite Changes

ALite, my long-neglected C#.NET framework for creating objects that interact with databases, has had a few updates. Back in June last year I complained that I wasn’t happy with the basic validation system. I have refactored this into a much more useful and extensible system. Instead of a single object that could validate a primitive value in a handful of simplistic ways, it now uses a combination of an interface and a base class to provide a structured way for creating validation objects that can be as complex as required. Martin Fowler’s Refactoring is already paying for itself.

I’ve tidied up the delegate- based validation system, too. I’ve fixed the only bug I spotted from the last release - clearing a collection now removes the collection’s property event changed listener from the child objects. Lastly, I’ve tidied up some obvious places that would cause problems with multithreaded code and made a few optimisations.

There’s still a few changes I want to make before I create a new release. Note that these changes are breaking changes. Not that anyone uses the library. Perhaps I’ll write some real documentation for the new release.