Kayak, Simple.Data and Razor

Kayak

I recently built an application that had to produce an XML data feed over HTTP, but needed to run locally on a desktop computer. ASP.NET and IIS wan’t really an option, as the installation is too much of a headache, so I looked to Kayak. It’s a small HTTP server, which can run independently of the ASP.NET stack. As a developer, you essentially get this:

  public void OnRequest(HttpRequestHead request, IDataProducer requestBody, IHttpResponseDelegate response)
  {
    string outputText = "HELLO WORLD!";
    var headers = new HttpResponseHead()
    {
      Status = "200 OK",
      Headers = new Dictionary<string, string>()
      {
        { "Content-Type", "text/plain" },
        { "Content-Length", outputText.Length.ToString() }
      }
    };
    var body = new BufferedProducer(responseBody);
    response.OnResponse(headers, body);
  }

This is obviously fairly low level, I’ve never had to worry about setting the Content-Length before! The request variable just has the raw URI, you’re missing QueryString and Form, as well as Session and Application variables etc…

However, I like this simplicity, all I need to do is look at the URI, and work out what the appropriate outputText should be. I created a really lightweight MVC framework to accomplish this. I parsed the URI into a path and a dictionary of  parameters. I did some simple routing to figure out which of my (two) controllers I wanted to run, based on the first part of the path.

Razor

The controllers returned the name of a view, and a model. I plugged the Razor view engine in with the help of this project on Matthew Abbot’s blog post. I just load the view from the disk, and pass it into this project, with the model, and out comes the rendered view as a string. Perfect.

Simple.Data

I used Simple.Data in my controllers to do all the data access, which is when the Razor views stopped working. Simple.Data creates an in-memory assembly, which the view engine tries to load off the disk, so you just need to put a try catch around that method.

When using one of the dynamic objects from Simple.Data in the views, I seemed to have to cast it to an System.Collections.Generic.IDictionary<string, object> to read the values correctly.

Conclusion

What impressed me most of all about this mix of technology was how little effort it was to get Simple.Data to work. For something lightweight and ‘proof of concept’, it’s a perfect way of accessing data without any fuss or ceremony.

Kayak is cool, but it amazed me (I suppose I shouldn’t have been surprised) how little you get, or how much you take for granted in ASP.NET MVC.

I spent the most time getting the Razor views to work, it was sometimes quite difficult to figure out the cause of them not compiling correctly.

All in all, I’d use the same mix again.

In the end, my Kayak endpoint looked more like this:

  public void OnRequest(HttpRequestHead request, IDataProducer requestBody, IHttpResponseDelegate response)
  {
    try
    {
      Console.WriteLine(request.Uri);
      ControllerRequest controllerRequest = CreateControllerRequest(request);
      IController controller = CreateController(controllerRequest);
      if (null == controller)
      {
        Return404(request, response);
        return;
      }
      ControllerResponse controllerResponse = controller.Execute(controllerRequest);
      if (controllerResponse == null || controllerResponse.View == null)
      {
        Return404(request, response);
        return;
      }
      string view = GetView(controllerResponse.View);
      string output = RazorEngine.Razor.Parse<object>(view, controllerResponse.Model);
      Return200(response, output, controllerResponse.ContentType);
    }
    catch (Exception ex)
    {
      Return200(response, ex.ToString(), "text/plain");
    }
  }

Maybe I’ll turn this into a framework one day…

Advertisements