You’ve done it. You have written the coolest, fanciest utility ever and you want to unleash it on the world. You throw it up on CodePlex or SourceForge and eagerly await the praise from developers all over the world for such a cool piece of software. Ten minutes later you get your first comment: “This is really cool but I need to integrate it with my other utility, do you have an API?”

DOH!!

You should have seen this coming. It’s a cardinal rule. Developers ALWAYS want to extend stuff, or use it in a way that you might not have anticipated. An API allows your product to be integrated with other products, and makes any software package that much more valuable. Let’s look at a bug tracker for example. There are all sorts of opportunities for an API with something like this. What if you want to trap unhandled exceptions in your application and create bugs with them automatically? What if you want to take any bugs that are assigned to you and have them show up in your task list? Those are perfect examples of why an API is useful.

OK. So we know we need an API, the question is how do we do it? What do we need to consider? I’m going to assume that our API will be web based, meaning that we will access it through port 80. The age old debate seems to be Representational State Transer (REST) vs. Simple Object Access Protocol (SOAP). I’m not going to incite a flame war by saying one is definitely better than the other, there are great examples of each. Off the top of my head, I’d say Flickr is an outstanding example of a REST API, while Amazon is a great example of a SOAP API.

DISCLAIMER:  It was correctly pointed out to me that Flickr’s API is not a good example of a REST API, and my example API in this article is actually more like RPC than REST.

Basically, our API will take a request, and return an XML string with the response. The first thing we need to do in order to make that happen is to write our own HttpHandler. To do this, you need to create a class that implements the IHttpHandler interface in the System.Web namespace. Your class should look something like this after implementing this interface:

   1: public class TestHandler : IHttpHandler
   2: {
   3:   #region IHttpHandler Members
   4:   public bool IsReusable
   5:   {
   6:     get { throw new Exception("The method or operation is not implemented."); }
   7:   }
   8:  
   9:   public void ProcessRequest(HttpContext context)
  10:   {
  11:     throw new Exception("The method or operation is not implemented.");
  12:   }
  13:   #endregion
  14: }

I’ll start with the IsReusable property.   This just indicates that a single instance of our handler can handle multiple concurrent requests.  What does this mean to you?  For your handler to be reusable, it must be thread safe.  The ProcessRequest function does all the work for our handler, taking the HttpContext as a parameter.  To keep this example manageable, we will only create one method for our API, we’ll call it LoadPeople.  Since our API will be returning data in an XML format, we need to decide what the format of our XML should look like.  Each of our people records will have a first name and a last name, so our XML could look like this:

   1: <People>
   2:   <Person>
   3:     <FirstName>John</FirstName>
   4:     <LastName>Doe</LastName>
   5:   </Person>
   6:   <Person>
   7:     <FirstName>Fred</FirstName>
   8:     <LastName>Smith</LastName>
   9:   </Person>
  10: </People>
  11:   
Before we start writing our ProcessRequest function, we need to decide how the API is going to work.  Let’s say we want it to work like this: http://www.oursite.com/API/LoadPeople.ashx.  There are a few concepts that we need to go over.  First, when you write a custom HttpHandler, we need to tell IIS how to handle it, which we can do through our web.config file.  I’m going to assume that in our case, we have a website that needs to function normally, and we only want our custom handler to process requests that go point to /API.  We can do this by adding a verb to the httpHandlers section of the web.config.  In my example, it looks like this: (lines 2-4 in my example are on the same line in the actual web.config)
   1: <httpHandlers>
   2:   <add verb="*" path="API/*.ashx" type="RestAPI.TestHandler, RestAPI, 
   3:   Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
   4:   </add>
   5: </httpHandlers>

I’m not going to go into a lot of detail about this part, I’ll just sum it up by saying that my website project has it’s assembly name set to RestAPI in the properties, and our handler’s classname is TestHandler.  You can get more information on how to set these up here or here.   I chose .ashx as my extension arbitrarily, so use whatever extension you like. 

