Getting ASP.NET with AJAX talking to Flash CS3 (or Flex)

Post to Twitter

Here is a way you can use ASP.NET with the AJAX extensions and Visual Studio 2005/2008 to communicate with Flash CS3. If you read my post on getting PHP talking to Flash CS3 then you may notice some similarities. With very little modification you can also use this to get Flex 2 or 3 talking to ASP.NET and the AJAX extensions.

What you’ll need to do this:
1. Visual Studio 2005 with ASP.NET installed as well as the AJAX toolkit. (Visual Studio 2008 should work as well)
2. You need Flash CS3 along with the as3corelib

Go ahead and create a new website in Visual Studio 2005, choose the “ASP.NET AJAX-enabled website” option. I called mine “FlashCommunicater” and picked C# as my language. Remove the “default.aspx” file as we won’t need it. Then add a “WebService” to the project. I called this “ExampleService”.

Here is the code you will want to use:

using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;

/// <summary>
/// Summary description for ExampleService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class ExampleService : System.Web.Services.WebService
{

    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public string[] HelloWorldArray()
    {
        string[] arr = new string[3];
        try
        {
            arr[0] = "Hello Person A";
            arr[1] = "Hello Person B";
            arr[2] = "Hello Person C";
        }
        catch (Exception) { }

        return arr;
    }

}

Here is what makes this interesting…

[ScriptService]

ScriptService is an attribute allows the web service to be called and return JSON or XML. Which brings us to the next attribute:

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]

If you’ve worked with WebMethod before then you know you need this to mark a particular method as exposed it’s functionality to the outside world. The ScriptMethod attribute with the ResponseFormat set to JSON will of course return JSON format.

Time for some ActionScript 3. Start Flash CS3 and create a new “Flash File (ActionScript 3)” and save it as “JSONExample.fla”. Now add an ActionScript file to this project and save it as “MyJSONExample.as”. Now add a TextArea component to the stage and call it “myTxt”. I also set the TextArea’s verticalScrollPolicy proeprty to “true” – do the same with the htmlText property.

Drop the following ActionScript code into the “MyJSONExample.as” file:

package
{
	import flash.events.*;
	import flash.net.*;
	import fl.controls.TextArea;
	import com.adobe.serialization.json.JSON;

	public class MyJSONExample
	{
		var txt:TextArea = null;

		public function MyJSONExample(textArea:TextArea)
		{
			var loader:URLLoader = new URLLoader();
			txt = textArea;
			configureListeners(loader);
			var request:URLRequest = new URLRequest("ExampleService.asmx/HelloWorldArray");

			try
			{
				var header:URLRequestHeader = new URLRequestHeader("content-type", "text/plain");
				var header2:URLRequestHeader = new URLRequestHeader("pragma", "no-cache");

				request.requestHeaders.push(header);
				request.requestHeaders.push(header2);

				request.method = URLRequestMethod.POST;
				loader.load(request);
			}
			catch (error:Error)
			{
				txt.htmlText = txt.htmlText + "\nUnable to load requested document.";
			}
		}

		private function configureListeners(dispatcher:IEventDispatcher):void
		{
			dispatcher.addEventListener(Event.COMPLETE, completeHandler);
			dispatcher.addEventListener(Event.OPEN, openHandler);
			dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
			dispatcher.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
			dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
		}

		private function completeHandler(event:Event):void
		{
			try
			{
			    var loader:URLLoader = URLLoader(event.target);
			    txt.htmlText = txt.htmlText + "\n\n" + loader.data;
			}
			catch (error:Error)
			{
				txt.htmlText = txt.htmlText + error.toString();
			}
		}

		private function openHandler(event:Event):void
		{
			txt.htmlText = txt.htmlText + "\n\nopenHandler: " + event;
		}

		private function progressHandler(event:ProgressEvent):void
		{
			txt.htmlText = txt.htmlText + "\n\nprogressHandler loaded:" + event.bytesLoaded + " total: " + event.bytesTotal;
		}

		private function securityErrorHandler(event:SecurityErrorEvent):void
		{
			txt.htmlText = txt.htmlText + "\n\nsecurityErrorHandler: " + event;
		}

		private function httpStatusHandler(event:HTTPStatusEvent):void
		{
			txt.htmlText = txt.htmlText + "\n\nhttpStatusHandler: " + event;
		}

		private function ioErrorHandler(event:IOErrorEvent):void
		{
			txt.htmlText = txt.htmlText + "\n\nioErrorHandler: " + event;
		}
	}
}

Make sure you’ve extracted the as3corelib into your working folder for the Flash project. You should have the “com/adobe/etc/etc/” folders in there.

The last thing we need to do is to put the following ActionScript onto the main timeline in the first frame (normally you would setup a layer for ActionScript or something to put your code into but this is just a quick example):

var obj:MyJSONExample = new MyJSONExample(myTxt);

Time to run this. Take the resulting files (AC_RunActiveContent.js, JSONExample.html and JSONExample.swf) and import them into your ASP.NET project and set the JSONExample.html as the start page. Now, run your ASP.NET project.

Hopefully you see the proper reponse, if not, try a tool like Fiddler2 or Firebug to see what is going back and forth over the wire.

You can look at the WSDL by using this link (add a port number if needed and modify accordingly depending how you setup your project):

http://localhost/FlashCommunicater/ExampleService.asmx?wsdl

  <?xml version="1.0" encoding="utf-8" ?>
  <wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
  <s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/">
  <s:element name="HelloWorldArray">
  <s:complexType />
  </s:element>
  <s:element name="HelloWorldArrayResponse">
  <s:complexType>
  <s:sequence>
  <s:element minOccurs="0" maxOccurs="1" name="HelloWorldArrayResult" type="tns:ArrayOfString" />
  </s:sequence>
  </s:complexType>
  </s:element>
  <s:complexType name="ArrayOfString">
  <s:sequence>
  <s:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="s:string" />
  </s:sequence>
  </s:complexType>
  </s:schema>
  </wsdl:types>
  <wsdl:message name="HelloWorldArraySoapIn">
  <wsdl:part name="parameters" element="tns:HelloWorldArray" />
  </wsdl:message>
  <wsdl:message name="HelloWorldArraySoapOut">
  <wsdl:part name="parameters" element="tns:HelloWorldArrayResponse" />
  </wsdl:message>
  <wsdl:portType name="ExampleServiceSoap">
  <wsdl:operation name="HelloWorldArray">
  <wsdl:input message="tns:HelloWorldArraySoapIn" />
  <wsdl:output message="tns:HelloWorldArraySoapOut" />
  </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="ExampleServiceSoap" type="tns:ExampleServiceSoap">
  <soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
  <wsdl:operation name="HelloWorldArray">
  <soap:operation soapAction="http://tempuri.org/HelloWorldArray" style="document" />
  <wsdl:input>
  <soap:body use="literal" />
  </wsdl:input>
  <wsdl:output>
  <soap:body use="literal" />
  </wsdl:output>
  </wsdl:operation>
  </wsdl:binding>
  <wsdl:binding name="ExampleServiceSoap12" type="tns:ExampleServiceSoap">
  <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" />
  <wsdl:operation name="HelloWorldArray">
  <soap12:operation soapAction="http://tempuri.org/HelloWorldArray" style="document" />
  <wsdl:input>
  <soap12:body use="literal" />
  </wsdl:input>
  <wsdl:output>
  <soap12:body use="literal" />
  </wsdl:output>
  </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="ExampleService">
  <wsdl:port name="ExampleServiceSoap" binding="tns:ExampleServiceSoap">
  <soap:address location="http://localhost:1035/FlashCommunicater/ExampleService.asmx" />
  </wsdl:port>
  <wsdl:port name="ExampleServiceSoap12" binding="tns:ExampleServiceSoap12">
  <soap12:address location="http://localhost:1035/FlashCommunicater/ExampleService.asmx" />
  </wsdl:port>
  </wsdl:service>
  </wsdl:definitions>

Or you can try this:
http://localhost/FlashCommunicater/ExampleService.asmx/HelloWorldArray

I had to really fidget with the setup and everything else to get everything happy – so don’t expect this to work the first time. Its certainly not as simple to setup IMHO as using PHP or Java, however once I got it working it was pretty slick and worked very well.

Post to Twitter

This entry was posted in ActionScript, AJAX, ASP.NET, C#, Flash, Flex. Bookmark the permalink.

8 Responses to Getting ASP.NET with AJAX talking to Flash CS3 (or Flex)

  1. vOnez says:

    I tried your code and I get an IO Error (Error #2032). All the files are in the same directory. Any Idea why this may be? If I run “http://localhost:3123/testFlashAsp/flash/ExampleService.asmx” in the web browser I get some instructions on how to implement the service and a link to the “operations”. Clicking on the operations link takes me to a page where the service may be invoked. Clicking on the invoke button displays an XML file with the array values declared in the ExampleService class.

    Thanks…

  2. Chad Lung says:

    vOnez,

    There are a couple things to try:
    1. Make sure that Flash/Flex is really doing a POST, not a GET. I’ve seen the 2023 error and using Fiddler I found out Flash was doing a GET not a POST.
    2. Write a quick HTML page with some JavaScript that calls your method via AJAX to ensure it is working.
    3. This guy here has a great tidbit of information:
    http://aspzone.com/blogs/john/archive/2007/06/07/2796.aspx
    – that will help you diagnose the problem without flash player blocking the real exception information.
    4. You might find this helpful as well:
    http://www.judahfrangipane.com/blog/?p=87

    Hopefully that helps!

    Chad

  3. jt says:

    Hi,

    I’m just starting to get to grips with interfacing flash and ajax to communicate with a database, Can you describe the process in a simple way?

    This is what I think happend, but I am likely wrong!

    1 – Flash sends request to a serverside page in .net, php or whatever
    2- This page processes the request and submits it to the server
    3- Page processes response and sends an xml file back to the Flash movie?

  4. Chad Lung says:

    @jt

    There are many ways to communicate from Flash to a server. Some common ways are using the URLLoader/URLRequest classes, sockets, or something like AMF via Blase DS, PHPAMF, etc. There are many ways.

    Sending the information back can also be done in many ways (AMF, XML, JSON, Sockets, etc.). It all depends on the project’s needs.

    Chad

  5. Harry says:

    Hi Chad,

    You mention the possibility that Flash could be sending a GET instead of a POST, and indeed, that’s my current problem. I can’t seem to find out any way of stopping that, though.

    Here’s the code-snippet which is causing me problems:

    var request:URLRequest = new URLRequest(some_url);
    request.contentType = “application/octet-stream”;
    request.method = URLRequestMethod.POST;
    request.data = some_byte_array;

    var loader:URLLoader = new URLLoader();
    loader.load(new URLRequest(url));

    Any ideas what’s going wrong? I’ve trawled the web extensively, and you’re the only guy I’ve come across who has mentioned this problem.

  6. Harry says:

    Bugger – just noticed it, and it’s so obvious I can’t believe I’ve been staring at the code for hours without spotting it!

    Damn I feel silly!

  7. Chad Lung says:

    Ok, glad you got it figured out now.

    Chad

  8. Pingback: Getting Perl and Flex talking via XML « Giant Flying Saucer

Comments are closed.