Accessing a Restful service is actually no big deal, but it took me quite a while to figure out some details. So here’s a short description of it.
First of all, we build a small Zend Rest Service with two ping methods and save it as MyRestService.php.
<?php
class MyRestService {
/**
* @param string $name
* @return string
*/
public function ping($name) {
return 'Hello ' . $name;
}
}
require 'Zend/Rest/Server.php';
$server = new Zend_Rest_Server ( );
$server->setClass ( 'MyRestService' );
$server->handle();
require 'Zend/Rest/Server.php';
$server = new Zend_Rest_Server ( );
$server->setClass ( 'MyRestService' );
$server->handle();
We can now allready access our service with the browser by entering the URL http://localhost/MyRestService.php?method=ping&name=Simon. The service returns the answer as XML.
<MyRestService generator="zend" version="1.0"> <ping> <response>Hello Simon</response> <status>success</status> </ping> </MyRestService>
As you can see the call as well as the answer are really straightforward and easy to unserstand. We’re going now to access our service from C#.
public void CallRest() {
string methodName = "ping";
string name = "Simon";
// Build the URL with the parameters
StringBuilder sb = new StringBuilder();
sb.Append("http://localhost/MyRestService.php");
sb.Append(string.Format("?method={0}", HttpUtility.UrlEncode(methodName)));
sb.Append(string.Format("&name={0}", HttpUtility.UrlEncode(name)));
// Download the service answer as string
Uri address = new Uri(sb.ToString());
WebClient serviceClient = new WebClient();
serviceClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(serviceClient_DownloadStringCompleted);
serviceClient.DownloadStringAsync(address);
}
private void serviceClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) {
try {
// Check for service error
if (e.Error != null)
throw e.Error;
// Load the result as XML for easy Linq access
XElement elem = XElement.Parse(e.Result);
// Check the return status
string status = (string)(from el in elem.Descendants("status") select el).First();
if ("success".Equals(status)) {
// Get the response
string resp = (string)(from el in elem.Descendants("response") select el).First();
MessageBox.Show(resp, "The Restservice says...", MessageBoxButton.OK);
} else if ("failed".Equals(status)) {
// Get the error message
string errmsg = (string)(from el in elem.Descendants("message") select el).First();
throw new Exception(errmsg);
} else {
throw new Exception(string.Format("Unknown Rest status: {0}", status));
}
} catch (Exception exp) {
MessageBox.Show(exp.ToString(), "Error", MessageBoxButton.OK);
}
}
When we run the code a MessageBox with the service response should pop up.
So, this was the part I figured out quite fast. But what happens if you change the service function so somewhat like this:
/**
* @param array $names
* @return string
*/
public function ping($names){
return $names['p2'];
}
It took me some time to figure out that the answer is quite easy. Let’s change the C# function to fit the array parameter.
public void CallRest() {
string methodName = "ping";
string[] names = { "Simon", "John", "Bill" };
// Build the URL with the parameters
StringBuilder sb = new StringBuilder();
sb.Append("http://localhost/MyRestService.php");
sb.Append(string.Format("?method={0}", HttpUtility.UrlEncode(methodName)));
for (int i = 0; i < names.Length; i++)
sb.Append(string.Format("&names[p{0}]={1}", i, HttpUtility.UrlEncode(names[i])));
// Download the service answer as string
Uri address = new Uri(sb.ToString());
WebClient serviceClient = new WebClient();
serviceClient.DownloadStringCompleted += new
DownloadStringCompletedEventHandler(serviceClient_DownloadStringCompleted);
serviceClient.DownloadStringAsync(address);
}
As you can see I just add the parameter as everybody would access an array. And once again, you can also access the service direct with your browser unter the URL http://localhost/MyRestService.php?method=ping&names[p0]=Simon&names[p1]=John&names[p2]=Bill