Introduction
This is a short series of articles about Abstract Programming. This series is broken up into three parts. The first part is an overview of Abstract Programming, and how and when one program authors another program. The second part is a look at C# code authoring a JavaScript file at design time. The third part details how Abstract Programming can be used at runtime to create JavaScript that will serve as a .NET DataSet
, only living on the client. By using Abstract Programming, you can eliminate unnecessary postbacks, and realize the possibility of an application program running unplugged.
The methods used in this series are intended to create solutions that will run in all browsers. These examples were tested in both Internet Explorer and Netscape, but all the development was done with Internet Explorer. The examples and exercises were developed with the .NET 2.0 Framework using Visual Studio 2005 and SQL Server 2005, but the concepts of Abstract Programming are independent of any particular technology. This three-part short series was created using the techniques described in this series.
Overview
Traditionally, JavaScript was created at design time, by a human author. This author put JavaScript code in a .js file, then published his JavaScript for web applications to utilize. Now, we are ready for another approach to delivering a richer designer and user experience. This can be accomplished by understanding how JavaScript can be authored automatically. This part goes into detail on how you can create a solution that will author DScript (a JavaScript file) with a server control at design time. The next part, Part 3, will detail how the server can create a DScript file, at runtime, to represent data as a data table.
ClientScriptManager
The .NET 2.0 Framework has given us several methods to invoke JavaScript from an ASP.NET WebForm. Both RegisterStartupScript
and RegisterClientScriptBlock
allow you to put JavaScript into your WebForm at runtime, when the page is loaded. This is Abstract Programming at its finest, with one slight problem. This has the same problems as any JavaScript that is inline with the HTML, and that is: that it is downloaded every time the page is loaded. So... is there another way to abstract programs without producing an inline solution? Yes, and that is to create at design-time, a DScript file that is effectively doing the same thing, only from the client. Following is a completely different approach that abstracts the JavaScript code creation process to a routine written in C#, that executes from an ASP.NET server control.
CClock (A Real-World Example)
In this exercise, we will create a simple web page, with an analog looking clock. This exercise uses a server control to author DScript (a JavaScript file) that will provide details on how to display the clock. These details include the position of the clock, and the size of the clock.
Components Used in the Exercise
- CClock1.js - This is the DScript that is generated by the server control at design time. It is saved in a folder named "DScripts". The actual name of the file will be slightly different to allow using the component on different pages. So the actual name might be something like "ProMatrix.TestControls.CClock.Default.CClock1.js" to signify the actual path to the page that uses this DScript.
- CClock.js - This is a human authored JavaScript file that knows everything necessary to create a clock control, except where to actually put the clock on the WebForm, and how big to make the clock control. These values will be passed in as arguments to its rendering methods. This JavaScript also creates the entire control client-side, so if you do a "View/Source" on the web page, you will see no trace of a clock control HTML markup.
- CClock.cs - This is the C# code that responds to the moving of the clock control on the WebForm by writing a DScript file that details the absolute position of the control, and its size and shape, by width and height.
Step by Step
The developer drags the control from the designer toolbox, and places it on his .NET WebForm. Then, he begins moving the control to the appropriate location on the .NET WebForm. While he’s moving the control, DScript (a JavaScript file) is being authored for use at runtime. This is accomplished by writing DScript to the disk, that contains the location and the absolute position of the control. It is considered Abstract Programming because we have abstracted the process of generating the client code (DScript) by authoring the JavaScript through the Visual Studio environment. More accurately, the JavaScript is authored by an ASP.NET server control whose C# code is being executed at design time.
No Experience Necessary
After you have implemented a server control with this model, you can release it to developers to use the control without needing to know the details about how it works. That's because the DScript is created automatically by the server control. Then, at runtime, the server control will reference the DScript in the web page. The details of creating the JavaScript are completely and totally abstracted from the development process.
OK, Drill Down Time
Now, let's look at the project and drill down on it... First, download and install the projects in the appropriate location, in accordance to the readme.txt file supplied in the source code Zip file. The readme file will spell out the requirements and supply you with some quick installation notes. After installing, open up the solution "Unplugged", and make "TestControls" the startup project. Next, in the CClock folder, set "default.aspx" as the default startup page, and run the page in Debug by pressing F5. You should see a clock ticking away and displaying the current local time.
Now, stop the debug session. Let's change the position of the clock on the WebForm. Where is the location information stored? As part of the server control's properties? No... The resource data representing the size and positioning information is stored in a DScript (JavaScript) file, in the DScript folder. Let's look at that file. Please open the DScript file in the Visual Studio Designer by dragging and dropping the file "ProMatrix.TestControls.CClock.Default.CClock1.js" from the DScript folder.
With the DScript file "ProMatrix.TestControls.CClock.Default.CClock1.js" still in the Visual Studio Designer, go back to the clock on the WebForm Default.aspx, and move it around in the WebForm Designer. You should see this dialog. Choose Yes to this dialog, then view the DScript file "ProMatrix.TestControls.CClock.Default.CClock1.js" again. You should see the changes you made as a result of moving the clock around on the WebForm.
It looks like this...
Clk_pos_width = 50;
Clk_pos_height = 50;
Clk_pos_L = 130;
Clk_pos_T = 120;
Clk_image_T = 70;
Clk_image_L = 80;
Clk_zIndex = 0;
Clk_image = '/ProMatrix.TestControls/CClock/Images/CClock.gif';
Clk_image_L_offset = -20;
Clk_image_T_offset = -20;
Clk_image_W_offset = 40;
Clk_image_H_offset = 40;
What actually happened
While you were moving the clock around on the WebForm, it was executing code, which wrote, to disk, a new version of "ProMatrix.TestControls.CClock.Default.CClock1.js", with the new sizing and positioning information. Below is the C# server control code that was responsible for creating or updating the DScript.
void SaveJSfile()
{
if (!designMode) return;
StreamWriter sw = new StreamWriter(dScriptsPath +
getDScriptName() + ".js");
double clk_half_width = _width.Value / 2;
double clk_half_height = _height.Value / 2;
double clk_pos_left = pxToVal2(getStyleAttribute("left")) +
clk_half_width;
double clk_pos_top = pxToVal2(getStyleAttribute("top")) +
clk_half_height;
string zIndex = getStyleAttribute("z-index");
if (zIndex == "") zIndex = "0";
sw.WriteLine("Clk_pos_width = " + clk_half_width + ";");
sw.WriteLine("Clk_pos_height = " + clk_half_height + ";");
sw.WriteLine("Clk_pos_L = " + clk_pos_left.ToString() + ";");
sw.WriteLine("Clk_pos_T = " + clk_pos_top.ToString() + ";");
sw.WriteLine("Clk_image_T = " +
pxToVal(getStyleAttribute("top")) + ";");
sw.WriteLine("Clk_image_L = " +
pxToVal(getStyleAttribute("left")) + ";");
sw.WriteLine("Clk_zIndex = " + zIndex + ";");
sw.WriteLine("Clk_image = '" + _image + "';");
sw.WriteLine("Clk_image_L_offset = " + _image_offset_L.Value + ";");
sw.WriteLine("Clk_image_T_offset = " + _image_offset_T.Value + ";");
sw.WriteLine("Clk_image_W_offset = " + _image_offset_W.Value + ";");
sw.WriteLine("Clk_image_H_offset = " + _image_offset_H.Value + ";");
sw.Close();
}
This information that the server control is writing to the DScript file contains the the values passed in by the Visual Studio Designer as you are changing the position and shape of the clock. The important part about this type of Abstract Programming is that the server control is abstracting the generation of the DScript at design time. Then, at runtime, the server control simply references this DScript that it created earlier.
Summary
DScript is JavaScript that is authored dynamically, either at design time, or at runtime. This model of abstract programming uses an ASP.NET server control to author DScript at design time. Within the server control (CClock.cs) is code that will execute at design time while you are positioning the control on the WebForm. The code that executes at design time actually authors a DScript file that contains the positioning information. Then, at runtime, this DScript file is referenced by the server control it loads and executes, and looks to the browser just like any other ordinary JavaScript. All of this happens automatically, without any human intervention.
Using the source
Download the Zip file, then extract the files into your C:\Inetpub\wwwroot as per the instructions in the Install.Readme.txt. Follow the instructions to setup and use the source code and to setup the browser.