Click here to Skip to main content
13,410,501 members (35,799 online)
Click here to Skip to main content
Add your own
alternative version


276 bookmarked
Posted 30 Jan 2006

Atlas Tutorial: Creating an AJAX Scribble application

, 5 Feb 2006
Rate this:
Please Sign up or sign in to vote.
A tutorial on creating an AJAX version of the popular MFC sample. The tutorial utilizes ASP.NET Atlas framework.

Please read instructions at the end of article on how to run the application after downloading the source.

Image in Internet Explorer Image in FireFox 


ASP.NET Atlas is a rich set of client side and server side libraries to develop AJAX-style applications using ASP.NET. This tutorial (and probably more in this series) attempts to provide a general view of the features available in Atlas. Since, Atlas is a very vast library this very first tutorial concentrates on two most important features of Atlas:

  1. Ability to call server side web services from client side scripts
  2. Ease of developing cross-browser compatible JavaScript code


MFC Scribble application was one of the first application that I used to learn MFC. Therefore, I decided to base this tutorial on Scribble. Scribble application allows users to draw freehand sketches using the mouse. I first saw a similar application on the web, utilizing AJAX technologies, at the JavaScript Draw website. The JavaScript draw website works only on Mozilla Firefox. This article describes how to build a cross-browser version of the application. We will build on the application in each article in this series to demonstrates more features of Atlas.

Installing Atlas

At the time of writing of this article, December CTP of Atlas can be downloaded by clicking this link. If this link does not work you can always go to the Atlas website to get the correct link. The Atlas library is available as a Visual Studio 2005 template (VSI). The download site has instructions on how to install the template.

Creating an Atlas Project

Once the Atlas template is installed you can create a blank Atlas project by clicking selecting the menu option: File -> New -> Web Site. This brings up the New Web Site dialog box as shown.

Visual Studio Project

Under location you can either select File System or HTTP. Selecting HTTP will allow you to create a web site on an IIS server and selecting File System will allow you to create a web site on your local file system (which you can debug and test using the ASP.NET development web server). You can select either option but I have found the application to work better with Internet Explorer on IIS.

Atlas Blank Project

The newly created Atlas web site has the following directory structure.

  • App_Data
    This is an empty directory where you can place data files.
  • Bin
    This is the directory where dll file for the assembly Microsoft.Web.Atlas is placed. This contains the server portion of the Atlas library.
  • ScriptLibrary
    A directory where you can place any JavaScript files for the application.
    • Atlas
      Atlas client Scripts are placed here in two different subdirectories.
      • Debug
        The debug version of Atlas client side JavaScript files are placed in this directory.
      • Release
        The release version of Atlas client side JavaScript files are placed in this directory. The scripts in this directory are more compactly written and have some debug code removed.

Atlas Client Scripts

The December release of Atlas has the following client scripts.

  • Atlas.js
    This is the core Atlas script file consisting of basic utility functions and client side controls and components.
  • AtlasCompat.js
    This file contains the Atlas compatibility layer for supporting Mozilla Firefox and Apple-iMac-Safari web browsers. This script ensures that Atlas code is cross browser compatible.
  • AtlasCompat2.js
    Additional functions to ensure compatibility for the Safari web browser, are included in this file.
  • AtlasRuntime.js
    This is a scaled down version of the core Atlas script file. This script file does not have the client side components and controls. This script file can be used when the aforementioned components or controls are not being used in a web page.
  • AtlasUIDragDrop.js
    This file contains utility functions to provide drag drop functionality in a web page.
  • AtlasUIGlitz.js
    This file contains utility functions to provide animation and other special effects in a web page.
  • AtlasUIMap.js
    This is the script file for Atlas mapping framework that uses Virtual Earth.

Other Files

Atlas adds the following files to the root directory of the web site.

  • Default.aspx and Default.aspx.cs
    This is a web page containing Atlas Script Manager control that is responsible for rendering script blocks referring to the Atlas client side scripts. An client script of type test/xml-script block is also added to the page. This script block is used to write scripts using declarative XML syntax.
  • eula.rtf
  • readme.txt
  • Web.Config
    The web.config is essential for running Atlas applications. It contains some configuration settings specific to Atlas and also adds the Atlas HTTP modules and HTTP handlers.

The Scribble Application

The Scribble application allows users to draw freehand sketches by clicking on the left mouse button and moving mouse around. A sketch stroke ends when the user releases the mouse button or moves outside the drawing area. There are ways to draw using JavaScript by utilizing VML, but we are not going to use VML in this sample.

