Keeping web services simple
The easy way for .NET developers to create an API over HTTP is to use SOAP web services. It’s natively supported by .NET and has rich support for more complex data types such as the DataSet. The problem with SOAP is that it isn’t well supported by other platforms and to consume a .NET SOAP web service in PHP is a nightmare.
If you want to build an API for your web application over HTTP, then consider a simpler approach that is much faster, supports both GET and POST, can easily be RESTful, and works on all platforms. XML-RPC is a good way of doing such a service, but we can do it even simpler and define our own contract easily.
The class
I’ve build a very small class, RpcService, that let’s you pass plain text both ways over HTTP. The text will probably be XML for a more structured contract, but that’s up to you. The class has a static Send method and a static Receive method.
The Send method passes the plain text or XML to the request stream and returns the reply as a string. You can then parse the XML your self if needed. The Receive method listens for requests with text in the request stream and returns it as a string. Now you have both ends of the API – the client and the server.
Example
Let’s say you want to build a stock quote service that returns the quote of a given stock based on the a stock symbol. You then start by adding an HttpHandler to your website called stock.ashx. That file will function as your web service end point. In the handler’s ProcessRequest method you then call the Receive method to get the text from the request stream. It contains the stock symbol and now you need to respond with the current stock quote. You simply just write the quote using Response.Write in order to return it. It could look like this:
public void ProcessRequest(HttpContext context)
{
string symbol = RpcService.Receive();
string qoute = DataBase.GetQuote(symbol);
context.Response.Write(qoute);
}
Now you have the service ready on the server. The only thing missing is a way to consume the service . In order to do that we need to use the Send method of the RpcService class. It could look like this:
Uri url = new Uri("http://api.example.com/quote.ashx");
string symbol = "MSFT";
string quote = RpcService.Send(url, symbol, RpcService.HttpMethod.POST);
What happens here is that we now send the stock symbol in the request stream over HTTP to the stock.ashx service and retrieves the content of the response. The circle is now complete, we have a custom web service.
Use XML
Now you might think why in the world we need the RpcService when the above example could just use a WebClient to download the content and pass it a query string with the symbol. Well, you need it when you want to pass more complex data to the stock service. In that case it will be smart to use XML as the data format.
You will be able to do a complex query against the stock service that specifies at what dates you want the stock quotes returned from. Consider writing an XML document that looks like this and then pass it to the Send method:
<stock symbol="MSFT">
<date>2007-11-07</date>
<date>2007-11-06</date>
<date>2007-11-05</date>
<date>2007-11-04</date>
<date>2007-11-03</date>
<date>2007-11-02</date>
<date>2007-11-01</date>
</stock>
Then the XML will be written to the request stream and delivered to the stock.ashx service. The service could then iterate over the XML document to retrieve all the dates and return a response also in XML. It could look like this:
public void ProcessRequest(HttpContext context)
{
string request = RpcService.Receive();
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.LoadXml(request);
string symbol = doc.SelectSingleNode("stock").Attributes["symbol"].InnerText;
System.Xml.XmlNodeList list = doc.SelectNodes("//date");
context.Response.Write("<stock>");
foreach (System.Xml.XmlNode node in list)
{
DateTime date = DateTime.Parse(node.InnerText);
string quote = DataBase.GetQuote(symbol, date);
context.Response.Write("<quote date=\"" + date + "\">" + quote + "</quote>");
}
context.Response.Write("</stock>");
}
All this you could easily do in .NET using a SOAP web service, but this is much faster, much smaller and 100% cross platform compatible. You could use other formats instead of XML if you want. JSON objects for use in AJAX calls for instance.
The RpcService class
The static RpcService class exposes two public methods – Send and Receive. It also has a single private method and an enum for specifying the HTTP method. In total, it is 78 lines long including comments. You need to include the class on both the client and the server. For the server, you can just drop it into the App_Code folder. You can do the same on the client if it’s also a web application.
Comments
Comments are closed