A simple razor api : JSON Poco’s in Umbraco / WebMatrix

I’m rebuilding some ajaxy stuff on an Umbraco site using Knockout to spice up the UX. And I wanted a nice way to write my api functions. I tried several different approaches (Base, SignalR, WebApi), but in the end I got back to simple Razor scripts with a tiny twist.

1. Reserve a /macroScripts/api/ path in web.config to make your files callable directly from their url’s + you can still edit them from within Umbraco UI if you wish. Or just use /api/.

    <add key="umbracoReservedPaths" value="~/umbraco,~/install/,~/macroScripts/api" />

2. Write one file for each remote procedure to get a nice and easy to maintain structure. Use InitializePage to get rid of unnessesary whitespace. Only add minimum code to the api-files, ideally just one call.

2. Serialize and deserialize Json to Poco’s using the Json helper.

3. Make a little js helper to make the calls nicer.

Here’s a sample of how a Get (/macroScripts/api/order/get/{id}) script can look like:

@functions{
    // URL : /macroScripts/api/order/get/{id} [GET]
    protected override void InitializePage()
    {
        base.InitializePage();
        // UrlData[0] is the first url part after the path, in our case the {id}
        var orderId = UrlData[0].AsInt();
        Json.Write(WebApp.Db.SingleOrDefault<Order>(orderId),Response.Output);
    }
}

And here’s a sample of a post (/macroScripts/api/order/insert)

@functions{
    // URL : /macroScripts/api/order/insert [POST]
    protected override void InitializePage()
    {
        base.InitializePage();
        // Deserialize input stream to Order object
        var jsonData = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
        var order = Json.Decode<Order>(jsonData);                
        var newOrderId = WebApp.Db.Insert(order);
        Json.Write(newOrderId, Response.Output);
    }
}

My javascript calls looks like this:

// post knockout viewmodel:
my.utils.postJs("/order/insert", ko.toJSON(viewModel), function (newOrderId) {
  // update viewmodel with newOrderId;
});
// get:
my.utils.getJs("/order/get/" + orderId, function (order) {
  // do something with order
}

Thats it. Works on my machine.

Some nice things about this:

* It’s using Pocos, Json de- & serialized the same way as in WebApi and SignalR
* It’s just Razor, no need for extra DLL’s
* Easy to maintain structure

Comments / questions / suggestions are very welcome as always!

Here’s a gist with the same code as above + that little js helper

Also make sure you’re using in your web.config to be able to use WebPages funcitonality.

There is one problem with date formatting. The best workaround I found for it is to use Json.Net serializer (which is in Umbraco bin already). Like this:

        var isoConvert = new IsoDateTimeConverter();
        isoConvert.DateTimeFormat = "yyyy-MM-dd hh:mm:ss";
        Response.Write(JsonConvert.SerializeObject(Get(UrlData[0].AsInt()),isoConvert));
        var jsonData = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
        var isoConvert = new IsoDateTimeConverter();
        isoConvert.DateTimeFormat = "yyyy-MM-dd hh:mm:ss";
        var order = JsonConvert.DeserializeObject<Order>(jsonData, isoConvert);

        Json.Write(Insert(order), Response.Output);
Advertisements

5 thoughts on “A simple razor api : JSON Poco’s in Umbraco / WebMatrix

  1. Hello, thank you very much for this tutorial however I ddn’t manage to make it work on the production server. It is working fine on my computer.
    On the production server, I didn’t used WebMatrix and I did on my computer. Do you know how can I be able to configure it?
    I am looking forward from hearing from you.

    • It was just a 404 message.
      I compared the 2 web.config and I found that was just few difference and I think it was because of that line :
      in the appSettings.

      I found this post on Stackoverflow :
      “webPages:enabled with value false prevents .cshtml or .vbhtml files in the Views folder from being directly accessible from a web browser.”

      Thank you very much for answering and for you blog.
      Cheers

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s