I have been disappointed with the amount of legwork involved with setting up a simple REST API, so I decided to write a small attribute-based framework. The goal was to make it as simple as possible and be discoverable. Right now, the framework only supports GETting objects from your api, but that will change very soon.
Setting up RestLess
That's it!
Exposing an object via the api
You may have a Product object in your application with the properties Name, Description, and Amount. If you want to expose this via the api, you would simply decorate this class as follows. (RestLess code in blue, Comments in green)
// decorate the class as a RestResource, the first parameter is the url of the
// resource appended to the root url (defined in web.config). In this case /api/products/
// the second parameter specifies if this resource is discoverable (more on this later)
[RestResource("products", true)]
public class Product : IRestReadable
{
private string _name;
private string _description;
private double _amount;
// render this property as xmlelement "productname"
// IOType.InputOutput specifies that this property will be rendered
// to the outputted xml, and can also be inputted via querystring
[RestProperty("productname", IOType.InputOutput)]
public string Name
{
get { return _name; }
set { _name = value; }
}
// render this property as xmlelement "productdescription"
// IOType.Output specifies this property is rendered to the user,
// but it is not allowed in querystring for input
[RestProperty("productdescription", IOType.Output)]
public string Description
{
get { return _description; }
set { _description = value; }
}
// render this property as xmlelement "amount" (output only again)
[RestProperty("amount", IOType.Output)]
public double Amount
{
get { return _amount; }
set { _amount = value; }
}
#region IRestReadable Members
public object GetRestObject()
{
// this is where you could go access your data access layer or whatever
// method you choose.
// this is also where you could request an API key via querystring for security etc
// since productname is specified inputoutput, you should check for
// Request.QueryString["productname"] to get any data the user sends
// for the purposes of this demo, lets just make an object and pass it back
Product p = new Product();
p.Name = "Super Fly Ink Pen";
p.Description = "This is the most super fly ink pen ever";
p.Amount = 10.00;
return p;
}
#endregion
}
Done - that's all you have to do! You can add these attributes to as many of your classes as you want to expose through your api.
If you request the url http://yoursite.com/api/products/default.aspx, the output will look like below

Discovering The API
As I mentioned earlier, the second parameter of the RestResource attribute specifies if the resource is discoverable. If this parameter is set to true, you can visit http://yoursite.com/api/discover.aspx to see what the available resources are. The output of http://yoursite.com/api/discover.aspx will look something like below (notice another Customer object - I did not include this class for brevity).

I plan on making lots of updates and changes to the framework as needed (I am VERY open to suggestions!!). This is a rough-rough draft, but seems to work well.
... now go and add an API to your .NET application in a few minutes. :)
** UPDATE **
An updated version has been posted to http://ndepth.net/blog/restless-a-simple-rest-framework-part-2/. This version includes cleaner urls (no default.aspx) and IRestWritable.
Jayme
Chris Carter
on 4.20.2008 at 8:35 PM
I'm not sure, of the 10 kicks you received(as of the time of this writing), how many of those who kicked actually played around with your assembly. I took some time cuz I like the concept but I have issues with the mention of the term REST.
I'm confident that Mr. Fielding would not agree that anything ending with .aspx would fit his vision of REST. The prototype javascript guys, set up their online api using a RESTful architecture. If I want to know about the Element class, this is what I type: http://prototypejs.org/api/element. My expectation is that I'm going to get a web page that describes the prototype Element class. Already know generally what the Element class is used for but got stuck on the down method? type this in http://prototypejs.org/api/element/down. My expectation is to receive an html page(cuz i typed it in my browser) that describes the down method of the element class, and that's exactly what i get.
The delicious peeps did something similar. Want to know my bookmarks tagged as css? type this in: http://del.icio.us/chrcar01/css. Need to develop some sooper cool app that needs to get a JSON feed of my urls tagged as nhibernate? here ya go, feeds.delicious.com/.../nhibernate
What's the common thread? I have no clue about the technology that's delivering that content. Maybe it's .NET, or Java, or Python, Apache, IIS, or whatever, I don't know about the implemented architecture and I don't care.
On the developer side of things, what if you switched from .NET to Ruby on Rails on the server. You're screwed on any content previously published with a URL with an extension like .ASPX. Anyone who's bookmarked that aspx page will prolly get a nice 404, even though the content exists, it just doesn't have that extension.
RestLess seems more like straight up ASP.NET WebServices plus URL rewriting minus an xsd that can verify whether the response returned from the service matches your expectation. This is NOT a bad thing, not at all, that is, in the right context.
I'm thinking more of the consumer side of things as I'm writing this. So when I call something rendered through RestLess, and it returns xml, I try to imagine how painful it might be to use the results. Sending back plain jane xml requires me to do xml parsing which sucks, that's time consuming monkey coding. The web service client you get from wsdl.exe outputs one of those for you, no extra code required. Exposing your classes to a web service requires one attribute, Serializable, for .NET to know how to send that to clients requesting your resource.
So I guess I'm looking more for the need that RestLess fulfills, it's not REST and it's a step backwards from web services. Do you have a scenario where you've used RestLess because web services did not do it for you?
Jayme
on 4.20.2008 at 10:08 PM
Hi, Chris :) thanks for your comments.
I agree with you on the url including .aspx, I don't like it either. The only reason I included it is so users didn't have to configure IIS to process all requests through the runtime (eliminate the need for .aspx, .ashx, etc) to map to asp.net. If you configure it as such, problem solved.
If you want great urls (which we all do), you could easily do yoursite.com/products/productname ... with the help of a urlrewriting engine - which is a problem RestLess is not built to solve.
With that said, the discover option needs a lot of work. It's hardcoded now to show default.aspx and any parameters the user could pass. It definitely needs to be customizable in the event someone uses a urlrewriting engine to tidy things up.
The verbs that are sent to the URI determine the method that is called (GET = IRESTReadable), soon to come will be IRESTWriteable, etc which will handle other verbs at the specified URI.
Hope this helps!
Jayme
superjason
on 4.21.2008 at 8:28 AM
Possibly a stupid question:
Can IIS be configured to allow ASP.NET to process files without extensions?
Karthik
on 4.21.2008 at 9:03 AM
Jayme,
This is a great concept. You might want to try extending it for ASP.NET MVC so you can easily get rid of the .aspx for the requests :)
Also the open source MVCContrib project includes a SimpleRest controller to route true REST based requests with.
Jayme
on 4.21.2008 at 10:08 AM
superjason,
Yes. It's called an IIS wildcard mapping - check out this link for more info. weblogs.asp.net/.../tip-trick-integ
Karthik,
Good idea!.. I haven't messed around with MVC yet as much as I'd like :(
Ken Robertson
on 4.21.2008 at 10:39 AM
Jayme, looks pretty sweet! One thing I'd be interested to see would be to utilize something like a "RestMethod". Right now, the API modifies the objects directly, but might be good to move towards and intermediary. Usually with REST, they still follow the MVC pattern (view being the xml). Currently, it is kind of just MV... there is no intermediary between the model and the view. For read-only, it isn't as important, but for doing post/puts, you'd want it to do things like permission enforcing, validation, etc.
Joe
on 4.23.2008 at 2:50 PM
Jayme, very nice work!
Would you please post the source code for restless.dll, I need that
I want to see delete, put, update soon.
Jayme
on 4.23.2008 at 10:26 PM
IRestWritable implemented and cleaner urls.
ndepth.net/.../restless-a-simp
Jayme