Flex with Web Services, SOAP, .NET, and XML
Flex and .NET web services can be a powerful combination, and using them together can also be challenging. Using web services with Flex generally means you have to deal with SOAP (Simple Object Access Protocol), and this can be frustrating and tricky, in fact it can be so frustrating, that developers will forgo the use of web services and opt for the HTTPService object when retrieving xml from a web service, which is not always the best alternative (in my opinion), since web services are more robust (in my opinion) than HTTPServices.
This post shows how to work with .NET web services in Flex, and how to bypass a lot of the SOAP headache.
The problem:
Returning a native XML from .NET web service to Flex makes the XML object difficult to access on the Flex side- I was basically
unable to use e4x, even though I used namespaces, and operation return types properly.
C# Web Service code to retrieve XML from a database that contains client information for a fictitious business.
public XmlDocument GetClientsXML()
{
XmlDocument clientXMLDoc = new XmlDocument();
//create the connection to the database
SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["FOO"].ConnectionString);
SqlCommand cmd = new SqlCommand("spGetClients",conn);
cmd.CommandType = CommandType.StoredProcedure;
StringWriter sw = new StringWriter();
XmlTextWriter xw = new XmlTextWriter(sw);
SqlDataReader dr;</code>
//get the records
try
{
conn.Open();
dr = cmd.ExecuteReader();
//loop over the data set and create the xml for the clients
if(dr.HasRows)
{
xw.WriteStartElement("clients");
while(dr.Read())
{
xw.WriteStartElement("client");
xw.WriteStartElement("clientId");
xw.WriteString(((Int16) dr["ClientId"]).ToString());
xw.WriteEndElement();
xw.WriteStartElement("firstName");
xw.WriteString(dr["FirstName"].ToString());
xw.WriteEndElement();
xw.WriteStartElement("lastName");
xw.WriteString(dr["LastName"].ToString());
xw.WriteEndElement();
xw.WriteStartElement("email");
xw.WriteString(dr["Email"].ToString());
xw.WriteEndElement();
xw.WriteStartElement("city");
xw.WriteString(dr["City"].ToString());
xw.WriteEndElement();
xw.WriteStartElement("State");
xw.WriteString(dr["State"].ToString());
xw.WriteEndElement();
xw.WriteStartElement("zip");
xw.WriteString(dr["Zip"].ToString());
xw.WriteEndElement();
xw.WriteEndElement();
}
xw.WriteEndElement();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
conn.Close();
}
//parse the xml by loading it into the clientXMLDoc var and then return it as a native XML document
clientXMLDoc.LoadXml(xw.ToString());
return clientXMLDoc;
}
That is the methodology used to get the string representation from the database. Wanting to be a good developer I took it another step and wrapped the xml string into an XmlDocument and returned this to Flex at first
So now we have our xml document that will pass back to Flex which looks something like this
<clientid>2</clientid>
<firstname>Daffy</firstname>
<lastname>Duck</lastname>
<iail>dduck@binarygiant.com</iail>
<city>Las Vegas</city>
<state>Nevada</state>
<zip>889141</zip>
</clients>
<client>
<clientid>5</clientid>
<firstname>Some</firstname>
<lastname>Dude</lastname>
<iail>somedude@here.com</iail>
<city>San Diego</city>
<state>California</state>
<zip>99771</zip>
</client>
<client>
</client>
So now that I had my xml I thought it would be easy to work with on the Flex side, because I had declared the return type of the <mx:operation/> tag as e4x, and I added the namespace declaration to my Actionscript code to the same as that of the XML document
id="clientService"
wsdl="http://realityisabsolute.com/Foo/Client.asmx?wsdl"
showBusyCursor="true"></mx:webservice></code>
<mx:operation name="GetClientsXML" concurrency="multiple" resultformat="e4x">
</mx:WebService>
private namespace realityIsAbsolute = "http://realityisabsolute.com";
use namespace realityIsAbsolute;
In my Flex application I attempted to access the xml document using standard e4x syntax, but all my efforts failed. I scoured posts about removing headers, adding namespaces, etc., and came up with not much more than a headache, and had to revert back to an fairly archaic method of accessing XML nodes with the ActionScript XML class.
The Solution:
The project that inspired this post is a Flex/.NET application that uses the .NET framework’s XmlDocument class to return a native xml document to a Flex application. What I have found is that when you return a native xml document to Flex from a .NET web service, you have to deal with a SOAP nightmare. Instead of using the XmlDocument class on the web service side, I suggest you use the XmlTextWriter class to create a string representation of the XML document, return that string to Flex, and convert the string to XML on the Flex side (in one easy step), and then you’re ready to use e4x with you XML in Flex.
My ActionScript 3.0 code to access XmlDocument nodes
var clientXML:XML = new XML(event.result.toString());
//we set the resultFormat to e4x in the web service operation declaration, and we declared the namespace
//so we would think that we could access the xml using e4x, but we can’t. and after several attempts
//to strip the soap garbage, I gave up, and accessed the xml using the oh-so-fun decendants and children
//access notation.</code>
clientXML = clientXML.descendants().descendants()[0]; //drilling even further to get an XMLList
var clientXMLList:XMLList = new XMLList(clientXML.children());
//even after I extracted the XMLList and convert it to an xml list collection, and set it on the model
//so that bindings throughout the application will pick it up, the soap garbage gets in the way of that,
//so my next step would be to convert it to an array collection, but I can do much more easily by telling
//the web service call to return the result as an object
model.clientList2 = new XMLListCollection(clientXMLList);
//so you see that I had to inspect the xml that came across from the web service, drill in, and repeat
//a pretty arduous task of accessing the nodes using old methods. That is why instead of returning
//a native xml document from the web service, it is better to simply return a string and convert it to
//native xml using action script, then access it via e4x
Using the Flex Debugger to inspect my XML this is what I got back…. a SOAP mess.
The Solution:
I changed the .NET web service slightly, by removing the step where I convert the xml string on the XmlTextWriter to an XmlDocument on the C#.NET web service side. The method now returns the string xml to Flex, and I can access it using e4x after converting the string to xml using ActionScript
C# .NET web service code
public string GetClients()
{
//create the connection to the database
SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["FOO"].ConnectionString);
SqlCommand cmd = new SqlCommand("spGetClients",conn);
cmd.CommandType = CommandType.StoredProcedure;
StringWriter sw = new StringWriter();
XmlTextWriter xw = new XmlTextWriter(sw);
SqlDataReader dr;</code>
//get the records
try
{
conn.Open();
dr = cmd.ExecuteReader();
//loop over the data set and create the xml for the clients
if(dr.HasRows)
{
xw.WriteStartElement("clients");
while(dr.Read())
{
xw.WriteStartElement("client");
xw.WriteStartElement("clientId");
xw.WriteString(((Int16) dr["ClientId"]).ToString());
xw.WriteEndElement();
xw.WriteStartElement("firstName");
xw.WriteString(dr["FirstName"].ToString());
xw.WriteEndElement();
xw.WriteStartElement("lastName");
xw.WriteString(dr["LastName"].ToString());
xw.WriteEndElement();
xw.WriteStartElement("email");
xw.WriteString(dr["Email"].ToString());
xw.WriteEndElement();
xw.WriteStartElement("city");
xw.WriteString(dr["City"].ToString());
xw.WriteEndElement();
xw.WriteStartElement("State");
xw.WriteString(dr["State"].ToString());
xw.WriteEndElement();
xw.WriteStartElement("zip");
xw.WriteString(dr["Zip"].ToString());
xw.WriteEndElement();
xw.WriteEndElement();
}
xw.WriteEndElement();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
conn.Close();
}
string clientXML = sw.ToString();
return clientXML;
}
Convert the xml string returned from the web service to an ActionScript XML object and you can easily access it with e4x. In this instance I called parsed out the XML until I got to the root node for clients, called the children() method of the XML class to return an XMLList to pass to the constructor of the XMLListCollection class, and then set a property on the model (using Cairngorm) that is a dataprovider for some data components on the application.Flex/ActionScript 3.0 code to convert the string to an ActionScript XML object
{
//extract the string represenation of the xml from the web service result and convert it to native XML
//now we can access it using e4x, see the trace statements
var clientXML:XML = new XML(event.result.toString());</code>
//set the var on the model that the data grid (and/or any other component) is bound to
model.clientList = new XMLListCollection(clientXML.children());
for(var i:int = 0; i < clientXML.length(); i ++)
{
trace(clientXML.client[0].clientId);
trace(clientXML.client[i].firstName + " " + clientXML.client[i].lastName);
}
}
You can see that there is a huge difference in the way that Flex allows you to treat xml returned from web services. While writing this post I very briefly tested the new Flex 3 web service wizard. It created about 7 files to handle all of the SOAP issues to get to the XML. The files written by the wizard are no doubt powerful and extremely helpful, but if you are looking for a light-weight way to access XML using web services and .NET, this method works well.
About this entry
You’re currently reading “Flex with Web Services, SOAP, .NET, and XML,” an entry on Binary Giant
- Published:
- 03.30.08 / 10pm
- Category:
- .NET, C#, Flex, Rich Internet Applications, Web Services


1 Comment
Jump to comment form | comments rss [?] | trackback uri [?]