Click here to Skip to main content
13,145,464 members (62,657 online)
Click here to Skip to main content
Articles » Languages » XML » General » Downloads

Stats

425K views
8.7K downloads
136 bookmarked
Posted 15 Oct 2004

Generate dynamic ASP.NET pages by using XML and XSLT

, 15 Oct 2004
Generates dynamic forms by transforming XML into XSL file.
using System;
using System.Data;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
//using System.Web.Mail;
using WTMI.Util;
using WTMI.Collections;

namespace WTMI.Plan2Attend.RequestForm.Library
{
	/// <summary>
	/// Summary description for XmlTransformManager.
	/// </summary>
	public class XmlTransformManager
	{
		public System.Web.UI.WebControls.Panel ControlHolder;
		
		public XmlTransformManager()
		{
		
		}

		#region Public properties

		public string UniquePageId;

		public string DllAssembly
		{
			get
			{
				return (HttpContext.Current.Session["DllAssembly"] == null) ? @"C:\inetpub\wwwroot\requestform\bin\RequestForm.dll" : (string)HttpContext.Current.Session["DllAssembly"];
			}
			set
			{
				HttpContext.Current.Session["DllAssembly"] = value;
			}
		}		

		public string XslFile
		{
			get
			{
				if (HttpContext.Current.Session["XslFile"] == null)
				{
					XmlNode node = XmlData.SelectSingleNode("FORM/FILES/XSL_STYLE");
					if (node == null)
						HttpContext.Current.Session["XslFile"] = @"C:\inetpub\wwwroot\requestform\styles\default.xslt";
					else
						HttpContext.Current.Session["XslFile"] = node.InnerText;
				}
				return (string)HttpContext.Current.Session["XslFile"];
			}
		}

		public string XslSummary
		{
			get
			{
				if (HttpContext.Current.Session["XslSummary"] == null)
				{
					XmlNode node = XmlData.SelectSingleNode("FORM/FILES/XSL_SUMMARY");
					if (node == null)
						HttpContext.Current.Session["XslSummary"] = @"C:\inetpub\wwwroot\requestform\styles\defaultsummary.xslt";
					else
						HttpContext.Current.Session["XslSummary"] = node.InnerText;
				}
				return (string)HttpContext.Current.Session["XslSummary"];
			}
		}

		public string XslConfirmation
		{
			get
			{
				if (HttpContext.Current.Session["XslConfirmation"] == null)
				{
					XmlNode node = XmlData.SelectSingleNode("FORM/FILES/XSL_CONFIRMATION");
					if (node == null)
						HttpContext.Current.Session["XslConfirmation"] = @"C:\inetpub\wwwroot\requestform\styles\defaultconfirmation.xslt";
					else
						HttpContext.Current.Session["XslConfirmation"] = node.InnerText;
				}
				return (string)HttpContext.Current.Session["XslConfirmation"];
			}
		}

		public string XmlFile
		{
			get
			{
				return (string)HttpContext.Current.Session["XmlFile"];
			}
			set
			{
				HttpContext.Current.Session["XmlFile"] = value;
			}
		}

		public XmlDocument XmlData
		{
			get
			{
				if (HttpContext.Current.Session["XmlData"] == null)
				{
					XmlDocument xml = new XmlDocument();
					xml.Load(XmlFile);
					HttpContext.Current.Session["XmlData"] = xml;
				}
				return (XmlDocument)HttpContext.Current.Session["XmlData"];
			}
		}

		#endregion

		#region Private getters methods

		// return page id when at field level
		private string GetPageId(XmlNode node)
		{
			return node.ParentNode.ParentNode.Attributes["uniqueid"].Value;
		}

		private XmlNode GetPage()
		{
			return XmlData.SelectSingleNode("/FORM/PAGES/PAGE[@uniqueid='" + UniquePageId + "']");
		}

		private string GetFieldId(XmlNode node)
		{
			try
			{
				return node.SelectSingleNode("PROPERTIES/PROPERTY[@name='ID']").InnerText;
			}
			catch
			{
				return null;
			}
		}

		private object[] GetFieldParams(XmlNode node)
		{
			return GetFieldParams(node, null);
		}