The default web page in Scribble will have an image (a regular HTML image - the IMG tag). The user mouse events over the image are captured using JavaScript event handlers. The JavaScript functions send the series of points in a sketch stroke to a web service. The web service updates and image object saved in a session variable by drawing lines through all the points sent by the client. Finally, the client requests an updated image from the server. The image source is an HTTP handler which streams the image stored in the session variable to the client. Here are the main components of the application.

  • Default.aspx
    The page with the dynamic image and Atlas Script Manager control.
  • ScribbleImage.ashx
    This is an HTTP handler which streams the image object stored in the session variable.
  • ScribbleService.asmx
    This is the web service to which all the sketching requests are sent. The webservice modifies the image.
  • Scribble.js
    The JavaScript code for the application resides in this file to make a clear separation between design and the code.
  • Global.asax
    The Session_Start and the Session_End events are handled in Global.asax. The Session_Start creates the session variable and Session_End disposes the image stored in the session variable.


We begin our coding process from Global.asax.

  1. In the Website menu click on Add New Item or press Ctrl + Shift + A.
  2. In the Add New Item dialog box select Global Application Class and click ok. You will see the Global.asax file created.
  3. We start by importing the System.Drawing namespace. Insert the following line of code just after the first line.
    <%@ Import Namespace="System.Drawing" %>        
  4. Add the following code to Session_Start function.
    void Session_Start(object sender, EventArgs e)
        Bitmap bmp = new Bitmap(200, 200);
        using (Graphics g = Graphics.FromImage(bmp))
            g.FillRectangle(new SolidBrush(Color.White),
                new Rectangle(0, 0, bmp.Width, bmp.Height));
        Session["Image"] = bmp;
    The code creates a simple bitmap 200 pixels by 200 pixels white, paints the entire background white and assigns it to the session variable named Image.
  5. The Session_End function should dispose the image stored in the session variable.
    Bitmap bmp = (Bitmap)Session["Image"];
  6. From the Website menu select Add Reference.
  7. Select System.Drawing in the Add Reference dialog box and click OK
  8. Finally, in the Build menu click Build Web Site or press Ctrl + Shift + B to make sure that there are no build errors.


This web handler is supposed to stream the image stored in the session variable back to the client.

  1. In the WebSite menu click on Add New Item or press Ctrl + Shift + A.
  2. In the Add New Item dialog box select Generic Handler, set the name of the handler to ScribbleImage.ashx and click OK.
  3. For a web handler to use session variables it needs to implement the interface IRequiresSessionState. This is only marker interface and has no methods to override. Edit the class declaration to look like the following.
    public class ScribbleImage : IHttpHandler,
  4. Next we add code to the ProcessRequest method.
    public void ProcessRequest (HttpContext context) 
        context.Response.ContentType = "image/png";
        System.Drawing.Bitmap bmp =
            using (MemoryStream ms = new MemoryStream())
                bmp.Save(ms, ImageFormat.Png);
    • The first line sets ContentType header in the response to image/png. This make sure that the browser identifies the response to be a png image instead of HTML.
    • The next four lines indicate to the browser that the response should not be cached. All these four lines are necessary to make sure that the code is cross browser compatible. We will optimize the code in the later versions of the tutorial.
    • Finally, the bitmap from the session variable is saved to a memory stream and the contents of the memory stream are written to response. The BinaryWrite function is used, as the image is binary data.


We have means of initializing the session image and to stream the image contents as response. Now we need some method to add content to the image itself. We expect the clients to call on ScribbleService.asmx web service to add lines to the image.

  1. In the WebSite menu click on Add New Item or press Ctrl + Shift + A.
  2. In the Add New Item dialog box select Web Service, specify the name to be ScribbleService.asmx and click OK. Make sure that you uncheck Place Code in a Separate File.
  3. Import the namespace System.Drawing by adding the following line to the series of namespace imports.
    using System.Drawing;
  4. Next, we need to define a simple class for a point. We cannot use the System.Drawing.Point class as it is not XML serializable. In a later tutorial we will see how we can use System.Drawing.Point instead of the custom class. Add the following code just before the ScribbleService class declaration
    public class Point
       public int X;
       public int Y;
  5. Finally, we need to add a method to draw the sketch given a set of points. We add a web method Draw to our web service.
    [WebMethod(EnableSession = true)]
    public void Draw(Point[] points)
        Image scribbleImage = (Image)Session["Image"];
            using (Graphics g = Graphics.FromImage(scribbleImage))
            using(Pen p = new Pen(Color.Black, 2))
                if (points.Length > 1)
                    int startX = points[0].X;
                    int startY = points[0].Y;
                    for (long i = 1; i < points.Length; i++)
                        g.DrawLine(p, startX, startY,
                            points[i].X, points[i].Y);
                        startX = points[i].X;
                        startY = points[i].Y;
    • The attribute WebMethod(EnableSession = true) ensures that the session variables are accessible from the web service.
    • The image is locked to make sure that concurrent accesses are safe.
    • The drawing itself is pretty simple as it just joins the points supplied in the points array.


