Consuming RESTful API with RESTframework

As explained in previous post, we’re going to demonstrate how RESTframework handles REST web services. I’ll be consuming a simple Django demo web service created in previous post, so either grab the sources or read the post and build it yourself. Assuming you have this service running on localhost, port 8000, we can continue.

First, download RESTframework from GitHub. With git client, simply type in terminal:

$ git clone git@github.com:ivasic/RESTframework.git

The quickest way to get RESTframework into your project is just including all the files from RFClasses  folder. RF does not have any external dependencies so building shouldn’t be a problem.

RFClasses

RFClasses

Now, we’ll also need JSONKit to parse API response and MBProgressHUD to show some progress. Grab both from GitHub and add to your project.

Fetching objects list

We’ll have 2 view controllers in our demo app. One will be a simple object list and the other one will be, even more simple, view controller for creating a new object. First, we’re going to show how to fetch the object list. We’ll need a GET request to /objects/ URL and we’ll need to parse the JSON array we get in response and show in the table view.

RFRequest* r = [RFRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8000/"] type:RFRequestMethodGet resourcePathComponents:@"objects", nil];
[MBProgressHUD showHUDAddedTo:self.view animated:YES].labelText = NSLocalizedString(@"Loading...", @"");
[RFService execRequest:r completion:^(RFResponse* response) {
	[MBProgressHUD hideHUDForView:self.view animated:YES];
 
	if (response.error) {
		UIAlertView* aiv = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"") message:response.error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
		[aiv show];
		return;
	}
 
	self.dataSource = [response.dataValue objectFromJSONData];
	[self.tableView reloadData];
}];

So, what we’re doing in this code snippet is:

  • Creating a GET RFRequest with appropriate URL and resource path
  • Attaching MBProgressHUD to our view to show spinner progress
  • Executing RFRequest and defining the block to execute after RFResponse is received
  • Inside this block, we simply check for errors, parse the response, add to our tableView dataSource and reloading the table
You can see all this in action in the project sample attached to this blog post (at the bottom).

Creating new objects

Our view controller for creating new objects is responsible for creating POST requests to /objects/ URL. Again, very simple, you just need to do this:

RFRequest* r = [RFRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8000/"] type:RFRequestMethodPost resourcePathComponents:@"objects", @"", nil];
 
[r addParam:self.txtName.text forKey:@"name"];
[r addParam:self.lblDate.text forKey:@"date"];
 
[MBProgressHUD showHUDAddedTo:self.view animated:YES].labelText = NSLocalizedString(@"Submitting...", @"");
[RFService execRequest:r completion:^(RFResponse* response) {
	[MBProgressHUD hideHUDForView:self.view animated:YES];
 
	if (response.error) {
		UIAlertView* aiv = [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"") message:response.error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
		[aiv show];
		return;
	}
 
	UIAlertView* aiv = [[[UIAlertView alloc] initWithTitle:@"Success" message:@"Success" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
	[aiv show];
 
	[self.navigationController popViewControllerAnimated:YES];
}];

Similar to our previous snippet, but this time we also add some parameters to the request – name and date strings.

This is a brief overview with sample Xcode project of how RESTframework consumes RESTful web APIs. Questions welcomed via comments as usual.

 

Download project: RESTframework demo Xcode project download

RESTful web service, API with ASP MVC 2

In this very simple tutorial, I’ll show how to build a basic RESTful API with Microsoft ASP MVC 2 later to be used with various clients (e.g. iOS application). This is a very basic level tutorial but it will show how easy it is to build powerful REST services in the matter of minutes.

The first thing to do is to create a new MVC 2 project, as simple as shown on the screenshot.

Create new MVC 2 project

Create new MVC 2 project

Now, I have deleted the Account controller and all the views cause I don’t need it for this example, but you don’t have to. The key concept to understand here is pretty simple – instead of returning back the Views as action results, we return JSON. MVC already provides HTTP verbs such as GET, POST, PUT and DELETE so all we really need to do is prepare our data and (de)encode it as JSON and we’re done. Fortunately enough, MVC also provides built-in JsonResult which inherits ActionResult which makes our job even easier. A simple GET action that returns a “Hello World” might look like this:

[HttpGet]
public ActionResult Index()
{
	return Json("Hello World!", JsonRequestBehavior.AllowGet);
}

There you go, a simple GET method is created. Now if you want to return something more complex, you can pass any serializable object to the Json() method and return that back. Here’s an array/dictionary combination.

[HttpGet]
public ActionResult Array()
{
	List<object> objects = new List<object>();						
	Dictionary dict = new Dictionary();
	dict.Add("key1", "value1");
	dict.Add("key2", "value2");
	objects.Add("item1");
	objects.Add("item2");
	objects.Add(dict);
	return Json(objects, JsonRequestBehavior.AllowGet);
}

This produces a JSON like this:

["item1","item2",{"key1":"value1","key2":"value2"}]

Ok, so how about other REST concepts like PUT, POST or DELETE? Easy as well. Define your action and just place a HTTP verb attribute like this example:

[HttpPut]
[ActionName("Index")]
public ActionResult IndexPut(string key, string value)
{
	Dictionary dict = new Dictionary();
	System.Web.Caching.Cache c = HttpContext.Cache;
	if (key == null || value == null)
	{
		dict.Add("result", "failed");
		dict.Add("message", string.Format("No key or no value provided"));
	}
	else
	{
		if (c.Get(key) == null)
		{
			c.Add(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
			dict.Add("result", "ok");
			dict.Add("message", string.Format("You have inserted {0} for key {1}", c[key], key));
		}
		else
		{
			dict.Add("result", "failed");
			dict.Add("message", string.Format("Value for key {0} already exists. Use POST to modify the value", key));
		}
	}
	return Json(dict);
}

The example above takes 2 input parameters named key and value (both strings but can be any object) and puts them into HTTP Cache. It also prevents to PUT another value with the same key. The project source code has other methods as well (POST and DELETE) used to modify the values and delete values for keys. Take a look on how that is implemented. This is very basic stuff so I won’t cover those methods here but feel free to ask in comments if something is unclear.

This REST example will be used for future posts covering REST integration in iOS, so you can keep it somewhere for testing. The project source code can be downloaded here: ASP MVC 2 REST service example

Calling JSON-RPC webservice in iOS

This topic is already covered in my post for consuming .NET web services in iOS but some questions were raised about passing arguments to the JSON-RPC methods that require them. In this short post I’ll just explain how to do just that.

Assume you have a few RPC methods that require some arguments like this.

[Jayrock.JsonRpc.JsonRpcMethod("HelloWorld")]
public string HelloWorld()
{
	return "Hello World!";
}
 
[Jayrock.JsonRpc.JsonRpcMethod("Echo")]
[Jayrock.JsonRpc.JsonRpcHelp("Simple echo method, takes string input and returns it")]
public string Echo(string input)
{
	return input;
}
 
[Jayrock.JsonRpc.JsonRpcMethod("EchoArray")]
[Jayrock.JsonRpc.JsonRpcHelp("Returns input arguments as an array of strings")]
public List EchoArray(string str1, string str2, string str3, string str4)
{
	List lst = new List();
	lst.Add(str1);
	lst.Add(str2);
	lst.Add(str3);
	lst.Add(str4);
 
	return lst;
}

Now, those “Echo” methods need some arguments passed to them and in this case I worked with strings but remember those args can be any primitive or complex but serializable types. So now that we have a working web service, we can query it from iOS. I’ll refer to my old example project which can be found here. The way it’s coded right now is to call the HelloWorld method without any arguments like this.

JSONRPCService* svc = [[JSONRPCService alloc] 
	initWithURL:[NSURL URLWithString:txtURL.text]];
svc.delegate = self;
 
[svc execMethod:@"HelloWorld" andParams:[NSArray array] withID:@"1"];

We need to notice that we passed an empty NSArray for params. This is because our HelloWorld doesn’t need any arguments. Easily enough, if you want to call the Echo method with a single param you’ll just add a string to an array and pass that array as execMethod:andParams:withID  2nd argument.

JSONRPCService* svc = [[JSONRPCService alloc] 
	initWithURL:[NSURL URLWithString:txtURL.text]];
svc.delegate = self;
 
[svc execMethod:@"Echo" andParams:[NSArray arrayWithObject:@"Echo Me!"] 
	withID:@"2"];

You can pass as many arguments as your method requires just stack ‘em up in an NSArray and make sure the argument order complies with the argument order of the web method.

JSONRPCService* svc = [[JSONRPCService alloc] 
	initWithURL:[NSURL URLWithString:txtURL.text]];
svc.delegate = self;
 
[svc execMethod:@"EchoArray" 
	andParams:[NSArray arrayWithObjects:@"1st arg", @"second arg", @"3rd arg", @"4th arg string", nil] 
	withID:@"3"];

Hope this helps!

JSON (de)serialization in iOS

A few people asked how to serialize and deserialize JSON data in iOS projects. I know it’s covered on almost every cocoa blog on this planet and basically very simple, but I’ll describe in this short post anyway. There are a couple JSON libraries for Objective-C that I know of, but the 2 most popular and widely used are TouchJSON and SBJSON. Both are very simple to use although TouchJSON developers seem to be a bit more active.

TouchJSON

You start by downloading TouchJSON files from GitHub and including them into your project.The next step would be importing header files CJSONDeserializer.h and/or #import “CJSONSerializer.h” and you’re good to code it. Very simple, like this:

Deserialization:

CJSONDeserializer *jsonDeserializer = [CJSONDeserializer deserializer];
NSError *error;
NSDictionary *resultsDictionary =
          [jsonDeserializer deserializeAsDictionary:jsonData error:&error];

Where jsonData is a string representation of your json data.

Serialization:

    NSString *jsonString = [[CJSONSerializer serializer]
               serializeObject:myDict];
    NSData *data = [jsonString dataUsingEncoding: NSUTF8StringEncoding];

where myDict is a NSDictionary you want to serialize. You can also use jsonString directly if you don’t need NSData…

SBJSON

Similar stuff here too, download the files and include them in your project. After that, a simple import of “JSON.h” in your implementation files enables you to parse JSON with ease.

Serialization

NSString* jsonString = [myDict JSONRepresentation];

That’s it. myDict is a NSDictionary* and with a single line you converted it to its JSON representation.
Deserialization

NSDictionary* result = [jsonString JSONValue];

Again, a single line and you converted your jsonString NSString object to Cocoa NSDictionary structure.

Which one should I choose?

Both are simple and fast, although I didn’t benchmark them. I’d suggest to try out both and make your pick, you certainly won’t go wrong with either. I personally go with SBJSON just for the sake of ultra simplicity.

 

BTW,  if you run into problems with linking JSON libraries (e.g. you’re already using some library that includes JSON library) make sure you read about this, you will find it helpful.

Consuming ASP.NET web services in iOS part 2

In previous blog post I’ve explained how to create iOS friendly ASP .NET web service with JSON RPC so now we’re going to take it further by creating an iPhone app that will consume this web service. Since iOS natively does not support JSON, we’ll be using this nice JSON framework available on Google Code here. This framework provides NSObject categories which allow simple JSON parsing and and it’s really convenient to use with iOS SDK. Other than that, we’ll be using native iOS SDK APIs only to create HTTP connection and query our JSON RPC service. Calling this web service is done by creating NSURLRequest with HTTP POST method and passing method name, method parameters (arguments) and identificator. NSURLConnection uses this request and does the magic we need. Let’s see the code.

First, we need to create JSON string which we’re going to POST to our RPC service. We do this by simply creating a dictionary and breaking it down to JSON representation.

 
//RPC
 
NSMutableDictionary* reqDict = [NSMutableDictionary dictionary];
 
[reqDict setObject:methodName forKey:@"method"];
 
[reqDict setObject:parameters forKey:@"params"];
 
[reqDict setObject:identificator forKey:@"id"];
 
//RPC JSON
 
NSString* reqString = [NSString stringWithString:[reqDict JSONRepresentation]];

We should note 3 arguments we’re posting to the service – method, params and id. Method is RPC method name as declared in JSON RPC web service. Params are arguments this method requires and ‘id’ is the call identifier which RPC call returns when sending back response and it’s used to link the response to the request in case you’re sending out multiple requests. In our case, the method name is ‘HelloWorld’ without arguments and as the identifier we’ll just put 1.

So now we create NSURLRequest and NSURLConnection using this reqString. This is the main part of code so pay attention.

 
//Request
 
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
 
NSData* requestData = [NSData dataWithBytes:[reqString UTF8String] length:[reqString length]];
 
//prepare http body
 
[request setHTTPMethod: @"POST"];
 
[request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
 
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
 
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
 
[request setHTTPBody: requestData];

First we create a mutable url request, set it’s HTTP method to “POST” and fill out other HTTP specific header fields. Finally we set our JSON request string as HTTP body.

Now we simply create NSURLConnection, assign a delegate to it and wait for our data.

 
urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
 
[request release];

The delegate part of the calling object has these methods defined.

#pragma mark -
#pragma mark NSURLConnection delegate
 
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
	NSLog(@"Did receive response: %@", response);
 
	[webData release];
	webData = [[NSMutableData alloc] init];
}
 
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
	assert(webData != nil);
	[webData appendData:data];
}
 
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
	[webData release];
	webData = nil;
	[urlConnection release];
	urlConnection = nil;
 
	UIApplication* app = [UIApplication sharedApplication];
	app.networkActivityIndicatorVisible = NO;
 
	//notify
	[delegate loadingFailed:[error localizedDescription]];
}
 
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
	[urlConnection release];
	urlConnection = nil;
 
	UIApplication* app = [UIApplication sharedApplication];
	app.networkActivityIndicatorVisible = NO;
 
	//DO something with webData
	[delegate dataLoaded:webData];
 
	[webData release];
	webData = nil;
}

Once the connection gets a response we create NSData (webData) and we append bytes to it in didReceiveData callback. In the end we either get didFailWithError or didFinishLoading and take actions accordingly.

Finally, the app would return something like this when launched.

iPhone calling JSON RPC web service

iPhone JSON RPC

For your convenience, I have attached XCode project for download. Please note that this is an example only and should be treated as such, I don’t provide guarantee of any kind for this code.

JSON RPC iOS example project

Consuming ASP .NET web services in iOS part1

Since, at the time of my writing, iOS SDK does not natively support SOAP WebServices many have found different ways to consume these web services. Some of them include manually making HTTP requests and parsing response, using WSDL to ObjectiveC generators and more. One of the convenient ways I found when it comes to RPC is to combine the niceness of ASP .NET with JSON-RPC which can be accessed in iOS easily. So, let’s begin creating an iOS friendly ASP .NET web service.

The framework which makes this possible is Jayrock. Jayrock is a modest and an open source (LGPL) implementation of JSON and JSON-RPC for the Microsoft .NET Framework, including ASP.NET.

Let’s see how we can make this work. First, let’s create a simple HelloWorld() web service. Open up Visual Studio and create ASP .NET web project (or any other suitable type).

Visual Studio New Web Application Dialog

Create New Application

Add a generic handler to your app and call it whatever you like.

Visual Studio Add Handler

Add generic handler

Now we need to reference Jayrock library, so right click your project and “Add Reference”, browse to find Jayrock.dll and Jayrock.Json.dll and add references to them. Once you’ve finished that, we can continue to build our web service.

Open the handler you’ve created and modify the class to look something like this:

[csharp]public class my_service : Jayrock.JsonRpc.Web.JsonRpcHandler
{
	[Jayrock.JsonRpc.JsonRpcMethod("HelloWorld")]
	public string HelloWorld()
	{
		return "Hi iOS, this is ASP.NET!";
	}
}[/csharp]

  And now we’re ready. Try out this service in your browser, you should be able to see its description and test page. You can also test to see if it actually works, like this.
Jayrock RPC page

Jayrock RPC

If you see this, we’re completed JSON RPC web service in C# ASP .NET. In the next part of this blog, we’ll create an iOS app which will consume this service. Stay tuned!