Web Service Recipes
- Recipe 2.1 – Getting Started with XML-RPC
- Recipe 2.2 – Requests with XML-RPC
- Recipe 2.3 - Authentication and XML-RPC
- Recipe 2.4 – Getting Started with REST
- Recipe 2.5 – REST Service Class
Recipe 2.1 – Getting Started with XML-RPC
Problem: You want to connect to a XML-RPC enabled weblog to get you posts or even just to connect.
Solution: Pick up this RPC ActionScript 3 library from Google code, you have to fix one thing inside one of the classes its on the Wiki, its a quick fix that we have to do because they haven’t updated it yet, and you will be ready to go. Here a simple call to WordPress’s XML-RPC.
Since we are going to make some calls to WordPress lets take a look at one method that we are going to call, examine it and see how we can make this call from Flex.
Below is the "blogger.getUserInfo" method, the method says that it excepts 2 parameters, a username and a password. Here is the function.
/* blogger.getUsersInfo gives your client some info about you, so you don't have to */
function blogger_getUserInfo( $args )
{
$this->escape ( $args );
$user_login = $args [];
$user_pass = $args [];
if ( ! $this->login_pass_ok ( $user_login, $user_pass ) )
{
return $this->error;
}
set_current_user( , $user_login )
if ( ! current_user_can ( 'edit_posts' ) )
return new IXR_Error( , __( 'Sorry, you do not have access to user data on this blog.' ) );
do_action ( 'xmlrpc_call', 'blogger.getUserInfo' );
$user_data = get_userdatabylogin ( $user_login );
$struct = array (
'nickname' => $user_data->nickname, 'userid' => $user_data->ID, 'url' => $user_data->user_url, 'lastname' => $user_data->last_name, 'firstname' => $user_data->first_name
);
return $struct;
}
But if we use this code below to call this method from Flex, to the average Joe it looks ok right?
/**
* blogger.getUserInfo
*
* @args username password
*/
private function getUserInfo():void
{
service.call( "blogger.getUserInfo", txt_username.text, txt_password.text );
}
Wrong, we have to insert some jumble code I guess before our username and password for the call to actually work. I think it has something to do with blogger API using and apikey before or something.
So we use this code instead.
/**
* blogger.getUserInfo
*
* @args username password
*/
private function getUserInfo()void
{
service.call( "blogger.getUserInfo", "", txt_username.text, txt_password.text );
}
For WordPress methods they are straight forward, take this for example to get the users blogs:
Discussion: Now that we have figured out why the blogger methods weren’t working we can start creating a class to be able to call all of the methods that are defined inside the XML-RPC script on our server. I’ll leave that to you though.
Recipe 2.2 – Requests with XML-RPC
Problem: You want to authenticate the user before making calls, well you just want to send over some arguments and stuff.
Solution: Create some forms and code up some new functions to do exactly what you need.
Here are some functions that will get you prepared to send and receive data.
import mx.utils.Base64Encoder;
import mx.utils.ArrayUtil;
import mx.collections.ArrayCollection;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.AsyncToken;
import mx.controls.Alert;
//Our data that is going to be returned
[Bindable] private var returnedData:ArrayCollection;
//Our website endpoint where WordPress is installed at
[Bindable] private var wordpressEndpoint:String = "http://flexpress.jonniespratley.com";
//Our service variable that is a xmlrpc object
private var service:XMLRPCObject;
private function init():void
{
//Create a new service
service = new XMLRPCObject();
//Specify the endpoint
service.endpoint = wordpressEndpoint;
//We know what destination we need to access
service.destination = "/xmlrpc.php";
//Set a fault handler
service.addEventListener( FaultEvent.FAULT, onFault );
//And set a result handler
service.addEventListener( ResultEvent.RESULT, onResult );
}
/*******************************************
* wp.getUsersBlogs
* @args user_name, user_pass
********************************************/
private function getUsersBlogs():void
{
service.call("wp.getUsersBlogs", txt_username.text, txt_password.text)
}
/*******************************************
* blogger.getUserInfo
* @args fake app id, user_name, user_pass
********************************************/
private function getUserInfo():void
{
service.call( "blogger.getUserInfo",
"43243423",
txt_username.text,
txt_password.text );
}
/*******************************************
* blogger.getRecentPosts
* @args blog_ID, user_login, user_pass, num_posts
********************************************/
private function getRecentPosts():void
{
service.call( "blogger.getRecentPosts",
"43243423",
txt_blogid.value,
txt_username.text,
txt_password.text,
txt_count.value );
}
/*******************************************
* onResult/ Populates the dp:Array
********************************************/
private function onResult( event:ResultEvent ):void
{
returnedData = new ArrayCollection( ArrayUtil.toArray( event.result ) );
}
/*******************************************
* onFault/ Displays the FaultString
********************************************/
private function onFault ( event:FaultEvent ):void
{
Alert.show( event.fault.faultString,event.fault.faultCode );
}
And here is the view that will make the calls and show the data.
<]mx:HDividedBox width="100%" height="100%">
<]mx:Accordion width="225" height="100%">
<]mx:VBox label="User Infomation" width="100%" height="100%" styleName="sideBox">
<]!--Wordpress Username-->
<]mx:Label
text="Username:"
fontWeight="bold"/>
<]mx:TextInput id="txt_username"
text="username"/>
<]!--Wordpress Password-->
<]mx:Label
text="Password:"
fontWeight="bold"/>
<]mx:TextInput id="txt_password"
displayAsPassword="true"
text="password"/>
<]!--Wordpress Website-->
<]mx:Label
text="Your Website:"
fontWeight="bold"/>
<]mx:TextInput id="txt_website"
text="{ wordpressEndpoint }"/>
<]/mx:VBox>
<]mx:VBox
label="Methods without Parameters"
width="100%"
height="100%">
<]!--GetUsersBlogs-->
<]mx:Button
click="getUsersBlogs()"
label="Get Users Blogs"
width="100%"/>
<]!--GetUserInfo-->
<]mx:Button
click="getUserInfo()"
label="Get User Info"
width="100%"/>
<]/mx:VBox>
<]mx:VBox
label="Methods with Parameters"
width="100%"
height="100%">
<]!--What Blog-->
<]mx:Label
text="What Blog"
fontWeight="bold"/>
<]mx:NumericStepper id="txt_blogid"
maximum="5"
minimum="1"/>
<]!--How Many-->
<]mx:Label
text="How Many"
fontWeight="bold"/>
<]mx:NumericStepper id="txt_count"
maximum="25"
minimum="5"/>
<]!--GetRecentPosts-->
<]mx:Button
click="getRecentPosts()"
label="Get Recent Posts"
width="100%"/>
<]/mx:VBox>
<]/mx:Accordion>
<]!--Sandbox Results-->
<]mx:DataGrid id="dg_returneddata"
height="100%"
width="100%"
dataProvider="{ returnedData }"/>
<]/mx:HDividedBox>
Discussion: Now that you got the hang of things, you can start making a full service class that will allow creating and editing posts, pages, and categories.
Recipe 2.3 – Authentication and XML-RPC
Problem: Ok I got the hang of this XML-RPC thing, but what if my server requires authentication before making any requests for data? What am I suppose to do?
Solution: Simple, we will slightly modify the calls to our service by adding authentication headers with the call, encrypting the username and password with every request on the server, supplying its requirements and receiving our data.
We are going to be using the same as3rpc library as before and for the service we are going to be using the big social networking site Buzznet. You need an apikey to make calls so grab one and you will be set.
First add a xmlrpc object to your view like this.
//Fixing
What we do here is first create a variable that is type Base64Encoder and then we tell it to encode the values from the username input plus a ":" and then the values of the password input. This makes one string with a username password seperated by a colon to add to our header.
Then we set up the method, the content type, and create the header, we then set the Authorization: "Basic" with our encoded credentials to the header. Finishing it off by sending a request to get online users. And we do get a response and this is what we do with that.
And now to show the data.
//Fixing
Discussion: Wow we just about can do anything now, XML-RPC, authentication, man we are on top of the world right now!
Recipe 2.4 – Getting Started with REST
Problem: I want to make some RESTful calls to an API, but I don’t know where to start.
Solution: Create a function to test our REST calls to the 30boxes API and see what happens.
All calls to 30boxes must have a APIKEY, also for user data you must send a token that the user has been given allowing your application to access the users data. We will take care of that next.
First lets call one of there sample methods "test.Ping".
We need to set up our calls and make it easy to send out requests so lets use the following.
Discussion: Ok we start out by setting up our request the we create a function called sendQuery, and what this function does is it takes the service variable and builds it up so that when other functions call on this sendQuery function the passed arguments are being used to send the query and handle the result.
When we create the testPing function we are requiring one argument which is a apikey and then creating a variable type URI so we can set up name/value pairs for the call. We declare the method and the name and the "test.Ping" as the value, then since this method only requires an apikey parameter we set up that name/value pair with "apiKey" and the value aApiKey.
Once we have that set up we call the sendQuery function and filling the arguments with our URI and a result function.
//Fixing
Recipe 2.5 – REST Service Class
Problem: We are set up for making calls, and familiar with REST. Now can we see how to make more calls to 30boxes.
Solution: We will create a small class that will be the container for all of our calls we want to make to 30boxes.
Create a new class called T30boxesResultEvent.as enter the following
I like using interfaces so lets create a new interface called IT30boxesService.as
//Fixing
Our interface is just going to hold the functions that we want to call, this will be a very small interface for this example, but when we choose to extend the service class we must change the interface before the class because when a class implements a interface it basically signs a contract to include all of the functions defined inside of the interface. But the interface holds no functionality, its like guidelines for classes that choose to implement it.
Functions Explained
- testPing; This function requires an API Key before sending
- userAuthorize; This function returns a string, in that string will be all of the necessary elements to redirect your use to 30boxes.com were they will get a token. This token basically says ok I know that this application is accessing my data.
- userGetAllInfo; This function requires an API Key and the token from the user, returning all information about that user who’s token was sent.
Then we need to an service class that will implement our interface. This class is where we bring functionality to the functions we defined inside our interface.
Here is a portion of our T30boxesService.as:
//Fixing
This class is the holder of some methods that are on 30boxes.com, so we are bundling them up into a class for easy calling. When a function is called, we wait for a result or fault from the call, once we get that result, we dispatch one of our event classes depending on what the result was. If it was successful we dispatch a "T30boxesResultEvent.ok" we are letting whoever is listing for this event know that it happened and here is the data.
So when it comes to putting this all together to make it work, we can create a simple API Tester component that we can try out our new services. Here is the code for APITester.mxml:
I have included my API Key for you to test it out, please don’t abuse it
. But this should have you up and running with some good calls to 30boxes.com API.
Discussion:
That wasn’t to bad was it, now we are going to have to create a function to parse that XML data coming back. That is where you help me and show me how you do that, because I simply can’t figure it out.