We have the server side image handler and the server side web service to update the image. Now we need the client side script in scribble application that will send the points from mouse events to the server web service.

  1. Highlight the ScriptLibrary folder in the solution explorer.
  2. In the WebSite menu click on Add New Item or press Ctrl + Shift + A.
  3. In the Add New Item dialog box select JScript File, sepcify the name to be Scribble.js and click OK. This will place Scribble.js in the ScriptLibrary folder.
  4. Next we need to to declare some global variables. In this first version of scribble we will use global variables but in the coming versions we start using JavaScript objects.
    //The HTML image element that is to be drawn
    var image;
    //The source of the image
    var originalSrc;
    //The number of iteration
    var iter = 0;
    //The array of points
    var points = null;
    The comments above the variable declaration describe the purpose behind each variable. The iter variable is used to modify the source of the image after a draw request is sent to the server. In case of Internet Explorer setting image.src = image.src does refresh the image but the same code does not work for Firefox. To work around this problem we maintain the variables iter which is incremented every time we send a Draw request to the Webservice. We add the iteration number to the originalSrc variable so that the browser thinks that the it needs to request the server to get fresh data as opposed to using the cached image.
  5. We define the function startStroke which starts a stroke in response to the mousedown event.
    function startStroke()
        points = new Array();
        window.event.returnValue = false;
    When a new stroke starts we create a fresh set of points as indicated by the first line. The second line cancels the default behavior of the event. This is necessary as the default behavior of the mousedown event for an image is to start a drag operation which prevents any further events from being fired.
  6. When a stroke ends in response to the mouseup event or mouseout event, we need to make the actual call to the webservice. This is done in the endStroke function.
    function endStroke()
        if (!points || points.length < 2)
            return true;
        //Send the points to the webservice
        ScribbleService.Draw(points, onWebMethodComplete,
            onWebMethodTimeout, onWebMethodError);
        points = null;
        window.event.returnValue = false;
    The only interesting line in the function is ScribbleService.Draw(points, onWebMethodComplete, onWebMethodTimeout, onWebMethodError); , which invokes the web service method Draw in ScribbleService.asmx asynchronously. The function is automatically made available to us by the Atlas framework.
  7. onWebMethodError is a function which gets invoked by Atlas framework when an error occurs in the web service method and onWebMethodTimeout gets invoked when the web method call exceeds a configurable timeout defined in the Atlas framework. In this version we just show the user a message box with the error text.
    function onWebMethodError(fault)
        alert("Error occured:\n" + fault.get_message());
    function onWebMethodTimeout()
        alert("Timeout occured");
  8. onWebMethodComplete function is called when the web method call is successful. The image needs to be reloaded when this happens.
    function onWebMethodComplete(result, response, context)
        //We need to refresh the image
        var shimImage = new Image(200, 200);
        shimImage.src = originalSrc + "?" + iter++;
        shimImage.onload = function()
            image.src = shimImage.src;

    We create an Image object shimImage and set its source to the original source of the image we are drawing on. When the image object loads we set the source of the actual HTML image element on the page to the source of the temporary image object. This is done to avoid flicker when replacing the image.
  9. We need to fill the points array during the mousemove event. This is done in the addPoints function.
    function addPoints()
        if (points)
            var point = { X : window.event.offsetX,
                Y : window.event.offsetY};
            if (points.length == 3)
                points = new Array();    
            window.event.returnValue = false;
    • A new point object is constructed with the offsetX and offsetY properties of the event object and then it is appended to the points array. The offsetX and offsetY properties give the relative mouse position with respect to the HTML element causing the event.
    • If the length of array has reached 3, we automatically request the server to do a draw operation and reset the points array. This is done so that the user can see the drawing before he releases the mouse button.
  10. Finally, we need to hook the events this is done in the pageLoad function.
    function pageLoad()
        var surface = document.getElementById("drawingSurface");
        image = surface.getElementsByTagName("IMG")[0];
        originalSrc = image.src;
        surface.attachEvent("onmousedown", startStroke);
        surface.attachEvent("onmouseup", endStroke);
        surface.attachEvent("onmouseout", endStroke);
        surface.attachEvent("onmousemove", addPoints);
    • The pageLoad function is a special function which gets invoked when the Atlas framework has finished loading. We use this instead of the regular window or body load events so that we can be sure that Atlas has finished loading.
    • The actual image element which gets sketched is placed, inside a div tag with an id of drawingSurface. The size of the element is same as the size of the image so we can safely attach to the events to the drawingSurface div.