		// used to get param for database list controls
		private object[] GetFieldParams(XmlNode node, string val)
		{
			ArrayList al = new ArrayList();
			XmlNodeList xnl = node.SelectNodes("PARAMS/PARAM");
			foreach (XmlNode xn in xnl)
			{
				// for string only (temporary)
				if (xn.Attributes["type"].Value == "System.String")
					al.Add(xn.InnerText);
			}

			if (val != null)
			{
				al.Add(val);
			}

			return al.ToArray();
		}

		private XmlNodeList GetUserControls()
		{
			return XmlData.SelectNodes("/FORM/PAGES/PAGE[@uniqueid='" + UniquePageId + "']/FIELDS/FIELD[@type='UserControl']");
		}

		private XmlNodeList GetStaticControls()
		{
			return XmlData.SelectNodes("/FORM/PAGES/PAGE[@uniqueid='" + UniquePageId + "']/FIELDS/FIELD[@type!='UserControl']");
		}
		
		#endregion

		#region Private setters methods
		// used to fill out controls with values
		private void SetFieldValue(Control control, string cValue)
		{
			// set TextBox
			if (control is TextBox)
			{
				((TextBox)control).Text = cValue;
			}

				// set RadioButton and CheckBox controls
			else if (control is CheckBox)
			{
				((CheckBox)control).Checked = (cValue == "1") ? true : false;
			}

				// set listbox control
			else if (control is ListBox) 
			{
				ListBox listbox = (ListBox)control;
				if (listbox.SelectionMode == ListSelectionMode.Multiple) 
				{
					string[] aValues = cValue.Split(new Char[]{','},1000);
					foreach(string s in aValues)
					{
						ListItem item = ((ListControl)control).Items.FindByValue(s);
						if (item != null) item.Selected = true;
					}				
				}
				else
				{
					ListItem item = ((ListControl)control).Items.FindByValue(cValue);
					if (item != null) item.Selected = true;
				}
			}

				// set checkboxlist
			else if (control is CheckBoxList)
			{
				string[] aValues = cValue.Split(new Char[]{','},1000);
				foreach(string s in aValues)
				{
					if (s == "") continue;
					ListItem item = ((ListControl)control).Items[Convert.ToInt32(s)];
					if (item != null) item.Selected = true;
				}				
			}

				// set ListControls 
			else if (control is ListControl)
			{
				ListItem item = ((ListControl)control).Items.FindByValue(cValue);
				if (item != null) item.Selected = true;
			}			
		}
		
		#endregion

		#region Private bool methods
		private bool IsPageVisible()
		{
			XmlNode xn = GetPage();
			if (xn.Attributes["visible"] == null)
			{
				return true;
			}
			else if (xn.Attributes["visible"].Value.ToLower() == "true")
			{
				return true;
			}
			return false;
		}
		#endregion

		#region Private transformers methods

		private void TransformStaticFields()
		{
			/**
			 * Transform aspx page with static fields
			 * Get transform result as a astring
			 * Parse controls into a parent control holder
			 */

			// load xslt to do transformation
			XslTransform xsl = new XslTransform();
			xsl.Load(XslFile);

			// load xslt arguments
			XsltArgumentList xslarg = new XsltArgumentList();
			xslarg.AddParam("fields", "", UniquePageId);

			// get transformed results
			StringWriter sw = new StringWriter();
			xsl.Transform(XmlData, xslarg, sw, null);
			string result = sw.ToString().Replace("xmlns:asp=\"remove\"","").Replace("&lt;","<").Replace("&gt;",">");

			// free up the memory of objects that are not used anymore
			xslarg = null;
			xsl = null;
			sw = null;

			// parse the controls and add it to the page
			Control ctrl = ControlHolder.Page.ParseControl(result);
			ControlHolder.Controls.Add(ctrl);	
		}

