We recently created a companion iPhone application for a website
we released late last year, which needed to retrieve content from
the website. Rather than just retrieve pages of information
as html, we wanted to display lists of content, and we also wanted
to cache the content on the device for offline viewing. To do
this, it was decided we would use JSON as the transport as it is
lightweight.
On the client side, we used the JSON-Framework Cocoa based library
created by Stig Brautaset. On the server side we used JayRock
JSON-RPC library for dotNet.
Oh, and the website was based on the Umbraco CMS.
Background on JSON-RPC
The JSON-RPC
specification is fairly straightforward - it consists of a
request, a response, and a notification. The request sent to
the server has 3 parameters as follows:
- Method Name
- Parameters, and
- Id - This is used to associate the request with it's respective
reply, and provided it is unique can be used to quarantee that the
calling code receives the correct reply for the request - very
important if you are sending multiple requests asynchronously.
The response from the server also has 3 parameters:
- Result object - the result in JSON notation
- Error object - if an error is thrown by the called method, the
details will be contained in this object, including any exceptions
thrown, which is very useful for debugging
- Id - this is the same as the id passed in with the
Request.
Creating a JSON-RPC Service
Using the JayRock library, this is all encapsulated, and we can
just go about writing our Service Methods like so:
- In Visual Studio, or your favourite editor, start by creating a
Generic Handler (.ashx type).
- Change the class definition so that it derives from the
JsonRpcHandler class instead
- Create your Method declarations as per normal, but decorate
them with the JsonRpcMethod Attribute.
An example is as follows (this is the base class we have created
for authenticating user requests to the Umbraco backend):
using System.Web.Security;
using Jayrock.JsonRpc;
using Jayrock.JsonRpc.Web;
using System;
using System.Web;
namespace refactored.WebServices.json
{
/// <summary>
/// Provides a base class for JSON-RPC Services and handles authentication.
/// </summary>
public class BaseJSONService : JsonRpcHandler
{
protected string AuthenticationToken { get; set; }
[JsonRpcMethod("AuthenticateMember")]
public string AuthenticateMember(string username, string password)
{
..
..
}
[JsonRpcMethod("AuthenticationExpired")]
public bool AuthenticationExpired(string authToken)
{
return (HttpRuntime.Cache[authToken] == null);
}
protected bool IsUserValid()
{
return (!string.IsNullOrEmpty(AuthenticationToken) && !AuthenticationExpired(AuthenticationToken));
}
protected string GetUserName()
{
if (IsUserValid())
return HttpRuntime.Cache[AuthenticationToken].ToString();
else
return string.Empty;
}
protected MembershipUser GetMember() {
if (IsUserValid())
return Membership.GetUser(GetUserName());
else
return null;
}
private bool ValidateUser(string username, string password) {
return Membership.ValidateUser(username, password);
}
}
}
Once you compile and load the dll into Umbraco, along with the
associated ashx file, you can test the webservice in your favourite
web browser:

User Authentication and Web Services
One of the features of the iPhone Application was that it
allowed users to provide feedback on the content, as well as create
"favourite" lists. This required that users be able to
authenticate with the website in order to make changes to their
profile and update the lists on the website.
Because Web Services cannot store the users session, we need to
provide some way of authenticating the user each call. In order to
do this, an AuthenticateMember(string username, string password)
method was created on the Service that returned an authentication
token to be used in subsequent calls:
[JsonRpcMethod("AuthenticateMember")]
public string AuthenticateMember(string username, string password)
{
if (string.IsNullOrEmpty(username) || !ValidateUser(username, password))
throw new Exception("Your Username or Password is incorrect");
// Create and store the AuthenticatedToken before returning it
AuthenticationToken = Guid.NewGuid().ToString();
HttpRuntime.Cache.Add(
AuthenticationToken,
username,
null,
System.Web.Caching.Cache.NoAbsoluteExpiration,
TimeSpan.FromMinutes(60),
System.Web.Caching.CacheItemPriority.NotRemovable,
null);
return AuthenticationToken;
}
Then, on subsequent calls, we just pass the authentication token
in to be validated against the cached version.
Lets test out the method:

Notice wth this screen shot that the returned result was
actually the error - it even includes the Exception details along
with the erorr message.
Fixing up the parameters results in the following:

Note the returned value - this is the authentication token
generated by the server - we use this when calling subsequent
methods that require validation.
Well, that's it for now, hopefully you can see from this how we
can use JSON-RPC to retrieve information from a website and consume
it in other applications, or even using AJAX. Not only can we
retrieve information, we can also create new content and otherwise
manipulate information on a website.