Click here to Skip to main content
Click here to Skip to main content

Smart Code Generator: Use ASP.NET, NAnt and Cassini for Code Generation

, 27 Oct 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
This article describes how NAnt and Cassini can be integrated with the Smart Code Generator development cycle. This article can also used as a reference for ASP.NET developers who want to build, run and deploy ASP.NET projects seamlessly using NAnt and Cassini.

Screenshot - image001.jpg

Introduction

This article describes how NAnt and Cassini can be integrated with the Smart Code Generator development cycle. As a result of this, SCG developers and users are introduced to a very powerful code generation experience. This article can also used as a reference for ASP.NET developers who want to build, run and deploy ASP.NET projects seamlessly using NAnt and Cassini.

Smart Code Generator

SmartCodeGenerator is an ASP.NET 2.0 website OR an ASP.NET 1.1 web application and is a fully-fledged template-based code generator that allows you to generate code for any text language. Templates are written in Visual Studio as ASP.NET User Controls.

The current feature list of SmartCodeGenerator includes:

  • SCG Project is an ASP.NET Web project that uses existing ASP.NET 2.0 or ASP.NET 1.1 web application concepts
  • All development can be done in VS2005 or VS2003
  • SCG Projects can be run on Cassini Webserver
  • SCG Projects can be built and run using NAnt
  • Extensible Template Generation Engine
  • Open source Database Schema discovery API for MSSQL, Oracle and MySQL
  • Generates text based output
  • Generates output in batch mode
  • Fully customisable template-based code generation
  • Remembers custom property data entries
  • Intellisense, compilation, debug, code snippet, souce view, design view and all other countless features that are offered by the Visual Studio IDE

The entire development life cycle of creating custom templates using SmartCodeGenerator is done using Visual Studio by creating an ASP.NET application. Also, templates are ASP.NET User Controls, so during the generation of templates, intellisense, compilation, debug, sourceview, design view, CodeBehind file and all other features of Visual Studio (2005 or 2003) are available to you.

For the latest downloads please refer to Codeplex. This article is based on CTP 2.7 and tries to answer how to use SmartCodeGenerator along with NAnt and Cassini for template based output. This demonstration will focus on using SCG with Command Line options using NAnt and Cassini web server. For an architectural overview and usage overview of the SCG framework please refer to the following two articles at The Code Project,

"SmartCodeGenerator - Code Generation experience with Visual Studio and ASP.NET- Architectural Overview".

"SmartCodeGenerator - Code Generation experience with Visual Studio and ASP.NET- Usage Overview".

Cassini

Cassini is a mini web server written with 100% managed C# code, moreover Cassini is free. Cassini requires as an operating system either Windows 2000 or Windows XP; furthermore, the .NET Framework must also be installed. I am not going into further details of Cassini here, for more information please visit the Cassini Forum. All we need to know is Cassini is an independent web server and has the capability of running ASP.NET application locally and as SCG is a pure ASP.NET application, we can take full advantage of Cassini. With Cassini installed, the end user does not require Internet Information Server (IIS) or Visual Studio to be installed to run SCG Projects.

To run SCG Projects with Cassini mini web server

1. Download the latest build of Cassini from Microsoft's www.asp.net Web site.
2. Install Cassini using the instruction provided by the Cassini Team.

NAnt

NAnt is a .NET implementation of Ant. NAnt is a build tool written in C# and requires the .NET Framework to be installed. NAnt scripts are fairly easy to understand and are written in standard XML syntax. The core concept of NAnt includes project, property, target and task. A Project holds properties and targets, while target can hold multiple tasks. A sample NAnt script may look like the following where I have declared some properties and a target which executes the scg_console.exe. The complete script is saved with a .build extension:

<?xml version="1.0"?>

   <project name="SCG" default="build" basedir=".">

      <!--      -  Property definitions    -->

      <property name="projectPath" 
value="C:\Smartcodegenerator3\" overwrite="false" />

      <property name="scgConsoleAppPath" 
value="C:\SmartCodeGeneratorConsole\bin\ " 
overwrite="false" />

      <property name="port" value="1212" overwrite="false" />

      <property name="virtualPath" value="/" overwrite="false" />

      <property name="url" 
value=<a href=""http://localhost:1212/default_console.ASPx"">http://localhost:1212/default_console.ASPx</a> 
overwrite="false" />     

     <target name="runwithoutbuild" 
description="runs scg commandline and generates output">

       <exec basedir="${projectPath}" 

             program="${scgConsoleAppPath}/scg_console.exe" 

             commandline="${projectPath} ${port} ${virtualPath} ${url}"  

             workingdir="${projectPath}" 

             failonerror="true" />

     </target>

   </project>


SCG projects are ASP.NET 2.0 website projects and we can use NAnt to compile, build and run SCG projects.

To run SCG Projects with NAnt build tool

1. Download the latest build of NAnt from Source Forge Web site.
2. Install NAnt using the instructions provided by the NAnt Team.

Building SCG Projects or ASP.NET 2.0 Website Projects with NAnt

I will assume that both Cassini and NAnt has been installed and now we are going to write our NAnt script which will build an ASP.NET 2.0 website project. NAnt uses the ASPnet_compiler that ships with the .NET Framework 2.0, although we can call the ASPnet_compiler from a command line seperately using the following syntax:

ASPnet_compiler [-?] [-m metabasePath | -v virtualPath [-p physicalDir]]

                [[-u] [-f] [-d] [-fixednames] targetDir] [-c]

                [[-keyfile file | -keycontainer container]

                     [-aptca] [-delaySign]]

                [-errorstack]

Let also look at the –v and –p switch for our need. To see full details please use the -? switch.

-v The virtual path of the application to be compiled (e.g.

"/MyApp"). If -p is specified, the physical path is used to

locate the application. Otherwise, the IIS metabase is used, and

the application is assumed to be in the default site (under

"/LM/W3SVC/1/Root"). This switch cannot be combined with the -m

switch.

-p The physical path of the application to be compiled. If -p is

missing, the IIS metabase is used to locate the app. This switch

must be combined with -v.

The following command does not rely on the IIS metabase, as it explicitly specifies the physical source directory of the application:

ASPnet_compiler -v / -p c:\smartcodegenerator3 

To use NAnt for compiling, we first have to create an XML file that ends in the extension .build. Here's an example script that does the same thing as the single command line above.

<?xml version="1.0"?>

   <project name="SCG" default="build" basedir=".">      

      <!--      -  Property definitions      -->

      COMMENT: tell this script where the ASPnet_compiler.exe file resides...

      <property name="dotnetPath" 
value="c:/windows/Microsoft.NET/Framework/v2.0.50727" 
overwrite="false"/>

      <property name="projectPath" 
value="C:\smartcodegenerator3\" overwrite="false" /> 
      <!--

      - 'build'

      -

      - Precompiles this ASP.NET application

      - into the defined directory.

      -->

      <target name="build" description="compiles the source code">         

         <echo message="Build Directory is ${projectPath}" />

         <exec basedir="${projectPath}" 

               program="${dotnetPath}/ASPnet_compiler.exe" 

               commandline="-nologo -v /SCG.deploy -p ${projectPath}"  

               workingdir="${projectPath}" 

               failonerror="true" />

         <echo message="ASP.NET Compilation Successful" />

      </target>     

   </project>

Once you've created a build file, to build your project, you simply execute the command line:

nant

As long as the current directory contains the .build file, and the NAnt executable itself is in your current PATH environment variable, that's all you need to type. NAnt will parse the contents of the default.build file and perform the tasks specified in the file. The above script will try to compile the SCG Project or an ASP.NET Website Project and display theresult.

Let's compile an SCGTemplate which has the following piece of code:
Current Time is: <%=DateTime.Now.ToLongTimeString()%>

<%for (int i = 0; i < 5; i++)

  {%>

      Cool      

  <%} %>
Current Time is: <%=DateTime.Now.ToLongTimeString()%>

The build succeeded and the output looks like the following:

Screenshot - image001.jpg

Lets introduce a bug in the code by adding a "semicolon ;" after DateTime.Now.ToLongTimeString() and recompile.

Current Time is: <%=DateTime.Now.ToLongTimeString()%>

<%for (int i = 0; i < 5; i++)

  {%>

      Cool      

  <%} %>
Current Time is: <%=DateTime.Now.ToLongTimeString();%>

This time the build fails and the output looks like the following:

Screenshot - image002.jpg

You should note that the compilation errors are identified and displayed.

Building an SCG Project is easily achieved but we can run the project from the NAnt environment, and display the generated code in a command prompt screen. We will discuss this in the following section.

Running an SCG Project or an ASP.NET 2.0 website project using NAnt and Cassini

I will assume that Cassini and NAnt have already been installed. We are aware that SCG Projects are ASP.NET 2.0 website projects and SCG Templates are ASP.NET User Controls. To that end, to host these projects we need a web server capable of running ASP.NET, and IIS and Cassini come to mind. If you want to avoid the hassle of installing IIS and creating a virtual directory inside IIS, you can choose the Cassini mini web server. What I have written here is a small console application that starts and stops a Cassini Web Server programmatically. Let's examine this code closer:

static void Main(string[] args)
{
            ParseArgs(args);           
            System.IO.Stream st = null;
            System.IO.StreamReader sr = null;
            Cassini.Server server = null;
            try
            {
                Console.WriteLine
("Cassini server starting...at..{0} {1} {2} {3}", 
_appPath, _portString, _virtRoot, _url);
                
                if (_appPath.Length == 0 || !Directory.Exists(_appPath)) 
                    throw new Exception ("Invalid physical path).");
                               
                int portNumber = -1;
                int.TryParse(_portString, out portNumber);                
                if (portNumber <= 0)
                    throw new Exception("Invalid port");
                
                if (_virtRoot.Length == 0 || !_virtRoot.StartsWith("/"))
                    throw new Exception("Invalid virtual path");
                
                server = new Server(portNumber,_virtRoot,_appPath);
                server.Start();            
                Console.WriteLine("Cassini server started...");
                Console.WriteLine("Invoking <a href=""{0}"">url:{0}",_url</a>);
                System.Net.WebRequest req = 
                 System.Net.WebRequest.Create(_url); 
                // get the response and read from the result stream
                               
                System.Net.WebResponse resp = req.GetResponse();
                if (resp == null)
                    throw new Exception("WebResp is null");
                
                st = resp.GetResponseStream();
                sr = new System.IO.StreamReader(st);
                // read all the text in it
                Console.WriteLine(sr.ReadToEnd()); 
                Console.WriteLine("SCG Page Invoked Successfully");
            }
        …
            finally
            {
                …
                if (server!=null)
                    server.Stop();
                Console.WriteLine("Cassini Server Stopped...");                
            }
}

This console application expects 4 arguments: <physical-path>, <port>, <virtual-path> and <url>. Missing any of the arguments will throw an exception. Then, it instantiates the Cassini Web Server passing the <port>, <virtual-path> and <physical-path> as parameters, then calls the server.Start() method. As a result this hosts the ASP.NET website in the Cassini Web Server, and then I programmatically send a WebRequest to the recently started server. A response is received and is printed on the screen and as a final step, I stop the Cassini Web Server. The following command starts a Cassini Web Server, host a defined SCG project or ASP.NET website project and displays the response returned from the defined url parameted:

// Command line: <physical-path> <port> <virtual-path> <url> 
// Example: scg_console c:\foo 1212 / http://localhost:1212/default.aspx 


To do the same thing using NAnt, we can modify the NAnt script outlined above. Here's an example script that does the same thing as the single command line above.

<property name="scgConsoleAppPath" value="C:\SmartCodeGeneratorConsole\bin\Debug\" 
overwrite="false" />
      <property name="port" value="1212" overwrite="false" />
      <property name="virtualPath" value="/" overwrite="false" />
      <property name="url" value="<a href=""http://localhost:1212/default_console.aspx"">http://localhost:1212/default_console.aspx</a>" overwrite="false" />     

      <!--
      - 'run'
      -
      - Depends on build.
      - If build successful then Starts Cassini Web Server on the defined port and 
      - sends the WebRequest to the defined url
      -->
     <target name="run" depends="build" description="builds and then runs scg commandline  
and generates output">       
       <exec basedir="${projectPath}" 
             program="${scgConsoleAppPath}/scg_console.exe" 
             commandline="${projectPath} ${port} ${virtualPath} ${url}"  
             workingdir="${projectPath}" 
             failonerror="true" />
     </target>
    

Here I introduced new properties called scgConsoleAppPath, port, virtualPath and url. Furthermore, I introduced a new target named "run" which depends on the previously written target "build" and executes the scg_console.exe with the desired arguments. Let's see this in action with the following SCG Template.

Current Time is: <%=DateTime.Now.ToLongTimeString()%>
<%for (int i = 0; i < 5; i++)
  {%>
      Cool      
  <%} %>
Current Time is: <%=DateTime.Now.ToLongTimeString();%>


Let's fire up NAnt and execute the following command in a command line:

nant run 

We will see the following output:

C:\SmartCodeGenerator3>nant run
NAnt 0.85 (Build 0.85.2478.0; release; 14/10/2006)
Copyright (C) 2001-2006 Gerry Shaw
<a href=""http://nant.sourceforge.net/"">http://nant.sourceforge.net</a>
Buildfile: <a href=""file:///C:/SmartCodeGenerator3/scgproj.buildTarget"">file:///C:/SmartCodeGenerator3/scgproj.build
Target</a> framework: Microsoft .NET Framework 2.0
Target(s) specified: run

build:
     [echo] Build Directory is C:\Smartcodegenerator3\
     [echo] ASP.NET Compilation Successful
run:
     [exec] Cassini server starting...at.. 
            C:\SmartCodeGen3\
testproject\Smartcodegenerator3\ 1212 / 
<a href=""http://localhost:1212/default_console.aspx"">http://localhost:1212/default_console.aspx</a>
     [exec] Cassini server started...
     [exec] Invoking <a href=""http://localhost:1212/default_console.aspx"">url:http://localhost:1212/default_console.aspx</a>
     [exec] Current Time is: 7:53:09 PM
     [exec]       Cool
     [exec]
     [exec]       Cool
     [exec]
     [exec]       Cool
     [exec]
     [exec]       Cool
     [exec]
     [exec]       Cool
     [exec]
     [exec] Current Time is: 7:53:09 PM
     [exec] SCG Page Invoked Successfully
     [exec] Cassini Server Stopped...
BUILD SUCCEEDED
Total time: 8.6 seconds.

Notice the SCG project or ASP.NET website project is first compiled using the aspnet_compler.exe, furthermore on a successful build the scg_console.exe file is executed, which starts the Cassini server, displays the generated output of the SCG Template and finally stops the server.

Changes in SCG Projects to integrate with NAnt and Cassini

If you have already read the SCG Architectural Overview, you should be aware that SCG has 2 Pipelines: LoadUIProperty Pipeline and Generate (Output) Pipeline.

LoadUIProperty Pipeline:


Screenshot - image003.gif

OnPreLoadUIProperties: Called before UIProperty is generated.
OnLoadUIProperties: Called during UIProperty generation.
OnLoadUIPropertiesComplete: Called after UIProperty generation



Generate (Output) Pipeline:

Screenshot - image004.gif

OnPreGenerate: Called before generating output.
OnGenerate: Called during output generation.
OnGenerateComplete: Called after output generation is complete.
OnCleanTheProperties: A final event to allow cleaning.

When running SCG in a command line we do not need to generate a custom property user interface (UIProperty) as users are not expected to pass these property values over GUI, so LoadUIProperty Pipeline can be ignored. We can pass default property values using the TheProperties Class or programmatically via code.

If you look carefully in the default_console.aspx.cs, you will notice that I do not bind to any of the LoadUIProperty Pipeline related events (OnPreLoadUIProperties. OnLoadUIProperties, OnLoadUIPropertiesComplete). Everything else is same as before, except here the Generate_PipeLine is executed in the Page_LoadComplete event instead of the OnButtonClick event.

    protected void Page_LoadComplete( object sender, EventArgs e)
    {
        Hashtable dict = new Hashtable();        
        ScEventArgs args = new ScEventArgs(dict);
        Generate_PipeLine(sender, args); 
    }

Then I write the output with a Response.Write in the OnGenerateComplete event, which eventually gets displayed in the console at runtime.

 void _Default_OnGenerateComplete(object sender, EventArgs e)
 {        
     Response.Write(((ScEventArgs)e).Item["report"].ToString());
 }

Another thing to notice in the default_console.aspx page is that I do not have any body tags, all you will find on that page is:

<%@ Page Language="C#" AutoEventWireup="true" 
CodeFile="Default_Console.aspx.cs" Inherits="_Default_Console" %> 

All the other process of SCG development cycle still remains the same as described in other articles "Architectural Overview", "Usage Overview", only instead of using an automatically generated UI; we use the command line and pass property values programmatically. And good news is there is no changes required in the existing SCG templates. This makes the SCG Template generation experience very handy for the SCG Developers as he/she can use command line options to compile / debug the project and can also see the output immediately on the screen. Also any dependency on IIS or Visual Studio can be avoided.

I have demonstrated here how to use Cassini Web Server but IIS can serve the same purpose too. In that case you have to tweak the scg_console.exe application a bit and not instantiate Cassini.Server, and point the url to a virtual directory of IIS. I have also demonstrated here how to use NAnt but again, it is also not mandatory to use NAnt, an SCG Developer can easily use command line tools aspnet_compiler.exe and scg_console.exe directly in a command line to execute a compilation.

Running an SCG Project or an ASP.NET 2.0 website with Cassini alone

I'll assume Cassini has been downloaded and installed. I'll now demonstrate how to run GUI based SCG Projects with Cassini mini webserver alone.

1. Point Cassini to your desired SCG Project Folder. To do this specify port, virtual and physical path, for example

CassiniWebServer c:\temp\ExampleProject 1234

In this example the physical path of the SCG Project "c:\temp\ExampleProject" and port "1234" is specified.

Screenshot - image005.jpg

If you have used the default Cassini installation path the CassiniWebServer.exe will be located in the "C:\Cassini" Folder.

Screenshot - image006.jpg

Run Cassini pointing to the desired SCG Project folder.

Screenshot - image007.jpg

c:\cassini\CassiniWebServer c:\temp\ExampleProject 1234

Here physical path c:\temp\ExampleProject and port 1234 has been specified.

This will bring the following screen showing Cassini Mini Web Server has successfully run with the desired SCG Project.

Screenshot - image008.jpg

2. Browse to the SCG Project using Internet Explorer. We loaded our SCG Project in port 1234 so we have to browse using http://localhost:1234/


Screenshot - image009.jpg

Conclusion

SCG is a very powerful code generation Framework, which uses 100% ASP.NET. Based on the feedback from the community, I demonstrated how to run SCG Projects with command line tools like aspnet_compiler.exe and scg_console.exe. Furthermore, I demonstrated how to integrate NAnt and Cassini in to the SCG development cycle, but SCG can do much more than just this. This article can also used as a reference for ASP.NET developers who want to build, run and deploy ASP.NET projects seamlessly using NAnt and Cassini.

Thank you for being with me so far and please join the community and share your SCGTemplates and UIProperties.

Proof reading done by: Christopher Heale

Resources and Links related to SmartCodeGenerator

Download source code and releases at Codeplex.
Community: http://community.smartcodegenerator.com.
Community Forums: http://community.smartcodegenerator.com/forums/default.aspx Tutorials: http://www.smartcodegenerator.com.
Team Blog: http://community.smartcodegenerator.com/blogs/team_blog/default.aspx
And My Blog:
http://www.geekswithblogs.net/shahed.
http://msmvps.com/blogs/shahed

License

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

Share

About the Author

Shahed.Khan
Web Developer
Australia Australia
I have been awarded MVP (Visual C#) for year 2007, 2008, 2009. I am a Microsoft Certified Application Developer (C# .Net). I currently live in Melbourne, Australia. I am a co-founder and core developer of Pageflakes www.pageflakes.com and Founder of Simplexhub, a highly experienced software development company based in Melbourne Australia and Dhaka, Bangladesh. Simplexhub.
My BLOG http://www.geekswithblogs.net/shahed
http://msmvps.com/blogs/shahed/Default.aspx.

Comments and Discussions

 
GeneralCassini no longer available Pinmemberwindrago5-Jun-08 6:29 
GeneralRe: Cassini no longer available Pinmemberscott.leckie22-Sep-08 0:40 
GeneralNice Post Pinmember[hassan]22-Mar-07 5:03 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411023.1 | Last Updated 28 Oct 2008
Article Copyright 2007 by Shahed.Khan
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid