One might think that the title of this blogpost is due to the fact that this summer I will be turning 30.
However it is actually a task I have been looking into, that could also be phrased as: I wish to build a REST based service, what are my options? With REST gaining in popularity I think this a question that a number of developers are asking themselves these days.
First of all what is REST? REST is about staying true to the HTTP protocol, and using it to communicate between a client and a server - as opposed to SOAP. To parafrase from Wikipedia being RESTful is about using URIs, HTTP verbs and mediatypes as the means to communicate using a traditional request/response model.
Sinatra
A framework like Sinatra, that I looked at not too long ago, is a pretty popular choise for building REST based services in Ruby. Sinatra is build around defining routes, that respect http verbs and enable you to plug in a bunch of different viewengines that produces output using templates. With Sinatra you can work with templates in: Haml, Erb, Erubis, Builder, Nokigiri, Saas, Scss, Less, Liquid, Markdown, Textile, RDoc, Radius, Markaby, Slim and CoffeeScript - and probably others that I don't know about. So Sinatra is very versatile and it provides a very clean way of doing REST without making assumptions about what you want to return.
The issue for me as a daytime .NET and C# guy is, that going Ruby or even IronRuby is not really an option outside of my pet projects.
Sample:
get '/home/:name' do
"Hello #{params[:name]}!"
end
Nina and Nancy
For .NET there are Sinatra clones called Nina and Nancy - which are open source projects. They both manages to stay fairly simple, but being C# it requires a little more ceremony, and a bit more syntactic gobbledigook. As of this writing Nina comes with viewengines for NDjango, NHaml, Razor and Spark - so the quantity is not as impressive as with Sinatra, but depending on your tastes the quality might be. Nancy allows you to plug in viewengines and comes with Spark and JSon samples – but the general idea is that you write a wrapper for the viewengine yourself.
Personally I coulde definitely see myself using Nina with Razor or to either return JSon or XML - using my flavour of the month serializer.
Nina sample:
Get("home/{name}", (m,c) => Text("Hello, " + m["name"]));
Nancy sample:
Get["/home/{name}"] = parameters => {
return string.Concat("Hello ", parameters.name);
};
WCF DataServices
For services that need to make a datamodel accessible WCF DataServices is an attractive option. It allows the client to define a query through the URI, making the service very flexible compared to providing a fixed set of functions as implemented in the service. It is pretty easy to build a model using eg. Entity Framework, and exposing it with WCF DataServices. For the developer it is also straight forward to define access rights, and write custom methods that can be exposed to handle any specific needs. Data will be returned as either JSon or XML in the OData format - which is Microsofts extention of AtomPub. A limitation with WCF DataServices in its current version is that it does not support complex models with navigation properties - so you will probably need to have a model specifically for the service.
Sample:
public class Products : DataService<ProductContext>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Products", EntitySetRights.AllRead);
}
}
WCF Web API
The WCF Web API is an open source project by Microsoft, that is focused on building a HTTP true experience for WCF, making it "speak" HTTP - or in other words RESTful. This is a pretty new project, that is currently published as a preview 3. It enables you to build your own processores, that can return content based on mediatypes. The samples include services that return images and JSon. It also includes the features used by WCF DataServices to expose an IQueryable. Using this the service can do querycomposition, so the client can send a query that will be executed on the server against eg the SQL database.
Sample:
[WebGet(UriTemplate = "{name}")]
public JsonValue Get(string name)
{
var contactResponse = (dynamic)new JsonObject();
contactResponse.Message = "Hello " + name;
return contactResponse;
}