I've been working on a legacy AIR application for a client. It integrates with a backend I have no control over. According to their documentation, we need to pass the form parameters in a specific order. This seems unusual for a form post, which contains key-value pairs and is probably not accessed in parameter order. But due to other problems integrating with this service, I decided to see what I could do to specify the parameter order and remove that as a possible point of failure. I wrote about my attempts in this StackOverflow question.

What Didn't Work

This is what we were doing. First, create an HTTPService:

view plain print about
1<mx:HTTPService id="service"
2 showBusyCursor="false"
3 requestTimeout="240"
4 method="post" contentType="application/x-www-form-urlencoded"
5 url="yourURLHere" resultFormat="e4x"
6 /

Then, create the parameter object in code:

view plain print about
1var parameters : Object = new Object();
2parameters.firstParameter = "firstOne";
3parameters.amount = 100;
4parameters.otherParameters = "Other Random Misc Data";
5parameters.lastParameter = "LastOne";

When the parameter object is created for the service call, I added the parameters to the object in order.

Then make the call:

view plain print about
1var call : Object = this.service.send(parameters);
2call.addResponder( this.responder );

You may have already guessed why this won't work. Object parameters, or keys in a dictionary, are by definition, not in any specific sort order. When the Flex code looped over all parameters to add them to the outgoing service, it was accessing them in alphabetical order. However, that is not something I would bet my life on happening every single time due to the unordered nature of object properties. I also noticed that the outgoing request in the Flash Builder network monitor had the parameters in yet another order. Something with them changed between the Flex code and the server hit.

So, what am I to do?

Using Lower Level APIs to make this work

The final solution was to use lower level APIs. I created the request using URLRequest and URLLoader classes. Instead of passing an object to the request I also had to manually create the request body which is very similar to a URL parameter string.

First, create the parameter string:

view plain print about
1var parameters : String = '';
2parameters += "firstParameter=firstOne&";
3parameters += "amount=100&";
4parameters += "otherParameters=Other Random Misc Data&";
5parameters+= "lastParameter=LastOne";

Then, create the URLRequest:

view plain print about
1var r:URLRequest = new URLRequest(yourURLHere);
2r.data = parameters;
3r.method = URLRequestMethod.POST;
4r.contentType = "application/x-www-form-urlencoded";

The data is set to the parameters string. The method is set to POST and the contentType is set to 'application/x-ww-form-urlencoded'.

And finally, create the URLLoader:

view plain print about
1var l:URLLoader = new URLLoader();
2l.addEventListener(Event.COMPLETE, myResultMethod);
3l.addEventListener(IOErrorEvent.IO_ERROR, myFailureMethod );
4l.addEventListener(SecurityErrorEvent.SECURITY_ERROR, myFailureMethod );

After doing this I could see in the outgoing requests that the parameter order was retained. So, things were good and my issue was solved! This is a lot more tedious than using the HTTPService, but at least I eliminated it as a possible error.