The individual components of the application need to be assembled in the Default.aspx page. Here is the code of this page.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"

    Inherits="_Default" %>


<html xmlns="">
<head runat="server">
    <title>Atlas Scribble Sample</title>
    <form id="form1" runat="server">
        <Atlas:ScriptManager ID="AtlasScriptManager" runat="server"

            EnableScriptComponents="False" >
    <Atlas:ServiceReference Path="ScribbleService.asmx" />
    <Atlas:ScriptReference Path="ScriptLibrary/Scribble.js" />
        <div id="drawingSurface"

            style="border:solid 1px black;height:200px;width:200px">
        <img alt="Scribble" src="ScribbleImage.ashx"

            style="height:200px;width:200px" galleryimg="false" />

The most important aspect of this page is the atlas:ScriptManager server control. The ScriptManager server control is responsible for generating client side script blocks for Atlas and for any web service proxy scripts. Lets examine the usage of the ScriptManager control in the Default.aspx page.

  1. The EnableScriptComponents property is set to false. This generates a client side script block referring to AtlasRuntime.js instead of Atlas.js. We prefer the lightweight version of Atlas Framework in this version of scribble as we are not using any Atlas components or controls.
  2. We add a service reference to the ScribbleService.asmx web service. This will generate a URL reference to client side script for the web service proxy.
  3. We add the Scribble.js as another script reference.

This brings all the pieces together and now you can compile and run the project. I encourage you to see the actual client html generated by the Atlas Script Manager.

The Atlas Magic

Here is what Atlas framework did for us.

  1. It allowed us to write the web application without us making special efforts to make it cross browser. The web service invocation and the client side event handling automatically works on both Internet Explorer and Firefox. The Atlas framework adds the required JavaScript prototypes to Firefox objects to make them look like Internet Explorer objects. The Internet Explorer specific functions like attachEvent and event.offsetX and event.offsetY are made available to Firefox. You can look at AtlasCompat.js file to see how this is done.
  2. It automatically created a JavaScript proxy for the Scribble web service methods. The JavaScript proxy script file for an ScribbleService.asmx file has the URL ScribbleService.asmx/js. This is generated by the Atlas HTTP module added in the web.config.

Where are We

We have seen how to call web services and how to write cross browser applications with ease using Atlas. In an upcoming tutorial we see more of Atlas client side controls and declarative programming (depending on user feedback!). If you liked the tutorial please free to write a comment. If you did not like it please write a comment on how to improve it.

Downloading and Running the Source

As Atlas is not yet redistributable, I have not included the Atlas files in the source download. Here are the steps you need to get the downloaded source to work.

  1. You need to download Atlas from Atlas Web Site.
  2. After downloading the Atlas blank project template create a new Web Site by pointing to New in the File menu and selecting Web Site
  3. Extract the source zip file to the directory of newly created projects overwriting any existing files.
  4. In the Website menu select Add Existing Item, add ScribbleService.asmx and ScribbleImage.ashx from the root directory of the website, and Scribble.js from the ScriptLibrary folder.
  5. Build and run the web site.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Rama Krishna Vavilala
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

GeneralJavascript Error - Help! Pin
yaronsimpson23-May-06 1:09
memberyaronsimpson23-May-06 1:09 
GeneralAJAX vs Webservices Pin
icestatue9-May-06 3:42
membericestatue9-May-06 3:42 
GeneralRe: AJAX vs Webservices Pin
secretGeek_net5-Jul-06 18:18
membersecretGeek_net5-Jul-06 18:18 
Generalmake it work in April Atlas and a suggestion in addPoints() Pin
mmelihh21-Apr-06 0:22
membermmelihh21-Apr-06 0:22 
GeneralGreat! using chinese is "&#39030;" Pin
Li Xiaojian(China)12-Apr-06 22:39
memberLi Xiaojian(China)12-Apr-06 22:39 
QuestionWorking example for April Atlas? Pin
John W Cole12-Apr-06 12:52
memberJohn W Cole12-Apr-06 12:52 
Generalbehaviour IE Pin
harvey20077-Apr-06 9:50
memberharvey20077-Apr-06 9:50 
JokeGreat Article! (but advice for those new to javascript) Pin
Nick Vuono6-Apr-06 8:24
memberNick Vuono6-Apr-06 8:24 
Reading your article gave me the idea to revisit the dynamic graph generation library I'd come up with a long time ago and improve it using ATLAS to stream the image via the xml data provider. This way I could eliminate the file-system overhead I was dealing with previously when I generated the graphs and had to save them to bmps on the hard drive at postback.

Unfortunately I spent many hours trying to debug it when I was getting the javascript error:
"Object does not support this property or method"

Being new to javascript I had no idea what this error message meant so I thought it could be occuring because of invalid method arguments, a problem with the session state, or perhaps an exception somewhere in the service itself...

The only reason I really got this error was because I had capitalized my C in the call to createNewGraph:
"Service.createNewGraph(SrchElem.value, graphComplete);"

ahh.. the joys of mashing VB, C#, XML and Javascript together!
QuestionI can't get it working with March CTP of Atlas. Pin
gbrown53927-Mar-06 8:17
membergbrown53927-Mar-06 8:17 
AnswerRe: I can't get it working with March CTP of Atlas. Pin
Rama Krishna Vavilala27-Mar-06 8:20
memberRama Krishna Vavilala27-Mar-06 8:20 
GeneralRe: I can't get it working with March CTP of Atlas. Pin
gbrown53927-Mar-06 8:28
membergbrown53927-Mar-06 8:28 
GeneralRe: I can't get it working with March CTP of Atlas. Pin
sikemullivan1-Apr-06 8:14
membersikemullivan1-Apr-06 8:14 
GeneralRe: I can't get it working with March CTP of Atlas. Pin
thales-is19-Apr-06 7:30
memberthales-is19-Apr-06 7:30 
GeneralRe: I can't get it working with March CTP of Atlas. Pin
sikemullivan19-Apr-06 7:57
membersikemullivan19-Apr-06 7:57 
AnswerRe: I can't get it working with March CTP of Atlas. Pin
steve_cooper26-Sep-07 10:18
membersteve_cooper26-Sep-07 10:18 
Generalnice work Pin
The_Myth19-Mar-06 22:29
memberThe_Myth19-Mar-06 22:29 
Generalerror, can not run Pin
Knight_Yun14-Mar-06 22:27
memberKnight_Yun14-Mar-06 22:27 
GeneralCannot Draw with AJAX Scribble Pin
Stuart Gygi7-Mar-06 7:29
memberStuart Gygi7-Mar-06 7:29 
GeneralRe: Cannot Draw with AJAX Scribble Pin
Rama Krishna Vavilala7-Mar-06 7:44
memberRama Krishna Vavilala7-Mar-06 7:44 
GeneralNice code but doesn't work in browser Pin
Fille853-Mar-06 2:58
memberFille853-Mar-06 2:58 
GeneralRe: Nice code but doesn't work in browser Pin
Rama Krishna Vavilala3-Mar-06 4:20
memberRama Krishna Vavilala3-Mar-06 4:20 
GeneralA great introduction Pin
PeterSQ1-Mar-06 4:13
memberPeterSQ1-Mar-06 4:13 
GeneralCompile Errors on January Release Pin
Stuart Gygi28-Feb-06 17:35
memberStuart Gygi28-Feb-06 17:35 
GeneralRe: Compile Errors on January Release Pin
Rama Krishna Vavilala1-Mar-06 4:26
memberRama Krishna Vavilala1-Mar-06 4:26 
GeneralRe: Compile Errors on January Release Pin
Stuart Gygi4-Mar-06 10:04
memberStuart Gygi4-Mar-06 10:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.180221.1 | Last Updated 5 Feb 2006
Article Copyright 2006 by Rama Krishna Vavilala
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid