So I went through the very basics last time, and while I'm gonna keep it simple, I'm not gonna do a newbie style step-by-step like I did before. For this tutorial I'm going to create a little media library sample for you to work with to show how typed object data can be received via Fluorine.
To start out, download and install the latest version of the Fluorine Gateway. Zoli made some upates since my last posting that will allow your program to run on a shared hosting website. Worked for my last sample anyway. This also goes to show that the folks at The Silent Group are extremely helpful when issues arise with Fluorine. I don't think the guy sleeps.
Setting up the project folder structure
Start out by setting up a project folder structure by creating a master project folder with a Dot Net and a Flex folder in it. Mine is D:\Projects\Flex\Fluorine Flex 2.
Setting up the Visual Studio project
This time we'll use the new Fluorine ASP.NET Web Application template. Fire up Visual Studio and create a new web site project. Select the Fluorine template and set up a virtual web directory that points to the project folder's Dot Net folder. For me it's http://localhost/fluorineflex2/. If you tried the last tutorial, you'll quickly figure out that this template saves you a LOT of steps. Once you've created the project, you only have to do one thing to configure Fluorine.
Configuring the Fluorine Gateway in Visual Studio
Open the WEB-INF/flex/services-config.xml file and modify the endpoint node to point to the virtual web directory location of Gateway.aspx. In my case it was http://localhost/fluorineflex2/Gateway.aspx. You should be able to copy and paste this url into a browser and a blank page should load without any error messages.
UPDATE
I was not aware of this, but I recieved an email from Zoli at The Silent Group and he notified me that the uri attribute does not have to change as long as the context root remains the same on the server you are deploying to. In this case if I'm developing on http://localhost/fluorineflex2/Gateway.aspx, and deploying to http://www.darbymedia.com/fluorineflex2/Gateway.aspx, then I can leave the uri attribute as it's default: http://{server.name}:{server.port}/{context.root}/Gateway.aspx. You should still however be able to copy and past the actual URL of the Gateway.aspx file and the blank page should load without any errors. It's a quick way to check for issues if you are not getting the results you want.
Setting up the Flex project
Start Flex Builder 2 and create a new Flash Data Service Project with the Root folder pointing to the Dot Net folder of your project directory (D:\Projects\Flex\Fluorine Flex 2\Dot Net) and the Root URL pointing to the virtual web directory for the Visual Studio project (http://localhost/fluorineflex2/). The Context root should be the final bit of the virtual web path (/fluorineflex2). Enter the project name (fluorineflex2) and use the Flex directory of your project folder as the location of your Flex project files (D:\Projects\Flex\Fluorine Flex 2).
If you need help with any of the stuff above please check out the previous tutorial.
Creating a C# compact disc value object class
To start out we'll need a value object on the server side to pass back to Flex when requested. Let's create a class called CompactDiscVO that has the properties, artist, title, and year.
C#:
-
using System;
-
-
namespace com.darbymedia.medialibrary.vo
-
{
-
public class CompactDiscVO
-
{
-
public string artist;
-
public string title;
-
public string year;
-
-
public CompactDiscVO(){}
-
}
-
}
Creating a Fluorine Gateway service class
To start out, create a basic service that you can point to with your Flex RemoteObject. We'll also include a method called getCDVO that will instantiate and return a CompactDiscVO object.
C#:
-
using System;
-
using System.Web;
-
using com.darbymedia.medialibrary.vo;
-
-
namespace com.darbymedia.medialibrary.service
-
{
-
public class MediaLibraryService
-
{
-
public MediaLibraryService() { }
-
-
public CompactDiscVO getCDVO()
-
{
-
CompactDiscVO cd =
new CompactDiscVO
();
-
-
cd.artist = "Redd Kross";
-
cd.title = "Third Eye";
-
cd.year = "1990";
-
-
return cd;
-
}
-
}
-
}
Now we can move on to Flex Builder.
Creating a corresponding Actionscript compact disc value object
In Flex Builder 2 create a CompactDiscVO class. I've added a toString() method for demonstration purposes (good for debugging too!). Note that the namespace/package path and class name are the same. This is not absolutely necessary but makes sense here.
ACTIONSCRIPT:
-
package com.darbymedia.medialibrary.vo
-
{
-
public class CompactDiscVO extends Object
-
{
-
public var artist:String;
-
public var title:String;
-
public var year:String;
-
-
public function CompactDiscVO(){}
-
-
public function toString():String
-
{
-
var s:String = "[CompactDiscVO]"
-
-
s += "\nArtist: " + artist;
-
s += "\nTitle: " + title;
-
s += "\nYear: " + year;
-
-
return s;
-
}
-
}
-
}
Building the main MXML application file
This time I've decided to use Actionscript only for my RemoteObject file. This way you can compare with the previous tutorial which used an MXML RemoteObject if you want. On creationComplete, the initApp() method instantiates the remote object with the destination, which is the destination name used in the services-config.xml file, the source, which is the namespace and class path of the C# service class we created, and listeners for result and fault events. Here is the MXML:
XML:
-
<?xml version="1.0" encoding="utf-8"?>
-
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApp()">
-
<mx:Script>
-
<![CDATA[
-
import com.darbymedia.medialibrary.vo.CompactDiscVO;
-
import mx.rpc.events.FaultEvent;
-
import mx.rpc.events.ResultEvent;
-
import mx.rpc.remoting.RemoteObject;
-
-
private var ro:RemoteObject;
-
-
private function initApp():void
-
{
-
ro = new RemoteObject();
-
ro.destination = "fluorine";
-
ro.source = "com.darbymedia.medialibrary.service.MediaLibraryService";
-
ro.addEventListener(ResultEvent.RESULT, roResult);
-
ro.addEventListener(FaultEvent.FAULT, roFault);
-
ro.getCDVO();
-
}
-
-
private function roResult(event:ResultEvent):void
-
{
-
trace(event.result);
-
trace(event.result.artist);
-
var cd:CompactDiscVO = event.result as CompactDiscVO;
-
trace(cd);
-
}
-
-
private function roFault(event:FaultEvent):void
-
{
-
trace("roFault(event)");
-
trace(event.fault.faultCode);
-
trace(event.fault.faultString);
-
trace(event.fault.faultDetail);
-
}
-
]]>
-
</mx:Script>
-
</mx:Application>
At this point we're calling the getCDVO method on the service immediately. roResult will trace out information to the console when run in debug mode. Go ahead and do that and you'll get the following:
[SWF] /fluorineflex2/fluorineflex2/FluorineFlex2-debug.swf - 628,788 bytes after decompression
[object Object]
Redd Kross
null
Interesting. In roResult, our first trace of event.result gives us [object Object] so obviously we're getting an Object type, but our CompactDiscVO.toString() method is not kicking in. Our second trace of the event.result.artist property, Redd Kross, shows that our data came through but when we try to put it into a typed variable as CompactDiscVO for our third trace we get null. So we are getting data back but it's not typed correctly. It's just a generic Object with properties.
To force the correct mapping you have use the flash.net.registerClassAlias() method. You pass it the full namespace and class name of the server side class as a string and the Actionscript class you want it to map to, like so:
flash.net.registerClassAlias("com.darbymedia.medialibrary.vo.CompactDiscVO", CompactDiscVO);
I put this in the initApp() method.
Now our MXML looks like this:
XML:
-
<?xml version="1.0" encoding="utf-8"?>
-
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApp()">
-
<mx:Script>
-
<![CDATA[
-
import com.darbymedia.medialibrary.vo.CompactDiscVO;
-
import mx.rpc.events.FaultEvent;
-
import mx.rpc.events.ResultEvent;
-
import mx.rpc.remoting.RemoteObject;
-
import flash.net.registerClassAlias;
-
-
private var ro:RemoteObject;
-
-
private function initApp():void
-
{
-
flash.net.registerClassAlias("com.darbymedia.medialibrary.vo.CompactDiscVO", CompactDiscVO);
-
-
ro = new RemoteObject();
-
ro.destination = "fluorine";
-
ro.source = "com.darbymedia.medialibrary.service.MediaLibraryService";
-
ro.addEventListener(ResultEvent.RESULT, roResult);
-
ro.addEventListener(FaultEvent.FAULT, roFault);
-
ro.getCDVO();
-
}
-
-
private function roResult(event:ResultEvent):void
-
{
-
trace(event.result);
-
trace(event.result.artist);
-
var cd:CompactDiscVO = event.result as CompactDiscVO;
-
trace(cd);
-
}
-
-
private function roFault(event:FaultEvent):void
-
{
-
trace("roFault(event)");
-
trace(event.fault.faultCode);
-
trace(event.fault.faultString);
-
trace(event.fault.faultDetail);
-
}
-
]]>
-
</mx:Script>
-
</mx:Application>
Run this in debug mode and you can see that our first trace of event.result gives us the toString() output of the CompactDiscVO class, our second trace of event.result.artist gives us Redd Kross, and our third trace of the typed variable, cd, prints out not null, but the toString() output as well! Pretty cool!
Doing something with the content
Now let's put this data into display items. I've added some labels and input fields to hold the data, a button to trigger the return, and an alert for any faults. I've put the call to the remote object's getCDVO in the button's click handler this time. Check it out:
XML:
-
<?xml version="1.0" encoding="utf-8"?>
-
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApp()">
-
<mx:Script>
-
<![CDATA[
-
import mx.controls.Alert;
-
import flash.net.registerClassAlias;
-
import com.darbymedia.medialibrary.vo.CompactDiscVO;
-
import mx.rpc.events.FaultEvent;
-
import mx.rpc.events.ResultEvent;
-
import mx.rpc.remoting.RemoteObject;
-
-
private var ro:RemoteObject;
-
-
private function initApp():void
-
{
-
flash.net.registerClassAlias("com.darbymedia.medialibrary.vo.CompactDiscVO", CompactDiscVO);
-
-
ro = new RemoteObject();
-
ro.destination = "fluorine";
-
ro.source = "com.darbymedia.medialibrary.service.MediaLibraryService";
-
ro.addEventListener(ResultEvent.RESULT, roResult);
-
ro.addEventListener(FaultEvent.FAULT, roFault);
-
}
-
-
private function btnGet_Click(event:Event):void
-
{
-
ro.getCDVO();
-
}
-
-
-
private function roResult(event:ResultEvent):void
-
{
-
var cd:CompactDiscVO = event.result as CompactDiscVO;
-
txtArtist.text = cd.artist;
-
txtTitle.text = cd.title;
-
txtYear.text = cd.year;
-
}
-
-
private function roFault(event:FaultEvent):void
-
{
-
trace("roFault(event)");
-
trace(event.fault.faultCode);
-
trace(event.fault.faultString);
-
trace(event.fault.faultDetail);
-
-
Alert.show(event.fault.faultDetail,"Fault Event");
-
}
-
-
]]>
-
</mx:Script>
-
-
<mx:Label text="Compact Disc" x="10" y="10"/>
-
<mx:Label text="Artist:" x="10" y="35"/>
-
<mx:TextInput x="56" y="35" id="txtArtist"/>
-
<mx:Label text="Title:" x="10" y="70"/>
-
<mx:TextInput x="56" y="70" id="txtTitle"/>
-
<mx:Label x="10" y="105" text="Year:"/>
-
<mx:TextInput x="56" y="105" id="txtYear"/>
-
<mx:Button x="140" y="135" label="Get Data" id="btnGet" click="btnGet_Click(event)"/>
-
</mx:Application>
Check it out here. Sending is easy...next time we'll do that.