This post presents an example that is one baby step more complicated that my first post, “Hello, World!”, in order to describe WebORB’s way of handling server-side data types.
In the “Hello, World!” app, the client’s call to the server returned (asynchronously) a simple data type: a string. It’s more common to request more-complex data — personnel records, weather data, astronomical info, marked-up medical images, or whatever.
In this example, our client’s request will return such “complex data.” It won’t be terribly complex, though, so don’t be frightened.
Here’s the first cut at our server-side code (in C#, for Visual Studio):
using System;
using System.Web;
namespace ComplexDataServer
{
public class ComplexDataService
{
public ComplexData getComplexData()
{
ComplexData result = new ComplexData();
return result;
}
}
public class ComplexData
{
string helloString = "Hello, World!";
string now = DateTime.Now.ToString();
double r = (new Random()).NextDouble();
}
}
Proper code would have getters and setters…but then, proper code probably wouldn’t be setting hard-coded values in ComplexData’s constructor, either. I’m keeping this simple.
This code compiles cleanly, with no errors or warnings, so it looks Good To Go. We can deploy it into WebORB for .NET by copying its DLL into WebORB’s \bin directory, as described in my earlier “Hello, World!” post.
We can verify that the deployed code works as intended by invoking it from WebORB for .NET’s management console, as shown below:
Wait a minute…what did the method invocation return, exactly? Let’s look closer:

That doesn’t look right. WebORB doesn’t know how to interpret the data returned by the service.
Well, gee, I’m new at this, so maybe I just don’t get it, so I’ll go ahead and generate the client-side code anyway, load it up into Flash Builder, and hope for the best.

Clicking the “Download Code” button generates the weborb.codegen file for this service, which I import into Flash Builder..mostly, but not entirely, as I did in “Hello, World!”. This time, when Flex’s Import… process displays its “Choose Flex SDK Version” dialog, I’m going to click the “Use Flex 3 Compatibility Mode” checkbox on the import dialog. That way, the generated code will “just work” with Flash SDK 4, even though it was generated for Flash SDK 3.x.
In Flash Builder, the generated project is shown in the Package Explorer as shown above. It’s structure is identical to the “Hello, World!” project:
- In the default package
- main.mxml
- In the [Service] folder (where) [Service] is the name of the DLL/namespace of the server-side code)
- [Service].as
- [Service]Model.as
Seeing the same structure is rather comforting — like seeing an old friend’s face in an unfamiliar crowd.
main.mxml looks like this:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="onLoad()">
<mx:Script>
<![CDATA[
public function onLoad():void
{
}
]]>
</mx:Script>
</mx:Application>
…which is pretty much the same as it looked in “Hello, World!”.
As before, we’ll go into the [Service].as file (in this case, ComplexDataService.as), copy out the code that’s in its header comment, paste it into main.mxml’s CDATA block, and update the onLoad() function to have the serviceProxy call the remote function (in this case, serviceProxy.getComplexData()). The result of all that looks like this:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="onLoad()" width="275" height="298">
<mx:Script>
<![CDATA[
import ComplexDataServer.ComplexDataService;
import ComplexDataServer.ComplexDataServiceModel;
[Bindable]
var model:ComplexDataServiceModel = new ComplexDataServiceModel();
var serviceProxy:ComplexDataService = new ComplexDataService( model );
public function onLoad():void
{
// make sure to substitute foo() with a method from the class
serviceProxy.getComplexData();
}
]]>
</mx:Script>
</mx:Application>
There’s only one problem: the code won’t compile. The compiler barfs error #”1046: Type was not found or was not a compile-time constant: ComplexData. ComplexDataServiceModel.as.” Well, fooey.
Here’s ComplexDataServiceModel.as:
package ComplexDataServer
{
[Bindable]
public class ComplexDataServiceModel
{
public var getComplexDataResult:ComplexData;
}
}
By golly, the type of ComplexDataServiceModel’s getComplexDataResult property is ComplexData, and ComplexData is defined…where, exactly? It was defined over in the C# code on the server, but WebORB doesn’t seem to know about that.
WTF? Why did WebORB understand the “Hello, World!” service’s result type/class/whatever, but not ComplexData’s?
The answer is, in brief, that the “Hello, World!” service’s result type was simple — that is, it was of a single instance of a single type well-known to the type systems of both C# and Flex, so WebORB could shoot it right over. ComplexDataService’s result isn’t a simple type; it’s a complex type. It’s a user-defined class, containing a couple of strings and a double-precision real number. That may not be super-complicated, but it isn’t “simple,” either.
How can we make our Flex-based client aware of the type/class/structure of our server-side data? The fix is rather arcane, due to a quirk of Flex. Fortunately, WebORB handles most of the complexity.
The thing is, that the [Service] result’s class, in this case ComplexData, must have its properties declared to be public. Like so:
public class ComplexData
{
public string helloString = "Hello, World!";
public string now = DateTime.Now.ToString();
public double r = (new Random()).NextDouble();
}
- Add those three “public” keywords,
- build the ComplexDataServer.DLL,
- drag it to WebORB’s \bin directory (replacing the previous version),
- launch WebORB’s management console,
- refresh its list of .NET Assemblies,
- find the revised ComplexDataServer service,
- walk down the hierarchical menu to find the getComplexData() function,
- click the “Invoke” button, and
- voila!
…you ought to see a service result that looks like this:

[Of course, if you do this, the values you see for "now" and "r" will be different, as "now" is the current DateTime and "r" is a random number.]
Let’s generate a new project from the revised ComplexDataServer, import into Flex Builder as ComplexDataService2, and take a look at it.

Its structure looks different. There’s a new “vo” package, and two new files — ComplexData.as and DataTypeInitializer.as.
Let’s look at ComplexData.as first:
package ComplexDataServer.vo
{
import flash.utils.ByteArray;
import mx.collections.ArrayCollection;
[Bindable]
[RemoteClass(alias="ComplexDataServer.ComplexData")]
public class ComplexData
{
public function ComplexData(){}
public var helloString:String;
public var now:String;
public var r:Number;
}
}
Well, that makes sense. It’s a re-declaration, in ActionScript, of the ComplexData class defined in C# on the server. Clearly, WebORB must do some type-mapping magic here — for example, mapping C#’s double to Flash’s Number — but the code above makes sense.
That solves Mystery #1: getting server-side complex data type definitions into client-side Flex code via WebORB. The trick is to ensure that all of the properties (that you care about) are declared t be “public”.
But…what’s this “DataTypeInitializer” thingy?
Let’s look at its code:
package ComplexDataServer
{
import ComplexDataServer.vo.ComplexData;
public class DataTypeInitializer
{
public function DataTypeInitializer()
{
new ComplexDataServer.vo.ComplexData();
}
}
}
WTF? All this code does is
- define a new class, DataTypeInitializer, with a constructor that
- allocates a new object of class ComplexData…and throws it away.
It gets weirder. Look at the onLoad() function in the new project’s main.mxml file:
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="onLoad()">
<mx:Script>
<![CDATA[
import ComplexDataServer.DataTypeInitializer;
public function onLoad():void
{
new DataTypeInitializer();
}
]]>
</mx:Script>
</mx:Application>
Once again, all it does is allocate something that is immediately thrown away — in this case, an object of class DataTypeInitializer.
That is,
- onLoad() allocates a DataTypeInitializer
- which allocates a ComplexData
- and then throws the ComplexData away
- and then throws away the DataTypeInitializer.
That’s a whole lot of allocation, for no effect…unless the allocations have an important side-effect. As, indeed, they do.
Flex has this nasty/useful tendency to strip out the definitions of all types/classes that are never instantiated.
- On the one hand, this is useful, because keeps run-time code as small as possible.
- On the other hand, it’s nasty, because it forces developers to perform Stupid Programming Tricks to keep their class/type definitions from being stripped.
WebORB generates the code you need — not just the code you need to define your server-side types on the client, but also the code you need to keep Flex from stripping those definitions out. WebORB does Stupid Programming Tricks so that you don’t have to.
Which solves Mystery #2. Just import all the code that WebORB generates, and call “new DataTypeInitializer();” in your application’s initializer. DataTypeInitializer()’s constructor will contain allocations of ALL of your server-side data types, to ensure that none of them get stripped by Flex.
Another WebORB programming mystery exposed!
To finish up the client side of the ComplexDataService2 app, here’s the final version of its main.mxml:
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
width="354" height="184"
initialize="onLoad()">
<mx:Script>
<![CDATA[
import ComplexDataServer.DataTypeInitializer;
import ComplexDataServer.ComplexDataService;
import ComplexDataServer.ComplexDataServiceModel;
[Bindable]
private var model:ComplexDataServiceModel
= new ComplexDataServiceModel();
private var serviceProxy:ComplexDataService
= new ComplexDataService( model );
public function onLoad():void
{
new DataTypeInitializer();
// initialize the model
serviceProxy.getComplexData();
}
]]>
</mx:Script>
<mx:Panel x="10" y="10" width="332"
height="130"
layout="absolute"
title="ComplexData">
<mx:Label x="10" y="10" text="hello" fontWeight="bold"/>
<mx:Label x="10" y="36" text="now" fontWeight="bold"/>
<mx:Label x="10" y="62" text="r" fontWeight="bold"/>
<mx:Label x="49" y="9" text="{model.getComplexDataResult.helloString}"/>
<mx:Label x="49" y="35" text="{model.getComplexDataResult.now}"/>
<mx:Label x="49" y="61" text="{model.getComplexDataResult.r}"/>
</mx:Panel>
<mx:Button x="144" y="152"
label="Again"
click="{serviceProxy.getComplexData();}"/>
</mx:Application>
Notice that:
- The UI elements bind to the model’s properties.
- The “Again…” button’s click handler, and the application’s onLoad() method, both call “serviceProxy.getComplexData()” to update the service’s data model via a call to the server.
[You can find a concise presentation of this blarticle's key points here, in WebORB's formal documentation.]