Lastly, we need to write the request processing function of our handler.  I threw together a quick example, and mine ended up looking like this:

   1: public class Person
   2: {
   3:    private string _firstName;
   4:    private string _lastName;
   5:    public string FirstName
   6:    {
   7:       get { return _firstName; }
   8:    }
   9:    public string LastName
  10:    {
  11:       get { return _lastName; }
  12:    }
  13:    public Person(string fname, string lname)
  14:    {
  15:       _firstName = fname;
  16:       _lastName = lname;
  17:    }
  18: }
  19:  
  20: public class TestHandler : IHttpHandler
  21: {
  22:    #region IHttpHandler Members
  23:    public bool IsReusable
  24:    {
  25:       get { return true; }
  26:    }
  27:  
  28:    public void ProcessRequest(HttpContext context)
  29:    {
  30:       // use the http context to figure out what method they 
  31:       // are trying to call.
  32:       string methodName = GetMethodName(context.Request.Path);
  33:  
  34:       // load a dummy list of people to return.
  35:       List<Person> personlist = new List<Person>();
  36:       personlist.Add(new Person("John", "Doe"));
  37:       personlist.Add(new Person("Fred", "Smith"));
  38:  
  39:       switch (methodName)
  40:       {
  41:          case "loadpeople":
  42:             // Return the list of people.
  43:             using (XmlTextWriter writer =
  44:                new XmlTextWriter(context.Response.OutputStream, Encoding.ASCII))
  45:             {
  46:                context.Response.Clear();
  47:                writer.Formatting = Formatting.Indented;
  48:                writer.WriteStartDocument();
  49:                writer.WriteStartElement("People");
  50:  
  51:                foreach (Person p in personlist)
  52:                {
  53:                   writer.WriteStartElement("Person");
  54:                   writer.WriteElementString("FirstName", p.FirstName);
  55:                   writer.WriteElementString("LastName", p.LastName
  56:                   writer.WriteEndElement();
  57:                }
  58:  
  59:                writer.WriteEndElement();
  60:                writer.WriteEndDocument();
  61:                writer.Close();
  62:                context.Response.End();
  63:             }
  64:             break;
  65:  
  66:          // This means they called an invalid method, let them know that.
  67:          default:
  68:             using (XmlTextWriter writer = 
  69:                new XmlTextWriter(context.Response.OutputStream, Encoding.ASCII))
  70:             {
  71:                context.Response.Clear();
  72:                writer.Formatting = Formatting.Indented;
  73:                writer.WriteStartDocument();
  74:                writer.WriteStartElement("response");
  75:                writer.WriteElementString("errorType", "InvalidMethod");
  76:                writer.WriteElementString("methodName", methodName);
  77:                writer.WriteEndElement();
  78:                writer.WriteEndDocument();
  79:                writer.Close();
  80:                context.Response.End();
  81:             }
  82:             break;
  83:       }
  84:    }
  85:    #endregion
  86:  
  87:    private string GetMethodName(string path)
  88:    {
  89:       // I know that this handler is called like this: /API/function.ashx
  90:       string[] matches = path.Split('/');
  91:       int count = matches.GetLength(0);
  92:       string method = matches[count - 1].Substring(0, matches[count - 1].Length - 5);
  93:       return method.ToLower();
  94:    }
  95: }

When you are sending output through the API, you can use the Response object in the HttpContext that is passed into the ProcessRequest function.  I used the XMLTextWriter class for my output, and just sent the  output to the OutputStream of the Response object, as seen on lines 44 and 69 above.  Everything should be fairly self explanatory above….I just put together a dummy collection to return to the user.   This sample API relies on the function being requested being called through the URL, so I also included a way to tell the user that they requested an invalid method.

One thing that I didn’t touch on with this example is parameters.  You could fairly easily have full parameter support by just passing them through the querystring.  For example, you could add an AddPerson function to our sample API and call it like this:  http://www.oursite.com/API/AddPerson.ashx?firstName=Jimmy&lastName=Jones.  We would just have  to be sure to error check our parameters for the function, etc.

That’s all their is to it, an API in just a few steps! 

kick it on DotNetKicks.com