		private void TransformDataBindFields()
		{
			/**
			 * Select all controls that has attribute databind=true
			 * Select class information
			 * Select method information
			 * Select required parameters
			 * Invoke selected method
			 * Bind data to control
			 */

			// find all databind nodes
			XmlNodeList xnl = XmlData.SelectNodes("/FORM/PAGES/PAGE[@uniqueid='" + UniquePageId + "']/FIELDS/FIELD[@databind='true']");
			foreach (XmlNode xn in xnl)
			{
				// set class, method, params objects
				string sClass = xn.Attributes["class"].Value;
				string sMethod = xn.Attributes["method"].Value;
				object[] aParams = GetFieldParams(xn);
				string sControl = GetFieldId(xn);

				ReflectionManager rm = new ReflectionManager(DllAssembly, sClass);

				// return only datatable only (temporary)
				DataTable data = (DataTable)rm.InvokeReturnMethod(sMethod,aParams); 

				// for list controls only (temporary)
				ListControl listcntr = (ListControl)ControlHolder.FindControl(sControl);
				listcntr.DataSource = data.DefaultView;
				listcntr.DataBind();

				// free up the memory of objects that are not going to be used any more
				rm = null;
				data.Dispose();
				data = null;
			}
		}

		private void TransformUserControlFields()
		{
			/**
			 * Select all user controls
			 * Load control into the page
			 * Set control properties
			 * Add control to the page
			 */
			// find user control objects
			XmlNodeList xnl = GetUserControls();

			foreach (XmlNode xn in xnl)
			{
				string strControl = GetFieldId(xn);
				string sControl = xn.Attributes["control"].Value;

				Assembly oAssembly = System.Reflection.Assembly.GetExecutingAssembly();
				Type oType = oAssembly.GetType(sControl);
				object oObject = Activator.CreateInstance(oType);

				XmlNodeList xnlprops = xn.SelectNodes("PROPERTIES/PROPERTY");
				foreach (XmlNode xnprop in xnlprops)
				{
					string strProp = xnprop.Attributes["name"].Value;
					string strValue = xnprop.InnerText;
					
					PropertyInfo prop = oType.GetProperty(strProp);
					prop.SetValue(oObject, strValue, null);						
				}

				// Load the first control dynamically
				Control c = (Control)oObject;
				
				Panel pnl = (Panel)ControlHolder.FindControl("Panel_" + strControl);
				pnl.Controls.Add(c);
			}
		}

		private void TransformSummaryStaticFields()
		{
			/**
			 * Transform aspx page with label fields
			 * Get transform result as a astring
			 * Parse controls into a parent control holder
			 */
			// load xslt to do transformation
			XslTransform xsl = new XslTransform();
			xsl.Load(XslSummary);

			// get transformed results
			StringWriter sw = new StringWriter();
			xsl.Transform(XmlData,null,sw,null);
			string result = sw.ToString().Replace("xmlns:asp=\"remove\"","").Replace("&lt;","<").Replace("&gt;",">");

			// parse the controls and add it to the page
			Control ctrl = ControlHolder.Page.ParseControl(result);
			ControlHolder.Controls.Add(ctrl);

			// free up the memory of objects that are not used anymore
			sw.Close();
		}

