Avg. Rating 3.3
Tags:



Problem

I want to be able to call methods on a C# class from Flex. I also want to minimize the amount of data transfer between client and server.

Solution

Set up Weborb and deploy your .NET class into it. Use mx:RemoteObject to invoke methods on the .NET class from Flex.

Detailed explanation

Install and Configure IIS and .NET

Install Internet Information Services (IIS) and .NET. If IIS is installed after .NET, you will have to register .NET with IIS. This can be done with the aspnet_regiis tool which is in C:\windows\microsoft.net\Framework\v2.0.50727 folder where v2.0.50727 is the .NET version. Run the following from a command prompt after changing the current directory to where the tool is:

aspnet_regiis -i

Install Weborb

Download Weborb from themidnightcoders.com and install it. You should be now able to access the Weborb dashboard by going to the URL http://localhost/weborb30/

Write your C# Class

Consider the following two C# classes:

using System;
using System.Collections;

namespace Flex.DotNET.Example
{
public class UserVO
{
public String name;
public String location;
public DateTime currentTime;
}

public class DotNetClass
{

private void userToUpper(UserVO user)
{
if (user.name != null)
{
user.name = user.name.ToUpper();
}
if (user.location != null)
{
user.location = user.location.ToUpper();
}
user.currentTime = DateTime.Now;
}

public ArrayList convertData(ArrayList inData)
{
foreach (Hashtable asObject in inData)
{
userToUpper((UserVO)asObject["User"]);
asObject["Data"] = ((String)asObject["Data"]).ToUpper();
}

return inData;
}
}
}

An interesting method here is convertData. It takes in an ArrayList, iterates through each object changing it. Each object in the ArrayList is a Hashtable. Anonymous or untyped actionscript objects are converted to Hashtable objects on the .NET side. The [] operator can be used to access the value of fields just like in actionscript.

The User field in the object points to an object of type UserVO and the Data field points to a String. We convert the String in the Data field and user object's location and name to uppercase and also set its currentTime property to DateTime.Now.

Finally the ArrayList with the modified objects is returned.

Compile this class into a .NET assembly and put the resulting dll file into c:\inetpub\wwwroot\weborb30\bin assuming that Weborb is installed at c:\inetpub\wwwroot\weborb30.

Write your Flex Application


In Flex Builder, go to File -> New -> Flex Project. Type in a project name, choose Application server type as ASP.NET. Hit on next and choose Use Internet Information Services. Set the web application root to c:\inetpub\wwwroot\weborb30 and web application URL to http://localhost/weborb30. Click Validate Configuration and then on Finish.

Right click on the project and choose Properties -> Flex Compiler -> Additional compiler arguments. Append the following compiler argument:

-services "c:\inetpub\wwwroot\weborb30\web-inf\flex\services-config.xml"

This is the location of the default services-config that comes with Weborb. It includes remoting-config.xml which has destination nodes mapping destination names (used in RemoteObject's destination attribute) to fully qualified .NET class names. Weborb's remoting-config.xml has a catch-all destination called GenericDestination which takes the name of the .NET class from the source attribute of RemoteObject tag.

Now paste the following code in your main MXML file:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" creationComplete="initApp()">
<mx:Script>
<![CDATA[

import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.controls.Alert;
import mx.collections.ArrayCollection;

[Bindable]
private var testData:ArrayCollection;

private function initApp():void
{
var user1:UserVO = new UserVO();
var user2:UserVO = new UserVO();
user1.name = "User1";
user1.location = "Chicago";
user2.name = "User2";
user2.location = "Frankfurt";
testData = new ArrayCollection([{User: user1, Data: "DummyData"},{User: user2, Data: "DummyData"}]);
}

private function callServer():void
{
remoteObject.convertData( testData.source );
}

private function gotConvertedData( event:ResultEvent ):void
{
testData = new ArrayCollection(event.result as Array);
}

private function faultHandler( event:FaultEvent ):void
{
Alert.show( "Error: " + event );
}
]]>
</mx:Script>
<mx:RemoteObject id="remoteObject"
destination="GenericDestination"
source="Flex.DotNET.Example.DotNetClass"
showBusyCursor="true"
fault="faultHandler(event)" >
<mx:method name="convertData" result="gotConvertedData(event)"/>
</mx:RemoteObject>
<mx:DataGrid id="testDG" width="100%" height="100%" dataProvider="{testData}">
<mx:columns>
<mx:DataGridColumn dataField="User">
<mx:itemRenderer>
<mx:Component>
<mx:Label>
<mx:Script>
<![CDATA[
override public function set data(obj:Object):void
{
if ( obj.User is UserVO )
{
var user:UserVO = obj.User as UserVO;
this.text = user.name + " From " + user.location;
if ( user.currentTime != null )
this.text += " at " + user.currentTime.toString();
}
else
this.text = "Obj is not UserVO";
}
]]>
</mx:Script>
</mx:Label>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
<mx:DataGridColumn dataField="Data" />
</mx:columns>
</mx:DataGrid>
<mx:Button label="Call Server Method" click="callServer()" />
</mx:Application>

Create a new ActionScript class called UserVO and put the following code in it:

package
{
[RemoteClass(alias="Flex.DotNET.Example.UserVO")]
public class UserVO
{
public var name:String;
public var location:String;
public var currentTime:Date

public function UserVO()
{

}

}
}

Compile this application and run it. You should be able to see a datagrid with some data. Click on "Call Server Method" and the grid should be updated with values that was returned from the .NET class.

The main piece on the Flex side is the mx:RemoteObject tag. It has a mx:method with the value of its name attribute matching the name of the server side method we want to call. We also register for the result event so that gotConvertedData() gets called when the remoting call completes.

On the click of a button, we are calling the convertData() method on our RemoteObject passing in an Array as a parameter. On the flex side as well, this array has in it objects with User and Data property. The User property points to a UserVO class which has a RemoteClass metadata tag stating that UserVO on the actionscript side is the class Flex.DotNET.Example.UserVO on the .NET side. When the remote call completes, our result handler fires with the result from .NET in event.result.

Since the .NET side returns an ArrayList, we get it as an Array on the flex side. This is then used to update the collection so that the grid updates.

Report abuse

Related recipes