Check out this Article for Xml based codegeneration with SCG

I uploaded this new article in the Unedited Section of CodeProject.

Abstract

This article describes how we can use XML as a metadata source for SCG Templates. It also shows step-by-step instructions of how to generate strongly typed objects from XSD and use it in the templates to generate text based output. ASP.NET developers can also use this paper as reference to transform XML using ASP.NET scripts and avoid XSLT.

Introduction

We all agree that XML’s primary purpose is to facilitate the sharing of data across different systems. However, the same XML can also be used as a powerful input for template generation tools. CodeSmith fans might be already familiar with XmlProperty and can be already seen in a variety of examples. In this article I am going to illustrate how to use XML as a metadata source for SCG templates. XML provides a text-based means to describe and apply a tree-based structure to information and SCG facilitates writing logic and code in your favorite .NET language (C#, Vb.Net etc). By combining these two technologies, we can generate meaningful input & output for a system which was very complex to achieve earlier. In the code generation world, XML is now highly used as a metadata source to generate business objects, data access layers and even user interfaces. The other practice is to generate different application layers based on database structure, but XML is becoming more popular as it provides more flexibility in integrating logic as a metadata source for templates. For example, in this example I defined the class name and its properties, and also specified to generate a UI with a gridview component and paging support. Notice this would have been a bit messy to define in a database structure.

  <?xml version="1.0" encoding="utf-8" ?>
  <BusinessObjects xmlns="http://www.smartcodegenerator.com">
    <class name="Student">
      <properties>
        <property name="Id" type="String" maxSize="36" />
        <property name="Name" type="String" maxSize="96" />        
      </properties>
      <userinterface generate="true">
        <uicomponent>GridView</uicomponent>
        <gridview paging ="true" rownum="20">          
        </gridview>
      </userinterface>
    </class>    
  </BusinessObjects>


Lets see how to use XML in SCG template.

How to use XML metadata in SCG templates

Example SmartCodeGenerator: BusinessObjectGenerator

While browsing the internet I found this article “Business Object for CodeSmith” by JR Hull, this comes with some CodeSmith templates that generates object layer, data access layer, and related sql from a schema defined in the XML. I thought this will be a good and quick example to show for SCG where XML is concerned, I converted the templates to SCG templates and these are producing the same output.

These templates will generate ObjectLayer, DataAccess Layer and SQL for you.

To run the example quickly please point the XmlFilePath property to the “InvoiceClassDef.xml” that you will find with the sourcecode. The “Generated Files” folder contains the generated files from the following XML.

If this interest you then Download and have a look…..
:
<?xml version=”1.0″ encoding=”utf-8″ ?>
<BusinessObjects>
 <class name=”Invoice”> 
     <properties>
  <property name=”Id” type=”String” maxSize=”36″ />
  <property name=”Customer” type=”String” maxSize=”96″ />
  <property name=”InvoiceDate” type=”DateTime” maxSize=”” />
  <property name=”InvoicePaid” type=”bool” maxSize=”” />
  <property name=”InvoiceDetails” type=”InvoiceDetailCollection” maxSize=”” />
     </properties>
 </class>
 <class name=”InvoiceDetail”> 
     <properties>
  <property name=”Id” type=”String” maxSize=”36″ />
  <property name=”InvoiceId” type=”String” maxSize=”36″ />
  <property name=”LineItem” type=”int” maxSize=”” />
  <property name=”ItemDescription” type=”String” maxSize=”96″ />
  <property name=”ItemCostPerUnit” type=”decimal” maxSize=”” />
  <property name=”ItemQuanity” type=”int” maxSize=”” />
  <property name=”ItemUnit” type=”String” maxSize=”8″ />
     </properties>
 </class>
</BusinessObjects>

This example can be dowloaded from community.smartcodegenerator.com

An alternative approach to XSLT with ASP.NET scripts

XSL stands for Extensible Stylesheet Language (OR XSL = Xml Style Sheet) and XSLT is the language to transform XML documents. Its a common practice to use XSLT to to transform an XML document into another XML document, or another type of document that is recognized by a browser, like HTML and XHTML. Normally XSLT does this by transforming each XML element into an (X)HTML element.

But today we will see how we can use ASP.NET scripts to achieve the same. This blog post is dedicated to those programmers who are lazy to learn XSLT like me.

We can do this in many ways
1. By using strongly typed classes that is the deserialized representation of the xml file
2. By using classes like XmlDocument, XmlNode etc…
3. XLINQ (which I am not going to describe in this blog….).


Lets take an example from w3schools…. say we want to transform the following XML file.

<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
  <cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>10.90</price>
    <year>1985</year>
  </cd>
.
.
.
</catalog>

Then we create an XSL Style Sheet (“cdcatalog.xsl”) with a transformation template:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <h2>My CD Collection</h2>
    <table border="1">
    <tr bgcolor="#9acd32">
      <th align="left">Title</th>
      <th align="left">Artist</th>
    </tr>
    <xsl:for-each select="catalog/cd">
    <tr>
      <td><xsl:value-of select="title"/></td>
      <td><xsl:value-of select="artist"/></td>
    </tr>
    </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>

You can view the result here: http://www.w3schools.com/xsl/cdcatalog_with_xsl.xml

To achieve the same output by using strongly typed classes that is the deserialized representation of the xml file we need to do the following.

Step1: Generate Strongly Typed classes from the XML
We can use xsd.exe that ships with Visual Studio, to generate .Net classes from the xml. For full list of options of xsd.exe please refer to this link.
http://msdn2.microsoft.com/en-us/library/x6c1kb0s(vs.71).aspx

a. The following command will generate a XSD file from the XML.

C:\Temp>xsd catalog.xml
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file ‘C:\Temp\catalog.xsd’.



b. The following command will generate CS classes from XML.


C:\Temp>xsd catalog.xsd /l:cs /c
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file ‘C:\Temp\catalog.cs’.

if you look carefully you will find all xsd has automatically generated necessary classes and properties in your preferred language.

/// <remarks/>
public partial class catalog {
  private catalogCD[] itemsField;
  /// <remarks/>
  public catalogCD[] Items {
    get {
      return this.itemsField;
    }
    set {
      this.itemsField = value;
    }
  }
}

/// <remarks/>
public partial class catalogCD {
  private string titleField;
  private string artistField;
  private string countryField;
  private string companyField;
  private string priceField;
  private string yearField;
.
.


  }
}


c. Now we can add this generated class to our ASP.NET project and use the XmlSerializer to Deserialize the xml file to .NET Strongly Typed Object. Here is how we do it…


public catalog TempCatalog;
private void Test()
{
  TempCatalog =new catalog();
  TempCatalog = (catalog)LoadSerializedObjectFromFile(TempCatalog,@”C:\temp\catalog.xml”);
}

public Object LoadSerializedObjectFromFile(Object objectToLoad, string path)
{
  TextReader textReader = null;

  try
  {
    Type thetype = objectToLoad.GetType();
    XmlSerializer x = new XmlSerializer(thetype);
    textReader = new StreamReader(path);
    objectToLoad = x.Deserialize(textReader);
  }
  finally
  {
    //Make sure to close the file even if an exception is raised…
    if (textReader != null)
    textReader.Close();
  }

    return objectToLoad;
}

d. Ready to transform XML with strongly typed Object and ASP.NET Script…here is the similiar example….as above….but I have used c# asp.net script here …. how cool is that..

<h2>My CD Collection</h2>
<table border=”1″>
<tr bgcolor=”#9acd32″>
<th align=”left”>Title</th>
<th align=”left”>Artist</th>
</tr>
<%foreach( catalogCD cd in TempCatalog.Items) {%>
<tr>
<td><%=cd.title%></td>
<td><%=cd.artist%></td>
</tr>
<%} %>
</table>

notice I am using strongly typed codes ie. TempCatalog.Items, cd.title, cd.artist etc..
 
You can also do the same using XmlDocument, XmlNodeList and XmlNode…

But I prefer generating .Net Classes from xml as it gives intellisense during development time… Here is the other way of how we do it…and here you need to know you attribute and elements:

<%System.Xml.XmlDocument document = new System.Xml.XmlDocument();
document.Load( @”C:\DotNetWorkFolder2005\Riccardo\TestProject\AJAXEnabledWebApplication2\AJAXEnabledWebApplication2\catalog.xml” );
System.Xml.XmlElement root = document.DocumentElement;
System.Xml.XmlNodeList cdList = root.GetElementsByTagName(“cd”);%>
<h2>My CD Collection</h2>
<table border=”1″>
<tr bgcolor=”#9acd32″>
<th align=”left”>Title</th>
<th align=”left”>Artist</th>
</tr>
<%foreach (System.Xml.XmlNode cd in cdList)
{
string title = cd.ChildNodes[0].InnerText;
string artist = cd.ChildNodes[1].InnerText;%>
<tr>
<td><%=title%></td>
<td><%=artist%></td>
</tr>
<%} %>
</table>


Note for SmartCodeGenerator Fans: I am soon releasing an article “Xml based codegeration for SCG” where it uses the same technique as described here to generate output depending on XML metadata information. It illustrate how to use XML as metadata source for SCG templates. XML provides a text-based means to describe and apply a tree-based structure to information and SCG facilitates writing logics and codes in your favorite .Net language (C#, Vb.Net etc). By combining these two technologies we can generate meaningful input/output for system which was very complex to achieve earlier. CodeSmith users might have seen examples of XmlProperty…I am talking the same thing…for SmartCodeGenerator…..

Conclusion

.Net comes with the richness with classes dedicated to XML and XML Manupulation….and here I have just shown a trick which allows to avoid XSLT completely and you can achieve the same result with pure ASP.Net scripts. In addition when you generate .Net classes from XSD you get full intellisense support during your development time.

Ajax.Asp.Net Tips and Tricks: Adding Dynamic Controls to UpdatePanel and Identifying what control has triggered the event.

Here is a cool technique on how to identify which control has triggered the UpdatePanel (when dynamic controls are added during runtime). Here we will use the Request Object to identify this.

Lets say we have updatePanel1

<div>
<asp:UpdatePanel ID=”UpdatePanel1″ runat=”server” UpdateMode=”conditional”>
  <ContentTemplate>
    <asp:Label ID=”Label1″ runat=”server” Text=””></asp:Label>
    <asp:Panel ID=”Panel1″ runat=”server” Height=”50px” Width=”125px”>
    </asp:Panel>
  </ContentTemplate>
</asp:UpdatePanel>
</div>


and during runtime we go and add dynamic buttons…. button1, button2 in the Panel1….

LinkButton button1 = new LinkButton();
button1.ID = “button1″
button1.Text = “button1″

LinkButton button2 = new LinkButton();
button2.ID = “button2″
button2.Text = “button2″

Panel1.Controls.Add(button1);
Panel1.Controls.Add(button2);


now we can identify which button is clicked, by looking at the Request Object and passing the key of the ScriptManager.ID:

protected override void CreateChildControls()
{
  base.CreateChildControls();
  if( ScriptManager1.IsInAsyncPostBack )
  {
    string fromWhere = Request[ScriptManager1.ID];
    Label1.Text = fromWhere;
  }
}

 

This will get the following wtring:
On Button1 click: UpdatePanel1|button1
On Button2 click: UpdatePanel1|button2

if we look carefully at the string  “UpdatePanel1|button1″ we see that it has 2 parts, the ID of the UpdatePanel which got triggered and the ID of the control (ie. button1) which triggered the event.

So we can do something like this…..

protected override void CreateChildControls()
{
  base.CreateChildControls();
  if( ScriptManager1.IsInAsyncPostBack )
  {
    string fromWhere = Request[ScriptManager1.ID];   

    if( fromWhere.Contains(“button1″) )
    {
        //Do something here
    }
    else if (fromWhere.Contains(“button2″)
    {

        //Do something else….as you wish….
    }
  }
}

Asp.Net Ajax Resources, Links and Documentation

Getting Started

ASP.NET AJAX Server Controls

Client Scripting

Debugging and Tracing

Web Services

Localization and Globalization

Extending ASP.NET AJAX

 

ScottGu’s Blog Post : Asp.net Ajax Documentaion, Videos and Cool Articles