Category: ASP.NET


Integrating Adobe Flex and .NET with ASP.NET MVC

January 2nd, 2009 — 3:30pm

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.

5 comments » | ASP.NET, ASP.NET MVC, Flex

jQuery Event Binding vs. ASP.NET AJAX UpdatePanel

October 9th, 2007 — 1:05pm

UPDATE (12/5/2008): An alternative solution to this issue is found in a more recent post here:
http://www.thegrubbsian.com/2008/12/jquery-vs-the-aspnet-update-panel-revisited.html

While this is a simple topic, it is one that tripped me up and since the documentation for ASP.NET AJAX is pretty poor, I thought I'd share how I worked it out.

One of the great advantages of using a JavaScript library like jQuery is easy event binding.  In jQuery you can bind an event in a cross-browser compliant manner with very little code:

$("someElement").click(function() { alert('I'm Clicked!');});

Another convenience of modern JS libraries is a loaded event, basically detecting when the browser has finished receiving and parsing the DOM from the server.  For example, in jQuery we can test for DOM completion thusly:

$(window).ready(function() { ... });

Anything within the function here will be executed only after the entire DOM has been downloaded and parsed by the rendering engine.

Now, when you wrap parts of markup with an ASP.NET AJAX UpdatePanel you create a scenario in which a certain portion of the DOM will be reloaded asynchronously while other parts are not.  Even though you will often be merely updating nodes within this area of the DOM, the UpdatePanel is heavy handed…it basically just wipes out whatever was in there and replaces it fresh from the server.  When this happens all your fancy events bound to those elements are blown away.  Thanks UpdatePanel!

Happily, there is a solution that works with any library, not just jQuery.  You will need to abstract your jQuery event bindings away from their handlers into new JS functions.  For example:

$(window).ready(function() {
    $("#someElement").click(function() {
        alert('I've been clicked!');
    });
});

would become:

$(window).ready(function() {
    $("#someElement").click(function() { SomeElementClicked() });
});

function SomeElementClicked() {
    alert('I've been clicked!');
}

Next, we need to replace the jQuery "ready" block with a function that automatically gets called by the ASP.NET AJAX client framework whenever a postback occurs (sync or async).  So our script would now be:

Sys.Application.add_load(WireEvents);

function WireEvents() {
    $("#someElement").click(function() { SomeElementClicked() });
}

function SomeElementClicked() {
    alert('I've been clicked!');
}

Now you can continue to use jQuery to bind events (and skip using the convoluted ASP.NET AJAX way) and use the UpdatePanel to surround jQuery bound DOM elements.

8 comments » | ASP.NET, jQuery

My Page Just Had Deja Vu

October 5th, 2007 — 1:42pm

One function whose absence I find annoying in ASP.NET is the ability to easily return to a previous page and reload its state.  I recently needed this functionality in a project for a course registration application I was building at work.

The basic scenario is this:

  1. User enters some search criteria on the Course Search page and a list of matching courses is returned.
  2. The user selects a course and is directed to the Student Roster page for that course.
  3. The user then selects a particular student and is directed to the Student Maintenance page.

Now, the user will almost always need to get back to the Student Roster page, and maybe even the Course Search page after making changes on the Student Maintenance page.  However, they don’t want to start the whole process over back at Course Search each time.

So, I tried a number of ways to accomplish this in a generic fashion, the first being a convoluted method using the PageStatePersister class to pop the page’s ViewState into Session and bring it back when the user returns.  However, this can be problematic because the page is unaware of what’s going on in the application outside of itself.  In other words, data may have changed or the user may have returned to this page through a non-linear route and now needs a different set of criteria; they don’t want the same options they chose before.

So what I came up with was a simple solution using the query string and a ReturnUrl parameter.  I’m sure we’ve all seen these things gumming up query strings around the web.  While it does tend to make your URL rather intense, it is an effective method and it’s easy to see what’s going on.  So here are the requirements I set up for whatever method would implement this functionality:

  1. The method must be able to pass forward a ReturnUrl parameter which can hold both control values on the original page as well as any query string variables which were passed to it.
  2. The method must be able to handle n forward progressions and likewise be able to link backwards n times without losing anything along the way.
  3. When a page reloads from a ReturnUrl the method must be able to set values on ASP.NET  WebControls on Page_Load.

So, I wrote a class which inherits from System.Web.UI.Page called DejaVuPage (an apt name I thought) which encapsulates this functionality.  The code for this class can be found in the App_Code folder in the zip file which accompanies this post as DejaVuPage.cs.  Essentially, there are four things any page inheriting from DejaVuPage can now do:

  1. Set a list of controls to be included in potential ReturnUrl params.  This is done by adding control IDs to the DejaVuPage.ReloadableControls (ArrayList) property.
  2. At any time get what the current ReturnUrl parameter would be.  This is done by getting the DejaVuPage.ReturnUrl property.
  3. Redirect to the previous page by calling this.RedirectToReturnUrl().
  4. Reload a page’s controls from a ReturnUrl by calling this.LoadFromReturnUrl().

The ASP.NET sample project included in the post has a good example; run the app, enter some criteria on each page, then when you get to the end use the ‘Go Back’ links each previous page will reload it’s controls as you left them before.

I’m sure someone can improve my code, so if you see somewhere where this concept could be refined, please let me know.  I hope some of you find this useful.

Download DejaVuSample.zip

Comment » | ASP.NET

Back to top