Introduction
Sometimes you need to create dynamic pages. You may allow users to build their own applications by selecting the fields they need. In this article, I will show how to build dynamic applications by
using ASP.NET and
XML. In this example, I use
XML for meta-programming or generative programming. I use
XML with an XSLT to generate
ASP.NET PRE, utilizing intrinsic
ASP.NET parsing methods with the XSLT output. Steps that we need to do:
- Create XML file (schema of our page).
- Create an XSLT style to transform XML into ASP.NET PRE.
- Transform XML, and create server controls defined by the generated ASP.NET PRE at runtime.
- Insert the instantiated controls into the page's control collection.
- Handle postback events from server controls.
First, what we need to come up with is a good structure of our page in a
XML file. A basic page structure is defined below. The example structure consists of field elements, with attributes, properties and listitems.
Collapse<FORM>
<PAGES>
<PAGE title="Page Title" id="page_1">
<FIELDS>
-->
<FIELD type="TextBox" label="Last Name:" required="true">
<PROPERTIES>
<PROPERTY name="ID">LAST_NAME</PROPERTY>
</PROPERTIES>
</FIELD>
-->
<FIELD type="TextBox" label="Description:">
<PROPERTIES>
<PROPERTY name="ID">DESCRIPTION</PROPERTY>
<PROPERTY name="TextMode">MultiLine</PROPERTY>
<PROPERTY name="Cols">30</PROPERTY>
<PROPERTY name="Rows">2</PROPERTY>
</PROPERTIES>
</FIELD>
-->
<FIELD type="TextBox" label="Prefilled Contrl:">
<PROPERTIES>
<PROPERTY name="ID">PREFILLED_CONTROL</PROPERTY>
<PROPERTY name="Text">Some Text</PROPERTY>
</PROPERTIES>
</FIELD>
-->
<FIELD type="TextBox" label="Start Date:"
required="true" validation="Date">
<PROPERTIES>
<PROPERTY name="ID">START_DATE</PROPERTY>
</PROPERTIES>
</FIELD>
-->
<FIELD type="DropDownList" label="Title:">
<PROPERTIES>
<PROPERTY name="ID">TITLE</PROPERTY>
</PROPERTIES>
<LISTITEMS>
<LISTITEM value="">Select One</LISTITEM>
<LISTITEM value="1">Architector</LISTITEM>
<LISTITEM value="2">Sr. Developer</LISTITEM>
<LISTITEM value="3">Programmer</LISTITEM>
<LISTITEM value="4">Web Designer</LISTITEM>
</LISTITEMS>
</FIELD>
-->
<FIELD type="RadioButtonList" label="Are you US citizen?">
<PROPERTIES>
<PROPERTY name="ID">IS_US_CITIZEN</PROPERTY>
<PROPERTY name="RepeatColumns">1</PROPERTY>
<PROPERTY name="RepeatDirection">Vertical</PROPERTY>
<PROPERTY name="RepeatLayout">Table</PROPERTY>
<PROPERTY name="TextAlign">Right</PROPERTY>
</PROPERTIES>
<LISTITEMS>
<LISTITEM value="1">Yes</LISTITEM>
<LISTITEM value="0">No</LISTITEM>
</LISTITEMS>
</FIELD>
-->
<FIELD type="CheckBoxList" label="Languages:">
<PROPERTIES>
<PROPERTY name="ID">LANGUAGES</PROPERTY>
<PROPERTY name="RepeatColumns">1</PROPERTY>
<PROPERTY name="RepeatDirection">Vertical</PROPERTY>
<PROPERTY name="RepeatLayout">Table</PROPERTY>
<PROPERTY name="TextAlign">Right</PROPERTY>
</PROPERTIES>
<LISTITEMS>
<LISTITEM value="C#">C#</LISTITEM>
<LISTITEM value="Java">Java</LISTITEM>
<LISTITEM value="VB">Visual Basic</LISTITEM>
</LISTITEMS>
</FIELD>
-->
<FIELD type="HyperLink">
<PROPERTIES>
<PROPERTY name="ID">LINK</PROPERTY>
<PROPERTY name="NavigateUrl">javascript:void(alert('Hello ooo'));
</PROPERTY>
<PROPERTY name="Text">Say Hello</PROPERTY>
</PROPERTIES>
</FIELD>
<FIELD type="html" src="file path"/>
-->
</FIELDS>
</PAGE>
...
</PAGES>
</FORM>
Next step is to create XSLT style to transform our
XML schema The XSLT iterates through each field, first outputting a label for the field as plain text. The stylesheet also checks if the field is required, and adds a
RequiredFieldValidator if needed. The stylesheet then creates a Web Control (it could be any valid web control such as
TextBox,
RadioButtonList,
DropDownList, etc.).
ListItems are created for each of the ListControls.
Collapse ="1.0" ="UTF-8"
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:asp="remove">
<xsl:output method="xml" indent="yes" encoding="utf-8" omit-xml-declaration="yes">
</xsl:output>
<xsl:template match="/">
-->
<xsl:param name="pageid"/>
-->
<table cellpadding="0" cellspacing="5">
-->
<tr>
<td colspan="3" align="center" style="font-size:25px">
<xsl:value-of select="FORM/PAGES/PAGE[@id=$pageid]/@title" />
</td>
</tr>
<tr><td colspan="3" style="height:20px"></td></tr>
-->
<xsl:for-each select="FORM/PAGES/PAGE[@id=$pageid]/FIELDS/FIELD">
-->
<xsl:element name="tr">
<xsl:attribute name="id">
TR_<xsl:value-of select="PROPERTIES/PROPERTY[@name='ID']"></xsl:value-of>
</xsl:attribute>
-->
<xsl:if test="@display='none'">
<xsl:attribute name="style">display:none;</xsl:attribute>
</xsl:if>
<xsl:choose>
-->
<xsl:when test="@type='HTML'">
<td colspan="3">
-->
</td>
</xsl:when>
-->
<xsl:otherwise>
-->
<td valign="top">
<xsl:value-of select="@label" />
</td>
-->
<td>
-->
<xsl:element name="asp:{@type}">
<xsl:attribute name="runat">server</xsl:attribute>
<xsl:for-each select="./PROPERTIES/PROPERTY">
<xsl:attribute name="{@name}">
<xsl:value-of select="current()"></xsl:value-of>
</xsl:attribute>
</xsl:for-each>
<xsl:for-each select="./LISTITEMS/LISTITEM">
<asp:ListItem value="{@value}">
<xsl:value-of select="current()"></xsl:value-of>
</asp:ListItem>
</xsl:for-each>
</xsl:element>
</td>
-->
<td>
<xsl:if test="@required='true'">
<asp:RequiredFieldValidator ErrorMessage="Required" runat="server"
ControlToValidate="{PROPERTIES/PROPERTY[@name='ID']}" />
</xsl:if>
<xsl:if test="@validation='Date'">
<asp:CompareValidator ErrorMessage="Dates Only" runat="server"
Operator="DataTypeCheck" Type="Date"
ControlToValidate="{PROPERTIES/PROPERTY[@name='ID']}" />
</xsl:if>
<xsl:if test="@validation='Number'">
<asp:CompareValidator ErrorMessage="Numbers Only" runat="server"
Operator="DataTypeCheck" Type="Integer"
ControlToValidate="{PROPERTIES/PROPERTY[@name='ID']}" />
</xsl:if>
<xsl:if test="@validation='Currency'">
<asp:CompareValidator ErrorMessage="Currency Only" runat="server"
Operator="DataTypeCheck" Type="Currency"
ControlToValidate="{PROPERTIES/PROPERTY[@name='ID']}" />
</xsl:if>
</td>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Our XSLT file has a prefix (
xmlns:asp="remove") defined for the XSL namespace. This is used to generate plain HTML. Now we are ready to write our Page transformer.
Collapse...
private readonly string XslFile = @"...\default.xslt";
private readonly string XmlFile = @"...\default.config";
...
private void Page_Load(object sender, System.EventArgs e)
{
string pageId = "page_1";
if (!Page.IsPostBack)
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(XmlFile);
XslTransform xsl = new XslTransform();
xsl.Load(XslFile);
XsltArgumentList xslarg = new XsltArgumentList();
xslarg.AddParam("pageid", "", pageId);
StringWriter sw = new StringWriter();
xsl.Transform(xdoc, xslarg, sw);
string result = sw.ToString().Replace("xmlns:asp=\"remove\"",
"").Replace("<","<").Replace(">",">");
sw.Close();
Control ctrl = Page.ParseControl(result);
Page.Controls.Add(ctrl);
}
}
private void BtnSave_Click(object sender, System.EventArgs e)
{
Response.Write (Request.Form["LAST_NAME"]);
}
Conclusion
In this article, we separate data from content to make a cleaner design and for better maintainability. When
XML is combined with XSLT,
ASP.NET server controls become even more powerful. This opens up numerous possibilities for dynamic and robust systems.
Comments
Post a Comment