代码改变世界

Integrating Adobe Flex and .NET with ASP.NET MVC

2010-03-01 10:04  AnyKoro  阅读(973)  评论(2编辑  收藏  举报

There are a lot of tools out there to help you utilize .NET as a back-end for Flex applications.  All of these solutions come with a heavy customization and implementation cost.  I’ve used WebORB with quite a bit of success in the past but it always seemed a little heavy to me.  The truth is that WebORB and its compatriots are the right choice for large applications or apps with highly complex server side needs.  But for the lightweight web application that doesn’t require tons of server side business logic there is another choice.

With the advent of ASP.NET MVC we have a very simple way to construct web accessible .NET endpoints – controller actions.  In the past when you needed to get data out of .NET using HTTP you might spin up a web service or a WCF service.  These are still great options, but if the data you need to transfer is small and/or jagged you might find yourself writing a lot of extra code.  You’ll also pay the XML tax and nobody likes paying taxes.

So if not XML, what then?  Well, JSON of course.  JavaScript Object Notation is a perfect media for transmitting moderate amounts of data over the wire.  And there are excellent serialization options on both the .NET and Flex sides of the game.  So here’s a little example of this pattern in action.

Create an ASP.NET MVC Controller Action – Return JSON.

public ContentResult GetInventory() {
var repository = new InventoryRepostiory();
var items = repository.GetItems().ToList<InventoryItem>();
return Content(items.ToJSON(null));
}

I’m not going to go into the data access pattern here in this article, but I’m using a repository to return a set of inventory items.  You might also be wondering where this ToJSON() method comes from.  It’s an extension method…and here it is (c/o ScottGu):

public static string ToJSON(this object thing, int? recursionDepth) {
var serializer = new JavaScriptSerializer();
if (recursionDepth.HasValue)
serializer.RecursionLimit = recursionDepth.Value;
return serializer.Serialize(thing);
}

All it does is take an object, do a little reflection magic on it via the System.Web.Script.Serialization.JavaScriptSerializer class and spits out a JSON string.

Calling Your ASP.NET MVC Controller Action from Flex

The first thing you’ll need on the Flex side before you can consume your MVC action is a way to de-serialize the JSON string.  Fortunately, the Adobe guys have provided a handy library of utilities called AS3CoreLib which contains just such a service.  Once you have the SWC just pop it in the Libs folder of your Flex app.

So now let’s create a wrapper class in ActionScript to consume our ASP.NET MVC action.  I like to mimic the repository pattern on the Flex side as well so that I can keep up with a somewhat consistent API.  There’s nothing that technically holds you to this rule, but it’s helpful to keep things logically organized.  So, here’s the InventoryRepository in AS3:

package Data {
import com.adobe.serialization.json.*;
import flash.net.*;
import flash.events.*;
import mx.collections.ArrayCollection;
 
public class InventoryRepository {
 
private var completeCallback:Function;
 
public function GetInventory(callback:Function) : void {
completeCallback = callback;
var loader:URLLoader = new URLLoader(new URLRequest("http://localhost/Home/GetInventory"));
loader.addEventListener(Event.COMPLETE, getInventoryComplete);
}
 
private function getInventoryComplete(event:Event) : void {
var obj:Object = JSON.decode(event.target.data);
completeCallback(obj);
}
}
}

You’ll notice that I’ve imported the com.adobe.serialization.json classes from AS3CoreLib.  That provides us with the JSON.decode() method.

Now, because remote calls in Flex are asynchronous, we need to do a little fancy footwork to deal with it.  So, when you call the GetInventory() method we also have to supply a callback to fire off when the data returns from the MVC action.  This is one of my favorite aspects of ActionScript…it’s dynamic…dynamic in the JavaScript sense of the word.  So we can supply a callback that doesn’t need to be defined in our repository class itself. 

So let’s look at some code that consumes our repository method.  This is just a code-behind file for an MXML appl ication:

package InventoryApplication {
import mx.core.Application;
import flash.events.Event;
import mx.controls.DataGrid;
import mx.collections.*;
import Data.*;
 
public class HomeApplication extends Application {
 
public var inventoryGrid:DataGrid = new DataGrid();
 
public function InventoryApplication() {
super();
LoadInventory();
}
 
public function LoadInventory () : void {
var repository:InventoryRepository = new InventoryRepository ();
repository.GetInventory(function(data:Object) : void {
inventoryGrid.dataProvider = data;
});
}
}
}

So the only really interesting thing here is how we’re defining the callback as an anonymous function passed into the GetInventory() method.  When the data is returned we just bind it to our data grid and we’re done.

Sending Data To an ASP.NET MVC Action From Flex

So, now we can pull data out of our .NET back end, but how do send data into an MVC action from Flex?  The solution couldn’t be simpler.  So here’s a new method for the AS3 repository:

public function CreateKind(itemName:String,
itemType:String,
itemSize:String,
callback:Function) : void {
 
var variables:URLVariables = new URLVariables();
variables.name = itemName;
variables.type = itemType;
variables.size = itemSize;
 
var request:URLRequest = new URLRequest("http://localhost/Home/CreateKind");
request.method = URLRequestMethod.POST;
request.data = variables;
 
var loader:URLLoader = new URLLoader(request);
}

Here you can see we’re passing in the properties of our new item and adding them to the variables object directly (another nice thing about ActionScript being dynamic).  So now these new properties will become variables in the form collection sent to our controller action.  Here’s our controller action:

public ContentResult CreateItem(string name, string type, string size) {
 
var item = new InventoryItem
{
Name = name,
Type = type,
Size = size
};
 
var repo = new InventoryRepository();
repo.SaveItem(item);
 
return Content("true");
}

You’ll notice that the parameters it accepts are “name”, “type”, and “size”.  These are the same properties added to the Flex URLVariables object in our Flex repository class.  Through the magic of ASP.NET MVC these items are simply available to the controller action as parameters, simple as that.

So, hopefully that demonstrates how easy it is to use ASP.NET MVC to integrate a .NET back-end with Flex.  I think the advantages of this method are substantial, but do your research and take a look at the other options as well.