		private void TransformSummaryDataBindFields()
		{
			/**
			 * Select all controls that has attribute databind=true
			 * Select class information
			 * Select summary method information
			 * Select required parameters
			 * Invoke selected method
			 * Bind data to a label control
			 */
			XmlNodeList xnl = XmlData.SelectNodes("FORM/PAGES/PAGE[@completed='True']/FIELDS/FIELD[@databind='true']");
			foreach (XmlNode xn in xnl)
			{
				string sControl = "Field_" + GetPageId(xn) + "_" + GetFieldId(xn);
				Label label = (Label)ControlHolder.FindControl(sControl);
				
				// set class, method, params objects
				string sClass = xn.Attributes["class"].Value;
				string sMethod = xn.Attributes["summarymethod"].Value;
				object[] aParams = GetFieldParams(xn,label.Text);
								
				ReflectionManager rm = new ReflectionManager(DllAssembly, sClass);
				label.Text = (string)rm.InvokeReturnMethod(sMethod,aParams); 

				// free up the memory of objects that are not going to be used any more
				rm = null;
			}
		}
		private void TransformSummaryUserControlFields()
		{
			/**
			 * Select all user controls
			 * Load control into the page
			 * Set control properties
			 * Add control to the page
			 */
			// find user control objects
			XmlNodeList xnl = XmlData.SelectNodes("FORM/PAGES/PAGE[@completed='True']/FIELDS/FIELD[@type='UserControl']");
			foreach (XmlNode xn in xnl)
			{
				string strControl = GetPageId(xn) + "_" + GetFieldId(xn);
				string sControl = xn.Attributes["summary"].Value;

				Assembly oAssembly = System.Reflection.Assembly.GetExecutingAssembly();
				Type oType = oAssembly.GetType(sControl);
				object oObject = Activator.CreateInstance(oType);

				XmlNodeList xnlprops = xn.SelectNodes("PROPERTIES/SUMMARY_PROPERTY");
				foreach (XmlNode xnprop in xnlprops)
				{
					string strProp = xnprop.Attributes["name"].Value;
					string strValue = xnprop.InnerText;

					PropertyInfo prop = oType.GetProperty(strProp);
					prop.SetValue(oObject, strValue, null);			
				}
				
				Control c = (Control)oObject;
				c.ID = strControl;
				
				Panel pnl = (Panel)ControlHolder.FindControl("Panel_" + strControl);
				pnl.Controls.Add(c);
			}
		}
		private void TransformSummaryCheckBoxFields()
		{
			/**
			 * Select all CheckboxList controls (checkbox values are indexes)
			 * Check if control not Database driven if not then continue
			 * Need to split data into array and then match array indexes with nodes indexes
			 */
			// find checkboxlists control objects
			XmlNodeList xnl = XmlData.SelectNodes("FORM/PAGES/PAGE[@completed='True']/FIELDS/FIELD[@type='CheckBoxList']");
			foreach (XmlNode xn in xnl)
			{
				// we do not need to get data if the control values comes from database
				if (xn.Attributes.GetNamedItem("databind") != null && xn.Attributes["databind"].Value == "true") continue;

				// get control id
				string sControl = "Field_" + GetPageId(xn) + "_" + GetFieldId(xn);

				// find control in the control holder
				Label label = (Label)ControlHolder.FindControl(sControl);

				// if label text is empty then we do not need to find values
				if (label.Text == "") continue;
				
				string sValue = "";
				string[] aValues = label.Text.Split(new Char[]{','},1000);
				foreach(string s in aValues)
				{
					if (s == "") continue;
					if (sValue != "") sValue += ",";
					sValue += xn.SelectSingleNode("LISTITEMS").ChildNodes[Convert.ToInt32(s)].InnerText;
				}

				// set selected value
				label.Text = sValue;
			}
		}
		private void TransformSummaryDisplayModeFields()
		{
			/**
			 * Select all controls that have displaymode property equal true
			 * Check if control not Database driven if not then continue
			 * Find text by selected value
			 */
			// find list control objects with displaymode=text
			XmlNodeList xnl = XmlData.SelectNodes("FORM/PAGES/PAGE[@completed='True']/FIELDS/FIELD[@displaymode='Text']");
			foreach (XmlNode xn in xnl)
			{
				// we do not need to get data if the control values comes from database
				if (xn.Attributes.GetNamedItem("databind") != null && xn.Attributes["databind"].Value == "true") continue;
				
				// get control id
				string sControl = "Field_" + GetPageId(xn) + "_" + GetFieldId(xn);
				
				// find control in the control holder
				Label label = (Label)ControlHolder.FindControl(sControl);
				
				// if label text is empty then we do not need to find values
				if (label.Text == "") continue;
				
				string sValue = "";
				XmlNode xnvalue = xn.SelectSingleNode("VALUE");
				if (xnvalue != null)
				{
					sValue = xn.SelectSingleNode("LISTITEMS/LISTITEM[@value='" + label.Text + "']").InnerText;
				}

				// set selected value
				label.Text = sValue;
			}
		}
		#endregion		

		#region Private fillers methods
		private void FillUserControlFields()
		{
			/**
			 * Find user controls from the page
			 * Fill controls with the saved values from http request stream
			 */
			
			// find all controls
			XmlNodeList xnl = GetUserControls();

			foreach (XmlNode xn in xnl)
			{
				string controlName = GetFieldId(xn);

				if (controlName == null) continue;

				// Load control dynamically
				Control c = ControlHolder.Page.FindControl(controlName);
			
				XmlNode xnlvalues = xn.SelectSingleNode("VALUES");
				if (xnlvalues != null)
				{
					foreach (XmlNode xnu in xnlvalues.ChildNodes)
					{
						string userControl = xnu.Name;
						
						Control uc = c.FindControl(userControl);
						if (uc != null)	SetFieldValue(uc, xnu.InnerText);
					}
				}
			}
		}

		private void FillStaticFields()
		{
			/**
			 * Find regular fields from the page
			 * Fill controls with the saved values from http request stream
			 */
			
			// find all controls
			XmlNodeList xnl = GetStaticControls();
			
			foreach (XmlNode xn in xnl)
			{
				string controlName = GetFieldId(xn);

				if (controlName == null) continue;

				// Load control dynamically
				Control c = ControlHolder.Page.FindControl(controlName);
			
				XmlNode xnvalue = xn.SelectSingleNode("VALUE");
				if (xnvalue != null)
				{
					SetFieldValue(c, xnvalue.InnerText);
				}
			}
		}

		#endregion

		#region Private savers methods
		private void SaveUserControlFields()
		{
			
			XmlNodeList xnl = GetUserControls();

			foreach (XmlNode xn in xnl)
			{
				// get control name
				string controlName = GetFieldId(xn);

				if (controlName == null) continue;

				// drop values if they are exists
				XmlNode xnvalues = xn.SelectSingleNode("VALUES");
				if (xnvalues != null) xn.RemoveChild(xnvalues);
				
				// recreate node element
				xnvalues = XmlData.CreateNode(XmlNodeType.Element,"VALUES","");
				xn.AppendChild(xnvalues);
					
				// loop through all request keys to save values of the usercontrol child controls
				for(int i = 0; i < HttpContext.Current.Request.Form.Keys.Count; i++)
				{
					string key = HttpContext.Current.Request.Form.Keys[i];
					if (key.IndexOf(controlName) > -1)
					{
						XmlNode xnvalue = XmlData.CreateNode(XmlNodeType.Element, key.Replace(controlName + ":",""), "");
						xnvalue.InnerText = HttpContext.Current.Request.Form[key];
						xnvalues.AppendChild(xnvalue);							
					}
				}
			}
		}
		private void SaveStaticFields()
		{
			XmlNodeList xnl = GetStaticControls();

			foreach (XmlNode xn in xnl)
			{
				// get control name
				string controlName = GetFieldId(xn);

				if (controlName == null) continue;

				// get control type
				string controlType = xn.Attributes["type"].Value;				
				
				// select value node if there is such a  node need to create
				XmlNode xnvalue = xn.SelectSingleNode("VALUE");
				if (xnvalue == null)
				{
					xnvalue = XmlData.CreateNode(XmlNodeType.Element,"VALUE","");
					xn.AppendChild(xnvalue);
				}

				if (controlType.Equals("CheckBoxList"))
				{
					string sValue = "";
					for(int i = 0; i < HttpContext.Current.Request.Form.Keys.Count; i++)
					{
						string key = HttpContext.Current.Request.Form.Keys[i];
						if (key.IndexOf(controlName) > -1)
						{
							if (HttpContext.Current.Request.Form[key] == "on")
							{
								if (sValue != "") sValue += ",";
								sValue += key.Replace(controlName + ":","");
							}
						}
					}
					xnvalue.InnerText = sValue;
				}
				else
				{
					xnvalue.InnerText = HttpContext.Current.Request.Form[controlName];
				}				
			}
		}
		#endregion

		public void ValidateBusinessLogic()
		{
			/**
			 * Select validation node from xml
			 * Select class information
			 * Select method information
			 * Invoke selected method
			 */

			// find all databind nodes
			XmlNode xn = XmlData.SelectSingleNode("/FORM/PAGES/PAGE[@uniqueid='" + UniquePageId + "']/VALIDATION");
			if (xn != null)
			{
				// set class, method, params objects
				string sClass = xn.Attributes["class"].Value;
				string sMethod = xn.Attributes["method"].Value;
				
				ReflectionManager rm = new ReflectionManager(DllAssembly, sClass);

				// return only datatable only (temporary)
				rm.InvokeNoReturnMethod(sMethod,null); 

				// free up the memory of objects that are not going to be used any more
				rm = null;
			}
		}

