|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionSometimes 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:
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. <FORM>
<PAGES>
<PAGE title="Page Title" id="page_1">
<FIELDS>
<!-- create regular TextBox -->
<FIELD type="TextBox" label="Last Name:" required="true">
<PROPERTIES>
<PROPERTY name="ID">LAST_NAME</PROPERTY>
</PROPERTIES>
</FIELD>
<!-- create multiline TextBox (textarea) -->
<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>
<!-- regular textbox prefilled with text -->
<FIELD type="TextBox" label="Prefilled Contrl:">
<PROPERTIES>
<PROPERTY name="ID">PREFILLED_CONTROL</PROPERTY>
<PROPERTY name="Text">Some Text</PROPERTY>
</PROPERTIES>
</FIELD>
<!-- regular text box which must filled
and allowed Date datata type -->
<FIELD type="TextBox" label="Start Date:"
required="true" validation="Date">
<PROPERTIES>
<PROPERTY name="ID">START_DATE</PROPERTY>
</PROPERTIES>
</FIELD>
<!-- create select box -->
<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>
<!-- radio buttons list -->
<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>
<!-- check box list -->
<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>
<!-- here is a hyperlink (a) -->
<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"/>
<!-- you can place here any other asp controls -->
</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 <?xml version="1.0" encoding="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="/">
<!-- page id parameter if we have more than 1 page in our XML file -->
<xsl:param name="pageid"/>
<!-- start form page -->
<table cellpadding="0" cellspacing="5">
<!-- set title of the current page -->
<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>
<!-- iterate through page fields -->
<xsl:for-each select="FORM/PAGES/PAGE[@id=$pageid]/FIELDS/FIELD">
<!-- create row -->
<xsl:element name="tr">
<xsl:attribute name="id">
TR_<xsl:value-of select="PROPERTIES/PROPERTY[@name='ID']"></xsl:value-of>
</xsl:attribute>
<!-- hide the row -->
<xsl:if test="@display='none'">
<xsl:attribute name="style">display:none;</xsl:attribute>
</xsl:if>
<xsl:choose>
<!-- this is the way to place "include" files into your PRE -->
<xsl:when test="@type='HTML'">
<td colspan="3">
<!-- #include file="<xsl:value-of select="@src"></xsl:value-of>" -->
</td>
</xsl:when>
<!-- other controls -->
<xsl:otherwise>
<!-- field label column -->
<td valign="top">
<xsl:value-of select="@label" />
</td>
<!-- field column -->
<td>
<!-- field element -->
<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>
<!-- validation message column -->
<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 ( ...
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)
{
/**
* Transform aspx page with fields from xml file
* Get transform result as a string
* Parse controls into a parent control holder
*/
XmlDocument xdoc = new XmlDocument();
xdoc.Load(XmlFile);
// load xslt to do transformation
XslTransform xsl = new XslTransform();
xsl.Load(XslFile);
// load xslt arguments to load specific page from xml file
// this can be used if you have multiple pages
// in your xml file and you loading them one at a time
XsltArgumentList xslarg = new XsltArgumentList();
xslarg.AddParam("pageid", "", pageId);
// get transformed results
StringWriter sw = new StringWriter();
xsl.Transform(xdoc, xslarg, sw);
string result = sw.ToString().Replace("xmlns:asp=\"remove\"",
"").Replace("<","<").Replace(">",">");
// free up the memory of objects that are not used anymore
sw.Close();
// parse the controls and add it to the page
Control ctrl = Page.ParseControl(result);
Page.Controls.Add(ctrl);
}
}
private void BtnSave_Click(object sender, System.EventArgs e)
{
// save data into a data container
// ...
Response.Write (Request.Form["LAST_NAME"]);
}
ConclusionIn 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.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||