HomeDigital EditionSearch Dotnet Cd
ASP.NET C# Certification Exams The CLI Data Access Editorials Extending .NET Fundamentals Interoperability Interviews Migrate Mobile .NET Mono .NET Interface Object-Oriented Programming Open Source Optimization Product/Book Reviews Security Source Code UML Visual Studio .NET

Most developers prefer to build systems using a favorite single platform. Sometimes our platform selection is based on fact and experience, and sometimes it is just the result of personal beliefs and prejudices. However, there are cases when employing a single - even the very best platform - actually makes our lives harder.

There are many who believe that Java is better than Visual Basic, or that C# is better than Java, or that Perl is better than either... Let's try a slightly different approach: I will discuss an architecture that takes advantage of three completely different platforms: J2EE, Microsoft .NET, and Macromedia Flash.

Tools for Building a Successful Application
Anyone who has ever written a decent browser-based "Hello World" realizes that static HTML does not have a lot to offer - even with good old JavaScript. Putting aside personal opinion about CGI (I'm human too, you know) I want to briefly discuss two major server scripting technologies - JSP and ASP.NET.

JSP was the first breakthrough technology to allow creation of dynamic pages using static HTML with small insertions of server-side script and/or special tags. Because every page compiles to a Java-based class (servlet), JSPs are very scalable - each page runs as a single process with a separate thread for each user. Developers are provided with easy access to request parameters, headers, etc; there is quite advanced state management and session support. JSPs also contain quite extensive features for customization since tag libraries could be used to build custom tags. However, there doesn't seem to be a lot of design tools to help with the process of creating such pages. In a lot of cases, we use Microsoft FrontPage (hoping that the Java god is not watching) to create a static HTML page and then add all the JSP stuff in there (and FrontPage, whose god is much more observant, immediately stops recognizing the document).

ASP.NET was developed a little later and to some degree employs a similar idea. ASP.NET pages are also converted to code that runs as a multithreaded process with one thread per user. However, Microsoft added great design-time support that includes event handling. Event handling is perhaps the most amazing feature; now instead of thinking of GET and POST, we define the handlers for events without worrying too much about how these events are generated. Years ago similar abstraction from Windows messages made Visual Basic very popular! Besides, even out of the box ASP.NET provides a marvelous set of controls, but more controls can be built using ASP.NET custom controls. Look at www.asp.net for some great examples.

With this variety of controls and with some help from JavaScript, ASP.NET is really useful for quick development of slick Web UIs. However, what if we need something really complex, perhaps animation? There is a tool that many .NET and Java developers are not even aware of. We've all seen Macromedia Flash movies and know how cool they can be; however, Flash can also be used to build a complex UI for client/server applications - often with significantly less effort then doing it in JavaScript. Flash provides rich tools for graphics and animation; it also offers a slightly strange scripting language - ActionScript (see www.actionscript.org and www.actionscript-toolbox.com for samples and more information). To support client/server communications, Macromedia recently released a product called Flash Remoting, which is a set of APIs that allows easy integration with ASP.NET, ColdFusion, and J2EE.

What about a back end? What if we have J2EE servers already? Do we have to port all the code to C# and ADO.NET? J2EE systems perform well and have proven to be quite scalable - and we've already invested in Unix systems. Can .NET communicate with a J2EE back end? Absolutely, with the help of Web services! Adding a Web service to the ASP.NET page is absolutely trivial. As for the back end, all we need is a servlet with an XML parser (or better, a SOAP library).

Sample Application - Internet Slide Show
In order to demonstrate a system built using all of these technologies, let's create an Internet-based slide show. Suppose we have photographers who produce different shows using their digital photos. We want to create a simple application that allows us to select a show and browse through these photos. Here's how we want it to work:

  • When the show is not selected, we want to display some animation (see Figure 1).

    Figure 1
  • When the show is selected we want to be able to go through the photos in the show (see Figure 2).

    Figure 2
  • The first release of the application will not have music and will not allow any special effects. However, we want to consider these and other possibilities in the future.

    The quickest and easiest way to implement such a system would be to create an ASP.NET page that uses a couple of controls and reads the data from the database using ADO.NET. However, right away there are some issues with this implementation:

  • Whenever we need to change the image, the page will be reloaded and as a result there will be a delay, perhaps a flicker.
  • Creation of animation is going to be tricky, therefore we might have to deal with animated GIF or similar challenges.
  • Assuming that the other part of the system - the one that allows photographers to create their shows - already exists and is written in J2EE, we will have to duplicate a lot of code in .NET.

    Let's discuss the alternative architecture (see Figure 3). We will keep the ASP.NET page as a container and insert controls for selection of the show. It may come as a great surprise to some of you, but the easiest way to implement the show is in Macromedia Flash. Using Flash we will have most of the required features without writing a lot of code! We will have to add one more ASP.NET page - the one that will host the Flash Remoting component. And for the back end we are going to utilize the enterprise beans already existing in the system by adding a "Facade" stateless session bean and a servlet that implements a Web service.

    Figure 3

    Creating a Web Service with BEA WebLogic
    Let's take a look at how we can build it. To be honest, writing a Web service servlet from scratch - even with a SOAP library - would not be an easy task. Luckily, J2EE vendors thought about it and added the tools to simplify this process. BEA WebLogic, for instance, includes a special add-in for the Ant build tool. (If you've never used Ant, you should try it [http://ant.apache.org]. It's a great scripting tool!) With this addition, Ant can generate all the necessary Web service code for any given stateless session bean and even package the whole project into an EAR (enterprise archive) file. All we need to do is add the servicegen task to the build script (see Listing 1).

    When the EAR file is deployed on the server, the Web service URL will be

    http://<server URL>/<contextURI><serviceURI>

    In other words if the server is deployed on server.company.com, contextURI is set to WebService, and serviceURI is /MyService, then the URL will be http://server.company.com/WebService/MyService. However, there is an immediate question - what about data types? Everything is pretty obvious if we send and receive simple types: C# int corresponds to Java int, C# string to Java String, etc. What if we need to return multiple results or an array of classes?

    Let's take a look at the EJB for our project.

    public interface SlideShow extends EJBObject
    {
    public ShowsResult [] getShows (String login, String passwd)
    throws RemoteException;

    public SlidesResult [] getSlides (int showID)
    throws RemoteException;
    }

    In order to return the array of Shows, we need to define the ShowsResult class in a certain way and let the builder do the rest (given that you did not forget the line generateTypes="True") (see Listing 2). The SlidesResult class must also be created the same way.

    Creating the Flash Movie and Remoting Gateway
    The next big step is to create a Flash movie (I assume that you are somewhat familiar with Flash and ActionScript). First, let's take care of animations. We need two animations:

  • "Idle" screen, to be displayed when there is no slide show to display
  • Screen that displays the "Loading" message while the slides are downloaded from the server

    I found that the easiest way to deal with this is to create these animations as movie clips. For instance, I create a movie clip called InitialMessage that contains only several key frames. In each frame (10, 20, 30, etc.) I move and rotate the little ball; then as soon as I create a motion tween, the ball will start moving (see Figure 4). That's it; no code is needed! Now, all we need to do is add this movie clip to the scene and make it visible or invisible when necessary.

    Figure 4

    Well, we are ready to write the whole movie and integrate it with the server. Let's start by understanding what is required on the server side. First, we need to add Flash Remoting to the ASP.NET project. This requires the following steps:

  • Add the flashgateway.dll (which comes with the Flash Remoting installation) to the project references.
  • Add the code in Listing 3 into Web.xml.
  • Add gateway.aspx to the project.

    Now, let's create a simple ASP.NET page that will be used for communication and replace all the HTML there with the code in Listing 4. Now our C# file will look like Listing 5.

    Here is how the movie communicates with the server:

  • The data sent from the movie to the server is returned in the collection Params of the Flash Remoting control.
  • The data from the server to the movie can be returned in two ways:
    -As a DataSet - in this case we need to use the DataSource property and the DataBind method (just like in our sample).
    -As a table of values - in this case the code may look like Listing 6.

    Add the following to the code for the movie:

  • #include "NetServices.as": Needed for Flash Remoting.
  • #include "NetDebug.as": Needed for Flash Remoting.
  • stop(): Used to stop the movie. Because the main timeline has only one frame, we need to stop the movie - this way it will not be constantly replaying.
  • _global.imgArr=new Array(): Creates arrays for slides.
  • _global.namesArr=new Array(): Creates arrays for the names of the slides.
  • _global.currentSlideID=0: Sets the marker for the current slide.

    We need to analyze the movie's input parameter, showID; if it's not present, the movie should show the "Idle" message. It is very easy to pass the input parameter to the show; just add it to the movie URL (i.e., "smallworld.swf? showID=1").

    if (showID==null)
    {
    initMsg._visible=true;
    waitMsg._visible=false;
    }
    else
    {
    initMsg._visible=false;
    waitMsg._visible=true;
    }

    The following lines establish the connection to the server's gateway and properly initialize Flash Remoting.

    NetServices.setDefaultGatewayURL
    ("http://localhost/publications/Slide
    Shows/gateway.aspx");
    connection=NetServices.create
    GatewayConnection();

    Now we are ready to connect to the service itself. Note that the path to the service must match the path to the ASP.NET application; in our case the application is called SlideShows and is under the publications directory. slideService=connection.getService("publications/SlideShows");

    As soon as we are connected to the service we can call the method. The name of the method matches the name of the appropriate ASP.NET page that contains FlashGateway.Flash control (without extension). The first parameter of the call is the response handler class; the rest is the data that will be sent to the server:

    slideService.Slides
    Manager(new AsdResult(),showID);

    The response handler class has to have two methods, onResult for success, and onStatus for exception (see Listing 7).

    The server returns an array of images in which each element contains the image URL and the name of the slide; we will load the images using the loadjpg function and store them and their names into the array.

    For an explanation of loadjpg method, see http://actionscript-toolbox.com/samplemx_loadjpg.php.

    Conclusion
    The system we created uses three very different technologies. Every technology has its own use; we use J2EE for scalability, ASP.NET for the ease and speed of development, and Macromedia Flash for its UI and graphics capabilities. I am not suggesting that every system must use this kind of architecture; a lot of systems can be developed on a single platform or technology. However, when needed, let's use what is the best on the market and get the best out of it!

    About the Author
    Roman Smolgovsky is responsible for architecting industry-leading flight intelligence solutions as well as managing the product development process at FlyteComm, Inc. He brings over 15 years of experience in system architecture, design, implementation, and deployment of software solutions and has a history of leading development teams to success. Roman has an MS in computer science from the University of Radio Engineering Minsk, Belarus. romans@flytecomm.com

    	
    
    
    
    Listing 1
    
    <project name="ejblink" default="all" basedir=".">
    	…………………………………………………………
    	<taskdef name="servicegen"
    	 classname="weblogic.ant.taskdefs.webservices.servicegen.ServiceGenTask"/>
    	…………………………………………………………
    	<target name="ear" depends="build-ejb">
    		…………………………………………………………
    		<servicegen destEar="<name of the EAR file>" 
    	warName="<name of the WAR file>" contextURI="<URL of web
    					  services root>">
    		<service ejbJar="<name of the EJB JAR file>" 
    				  targetNamespace="<namespace name>" 
    	serviceName="<service name>" serviceURI="<path to web service>" 
    				  generateTypes="True" 
    				 expandMethods="True"/>
    		</servicegen>
    	</target>
    	…………………………………………………………
    </project>
    
    Listing 2
    
    public final class ShowsResult implements Serializable
    {
    	private int showID;
    	private String showName;
    
    	public ShowsResult()
    	{
    	}
    
    	public ShowsResult(int showID, String showName)
    	{
    		this.showID=showID;
    		this.showName=showName;
    	}
    
    	public int getShowID()
    	{
    		return this.showID;
    	}
    
    	public void setShowID(int showID)
    	{
    		this.showID=showID;
    	}
    
    	public String getSlideName()
    	{
    		return this.showName;
    	}
    
    	public void setSlideName(String showName)
    	{
    		this.showName=showName;
    	}
    }
    
    Listing 3
    
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>  
      <system.web>
    	…………
        <sessionState ...../>    
        <httpModules>
    	<add name="GatewayController" 
    	type="FlashGateway.Controller.GatewayController,flashgateway"/>
        </httpModules>
       <globalization ...../>   
    	…………
     </system.web>
    </configuration>
    
    Listing 4
    
    <%@ Register TagPrefix="Macromedia" Namespace="FlashGateway"
     Assembly="flashgateway" %>
    <%@ Page language="c#" Codebehind="SlidesManager.aspx.cs"
     AutoEventWireup="false"
     Inherits="SlideShows.SlidesManager" %>
    <MACROMEDIA:FLASH id="flash" runat="Server"></MACROMEDIA:FLASH>
    
    Listing 5
    
    using System;
    ………
    using FlashGateway.IO;
    using SlideShows.SlideShowsWebService;
    
    namespace SlideShows
    {
    	public class SlidesManager : System.Web.UI.Page
    	{
    		protected FlashGateway.Flash flash;
    
    		private void Page_Load(object sender, System.EventArgs e)
    		{
    			if (flash.Params.Count<1)
    			{
    				throw new Exception("Parameter is missing!");
    			}
    
    			int showID=Convert.ToInt32(flash.Params[0]);
    			DataTable tbl=new DataTable();
    			tbl.Columns.Add("ImageName",typeof(String));
    			tbl.Columns.Add("Url",typeof(String));
    
    			using(SlideShowService ssSrv=new SlideShowService())
    			{
    				SlidesResult [] res=ssSrv.getSlides(showID);
    
    				foreach(SlidesResult sr in res)
    				{
    					DataRow dr=tbl.NewRow();
    					dr.BeginEdit();
    					dr["IMAGENAME"]=sr.slideName;
    					dr["URL"]=sr.slideURL;
    					dr.EndEdit();
    					tbl.Rows.Add(dr);
    				}
    			}
    			flash.DataSource=tbl;
    			flash.DataBind();	
    		}
    		#region Web Form Designer generated code
    			...........
    		#endregion
    	}
    }
    
    Listing 6
    
    private void Page_Load(object sender, System.EventArgs e)
    {
    		………………………………….
    		Hashtable hst=new Hashtable();
    		hst.Add("param1",param);
    		hst.Add("param2",param);
    flash.Result=hst;
       }
    
    
    Listing 7
    
    function AsdResult(result)
    {
    	this.onResult=function(result)
    	{
    		_global.imgArr.clear();
    		_global.namesArr.clear();
    		_global.imagesToLoad=result.getLength();
    		for(var i=0;i<_global.imagesToLoad;i++)	
    		{
    			var hld="h"+i;
    			image.loadjpg(result.getItemAt(i).Url, hld);
    			_global.imgArr.push(image[hld]);
    			_global.namesArr.push(result.getItemAt(i).ImageName);
    		}
    	}
    	
    	this.onStatus=function(status)
    	{
    		stop();
    		trace("Error "+status.description);
    		_global.logStatus(status);
    	}
    }
    

    All Rights Reserved
    Copyright ©  2004 SYS-CON Media, Inc.

      E-mail: info@sys-con.com