Category Archives: Code

NSDate from OData

Recently I’ve been working on an iOS project that loads data that we publish via the Open Data Protocol (OData).

At first everything was working perfectly. I was using JSONKit and NSOperation to download and process the information. That was until I had to get a DateTime object…which resulted in an epic fail!

It turns out that WCF Data Services publish DateTime objects as a new Date object represented by the time in milliseconds (not seconds) since January 1, 1970. Anyone familiar with EPOCH dates knows about January 1, 1970 right?

The problem isn’t so much in that it publishes dates from a known time, rather that it does it in the least accessible way! The value is rendered out (in JSON) as “\/Date(1311836400000)\/” – yeah..I know, right?

So now I had to figure out a nice way to parse this very custom date format in Objective-C. This led me to the shocking (and borderline unacceptable) realization that objective-c (lower case to drive the point home) has no support for regular expressions. There’s no punch-line to this joke…for real. No support for regex. A Unix-based OS has a development language that has no support for something that is natively supported (see the * below)!

To start, I decided to add a category to the NSDate object that would allow me to work with these ridiculous strings.

NSDate+OData.h

#import <Foundation/Foundation.h>

@interface NSDate (OData)

- (id)initWithODataString:(NSString *)dateString;
- (NSString *)toODataQueryFormat;

+ (NSDate *)dateFromString:(NSString *)dateString;

@end

NSDate+OData.m

#import "NSDate+OData.h"

@implementation NSDate (OData)

- (id)initWithODataString:(NSString *)dateString
{
    return [[NSDate dateFromString:dateString] retain];
}

- (NSString *)toODataQueryFormat
{
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];

    NSString *formattedDate = [formatter stringFromDate:self];
    [formatter release];

    return formattedDate;
}

+ (NSDate *)dateFromString:(NSString *)dateString
{
    NSInteger startIndex = [dateString rangeOfString:@"("].location;
    NSInteger endIndex = [dateString rangeOfString:@")"].location - startIndex;
    long long ticks = [[dateString substringWithRange:NSMakeRange(startIndex + 1, endIndex)] longLongValue];

    NSDate *date = [NSDate dateWithTimeIntervalSince1970:(ticks / 1000)];
    return date;
}

@end

The code above allows me to get an NSDate from the crazy OData DateTime string and also convert an NSDate to another (quite different) format used by OData to query based on a DateTime value.

To get an NSDate from the OData string, I am substring’ing the value between the two brackets. This value is then converted to a long long value (twice on purpose for you .NET developers out there). The NSDate has a static method called dateWithTimeIntervalSince1970: that will return an (autoreleased) NSDate object with the value of the time (in seconds) since January 1, 1970.

To get the date to the query format used by OData (see OData URI Conventions), we need to take an NSDate and get it into the format “yyyy-MM-dd’T'HH:mm:ss” for example, “2011-07-29T18:15:00″.

I hope this information helps someone, as I was unable to find a simple example online anywhere (although I will concede that my googling skills could use some work).

* Please don’t take this as a complete knock to Objective-C. The language is quite easy to work with and definitely robust…just lame on the regex front!

Showing Enums as a Select List in MVC and Razor

Recently I needed to show a drop down list of all of the enumeration values. So I did what we all do and hit up Google. While there was plenty of information out there detailing how to convert the enum to a Dictionary<int, string> and render it, I couldn’t find something that fit my needs.

Essentially I have an enumeration of field types. I wanted to display the names of those fields in a drop down list, but be able to make some of them prettier. Here is the enumeration:

public enum FieldType
{
    Text = 1,
    HTML = 2,
    [Display(Name = "Date/Time")]
    DateTime = 3,
    Number = 4,
    [Display(Name = "Dropdown List")]
    DropdownList = 5
}

Now I need a way to show the items in a drop down list, and set the selected one (from the Model) to selected. I decided the easiest way would be to use an editor template. So I created the FieldType editor template (under /Views/Shared/EditorTemplates) using the code below:

@model FieldType
@using System.ComponentModel.DataAnnotations
<select name="@ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty)"> 
@foreach (var name in Enum.GetNames(typeof(FieldType))) {
    <option selected="selected" value="@name">@DisplayName(name)</option>
}
</select>

@helper DisplayName(string name) {
    var attr = typeof(FieldType).GetField(name).GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault() as DisplayAttribute;

    if (attr != null)
    {
        @attr.Name
    }
    else
    {
        @name
    }
}

Now when I want to render a FieldType property of an object, I can just use the Html.EditorFor extension as I would for any other object:

</pre>
<div class="editor-label">@Html.LabelFor(model => model.Type)</div>
<div class="editor-field">@Html.EditorFor(model => model.Type)
 @Html.ValidationMessageFor(model => model.Type)</div>
<pre>

And Voila!

If for some reason you cannot name your editor template the same as the type, you can supply the name of the template to the EditorFor method using one of the overloads provided.

Happy coding!

Global Namespace Includes with MVC3 and Razor

While I’m loving MVC3 and the Razor view engine, I was sorely disappointed when I couldn’t use the system.web/pages/namespaces collection in web.config to add global namespace includes.

After a bit of hunting and looking through the web.config files underneath the views folder (in each Area), I found that this can be accomplished by adding the following to the root web.config file:

<configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>

  <system.web.webPages.razor>
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>



Now you can add any namespaces you require under the new razor namespaces section.