		public void TransformConfirmation(ObjectEntryCollection arguments)
		{
			/**
			 * Transform aspx page
			 * Get transform result as a string
			 * Create script control to set dynamic values onto confirmation page
			 * Parse controls into a parent control holder
			 */
			// load xslt to do transformation
			XslTransform xsl = new XslTransform();
			xsl.Load(XslConfirmation);

			// get transformed results
			StringWriter sw = new StringWriter();
			xsl.Transform(XmlData,null,sw,null);
			string result = sw.ToString().Replace("xmlns:asp=\"remove\"","").Replace("&lt;","<").Replace("&gt;",">");

			// set all params with values
			HtmlGenericControl scriptControl = new HtmlGenericControl("SCRIPT");
			string script = "function void_setparams() {" +
				"var params = new Array();";
			for (int i = 0; i < arguments.Count; i++)
			{
				ObjectEntry xca = arguments[i];
				script += "params[" + i + "] = new Array('" + xca.Name + "','" + xca.Value + "');";
			}
			script += "for (var i = 0; i < params.length; i++) { try {" +
				"document.getElementById(params[i][0]).innerHTML = params[i][1];}catch(ex){}} } void_setparams();";
			scriptControl.InnerHtml = script;

			// free up the memory of objects that are not used anymore
			xsl = null;
			sw = null;

			// parse the controls and add it to the page
			Control ctrl = ControlHolder.Page.ParseControl(result);
			ControlHolder.Controls.Add(ctrl);
			ControlHolder.Controls.Add(scriptControl);

		}
		public void TransformSummary()
		{
			TransformSummaryStaticFields();
			TransformSummaryDataBindFields();
			TransformSummaryUserControlFields();
			TransformSummaryCheckBoxFields();
			TransformSummaryDisplayModeFields();
		}

		public void Transform()
		{
			TransformStaticFields();
			TransformDataBindFields();
			TransformUserControlFields();
		}		

		public void Fill()
		{
			//FillUserControlFields(); ??? not needed
			FillStaticFields();
		}

		public void Save()
		{
			SaveStaticFields();
			SaveUserControlFields();
			// set page completed
			SetPageCompleted(true, GetPage()); 
		}

		public void MoveNext()
		{
			XmlNodeList xnl = XmlData.SelectNodes("/FORM/PAGES/PAGE");
			for (int i = 0; i < xnl.Count; i++)
			{
				if ((UniquePageId == "" || UniquePageId == null) && i < xnl.Count)
				{
					UniquePageId = xnl[i].Attributes["uniqueid"].Value;
					if (!IsPageVisible()) MoveNext();
					break;
				}
				if (UniquePageId.Equals(xnl[i].Attributes["uniqueid"].Value))
				{
					if (i < xnl.Count-1)
					{
						UniquePageId = xnl[i+1].Attributes["uniqueid"].Value;
						if (!IsPageVisible()) MoveNext();
						break;
					}
					else
					{
						UniquePageId = "Summary";
						break;
					}
				}
			}
			xnl = null;
		}

		public void SetPageCompleted(bool completed, XmlNode page)
		{	
			XmlAttribute xmlattr = page.Attributes["completed"];
			if (xmlattr == null)
			{
				XmlAttribute xa = XmlData.CreateAttribute("completed");
				xa.Value = completed.ToString();
				page.Attributes.Append(xa);
			}
			else
			{
				page.Attributes["completed"].Value = completed.ToString();
			}	
			if (completed)
				SetPageVisibile(true, page);
		}

		public void SetPageVisibile(bool visible, XmlNode page)
		{
			XmlAttribute xmlattr = page.Attributes["visible"];
			if (xmlattr == null)
			{
				XmlAttribute xa = XmlData.CreateAttribute("visible");
				xa.Value = visible.ToString();
				page.Attributes.Append(xa);
			}
			else
			{
				page.Attributes["visible"].Value = visible.ToString();
			}			
		}

		public string GetEmailPath()
		{
			XmlNode node = XmlData.SelectSingleNode("/FORM/FILES/EMAIL");
			if (node != null)
				return node.InnerText;
			else
				return null;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

rafael_p
Web Developer
United States United States
I am Microsoft Certified in .NET
I have over seven-year experience with client-server application development (full project lifecycle) on Windows platforms.
I've focused on creating middle tier, web application development, GUI development, custom data management software, and database programming.

You may also be interested in...

Pro
Pro
Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.170915.1 | Last Updated 15 Oct 2004
Article Copyright 2004 by rafael_p
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid