Click here to Skip to main content
15,893,588 members
Articles / Web Development / HTML

Magic AJAX: Applying AJAX to your existing Web Pages

Rate me:
Please Sign up or sign in to vote.
4.82/5 (72 votes)
28 May 2007MIT12 min read 979.6K   2.7K   251  
How to apply AJAX technologies to your web pages without replacing ASP.NET controls and/or writing JavaScript code.
using System;
using System.Xml;
using System.Configuration;
using System.Collections;
using System.Web.UI;

namespace MagicAjax.Configuration
{
	public enum PageStoreMode
	{
		NoStore,
		Session,
		Cache
	}

	public enum OutputCompareMode
	{
		HashCode,
		MD5,
		FullHtml
	}

	public class PageStore
	{
		#region Private Fields
		private Hashtable _state;
		private bool _isLocked;

		// web.config settings
		private PageStoreMode _origMode;
		private bool _origUnloadStoredPage;
		private int _origCacheTimeout;
		private int _origMaxConcurrentPages;
		private bool _origMaxPagesLimitAlert;
		// active settings
		private PageStoreMode _mode;
		private bool _unloadStoredPage;
		private int _cacheTimeout;
		private int _maxConcurrentPages;
		private bool _maxPagesLimitAlert;
		#endregion

		#region Public Properties
		public PageStoreMode Mode
		{
			get { return _mode; }
			set
			{
				if ( _isLocked && value != _mode )
					throw new MagicAjaxException("Configuration settings have been locked and cannot change.");

				_mode = value;
				if ( value != _origMode )
				{
					_state["Mode"] = _mode;
				}
				else
				{
					_state.Remove("Mode");
				}
			}
		}

		public bool UnloadStoredPage
		{
			get { return _unloadStoredPage; }
			set
			{
				if ( _isLocked && value != _unloadStoredPage )
					throw new MagicAjaxException("Configuration settings have been locked and cannot change.");

				_unloadStoredPage = value;
				if ( value != _origUnloadStoredPage )
				{
					_state["UnloadStoredPage"] = _unloadStoredPage;
				}
				else
				{
					_state.Remove("UnloadStoredPage");
				}
			}
		}

		public int CacheTimeout
		{
			get { return _cacheTimeout; }
			set
			{
				if ( _isLocked && value != _cacheTimeout )
					throw new MagicAjaxException("Configuration settings have been locked and cannot change.");

				_cacheTimeout = value;
				if ( value != _origCacheTimeout )
				{
					_state["CacheTimeout"] = _cacheTimeout;
				}
				else
				{
					_state.Remove("CacheTimeout");
				}
			}
		}

		public int MaxConcurrentPages
		{
			get { return _maxConcurrentPages; }
			set
			{
				if ( _isLocked && value != _maxConcurrentPages )
					throw new MagicAjaxException("Configuration settings have been locked and cannot change.");

				_maxConcurrentPages = value;
				if ( value != _origMaxConcurrentPages )
				{
					_state["MaxConcurrentPages"] = _maxConcurrentPages;
				}
				else
				{
					_state.Remove("MaxConcurrentPages");
				}
			}
		}

		public bool MaxPagesLimitAlert
		{
			get { return _maxPagesLimitAlert; }
			set
			{
				if ( _isLocked && value != _maxPagesLimitAlert )
					throw new MagicAjaxException("Configuration settings have been locked and cannot change.");

				_maxPagesLimitAlert = value;
				if ( value != _origMaxPagesLimitAlert )
				{
					_state["MaxPagesLimitAlert"] = _maxPagesLimitAlert;
				}
				else
				{
					_state.Remove("MaxPagesLimitAlert");
				}
			}
		}
		#endregion

		internal bool IsDirty
		{
			get { return ( _state.Keys.Count > 0 ); }
		}

		internal Hashtable State
		{
			get { return _state; }
			set 
			{
				Hashtable state = value;
				foreach (string key in state.Keys)
				{
					switch (key)
					{
						case "Mode":
							Mode = (PageStoreMode) state[key];
							break;
						case "CacheTimeout":
							CacheTimeout = (int) state[key];
							break;
						case "MaxConcurrentPages":
							MaxConcurrentPages = (int) state[key];
							break;
						case "MaxPagesLimitAlert":
							MaxPagesLimitAlert = (bool) state[key];
							break;
						case "UnloadStoredPage":
							UnloadStoredPage = (bool) state[key];
							break;
						default:
							throw new MagicAjaxException(String.Format("PageStore.State: Unknown property '{0}'.", key));
					}
				}
			}
		}

		internal bool IsLocked
		{
			get { return _isLocked; }
			set { _isLocked = value; }
		}

		public PageStore(PageStoreMode mode, bool unloadStoredPage, int cacheTimeout, int maxConcurrentPages, bool maxPagesLimitAlert)
		{
			_state = new Hashtable();
			_isLocked = false;
			_origMode = _mode = mode;
			_origCacheTimeout = _cacheTimeout = cacheTimeout;
			_origMaxConcurrentPages = _maxConcurrentPages = maxConcurrentPages;
			_origMaxPagesLimitAlert = _maxPagesLimitAlert = maxPagesLimitAlert;
			_origUnloadStoredPage = _unloadStoredPage = unloadStoredPage;
		}
	}

	/// <summary>
	/// Summary description for MagicAjaxConfiguration.
	/// </summary>
	public class MagicAjaxConfiguration
	{
		#region Private Fields
		private Hashtable _state = new Hashtable();
		private bool _isLocked = false;

		private PageStore _pageStore;
        // web.config settings
		private string _origScriptPath;
		private OutputCompareMode _origCompareMode;
		private bool _origTracing;
		// active settings
		private string _scriptPath;
		private OutputCompareMode _compareMode;
		private bool _tracing;
		#endregion

		#region Public Properties
		public string ScriptPath
		{
			get { return _scriptPath; }
			set
			{
				if ( _isLocked && value != _scriptPath )
					throw new MagicAjaxException("Configuration settings have been locked and cannot change.");

				_scriptPath = value;
				if ( value != _origScriptPath )
				{
					_state["ScriptPath"] = _scriptPath;
				}
				else
				{
					_state.Remove("ScriptPath");
				}
			}
		}

		public OutputCompareMode CompareMode
		{
			get { return _compareMode; }
			set
			{
				if ( _isLocked && value != _compareMode )
					throw new MagicAjaxException("Configuration settings have been locked and cannot change.");

				_compareMode = value;
				if ( value != _origCompareMode )
				{
					_state["CompareMode"] = _compareMode;
				}
				else
				{
					_state.Remove("CompareMode");
				}
			}
		}

		public bool Tracing
		{
			get { return _tracing; }
			set
			{
				if ( _isLocked && value != _tracing )
					throw new MagicAjaxException("Configuration settings have been locked and cannot change.");

				_tracing = value;
				if ( value != _origTracing )
				{
					_state["Tracing"] = _tracing;
				}
				else
				{
					_state.Remove("Tracing");
				}
			}
		}

		public PageStore PageStore
		{
			get { return _pageStore; }
		}
		#endregion

		internal bool IsDirty
		{
			get { return ( _state.Keys.Count > 0 || _pageStore.IsDirty ); }
		}

		internal bool IsLocked
		{
			get { return _isLocked; }
			set 
			{
				_isLocked = value; 
				_pageStore.IsLocked = value;
			}
		}

		internal string GetState()
		{
			if ( ! IsDirty )
				return null;

			if ( _pageStore.IsDirty )
				_state["PageStoreState"] = _pageStore.State;

			System.IO.StringWriter writer = new System.IO.StringWriter();
			new LosFormatter().Serialize(writer, _state);

			_state.Remove("PageStoreState");
			return writer.ToString();
		}

		internal void LoadState(string stateString)
		{
			Hashtable state = new LosFormatter().Deserialize(stateString) as Hashtable;
			foreach (string key in state.Keys)
			{
				switch (key)
				{
					case "ScriptPath":
						ScriptPath = (string) state[key];
						break;
					case "CompareMode":
						CompareMode = (OutputCompareMode) state[key];
						break;
					case "Tracing":
						Tracing = (bool) state[key];
						break;
					case "PageStoreState":
						_pageStore.State = (Hashtable) state[key];
						break;
					default:
						throw new MagicAjaxException(String.Format("MagicAjaxConfiguration.LoadState: Unknown property '{0}'.", key));
				}
			}
		}

		public MagicAjaxConfiguration(XmlNode xml)
		{
			// Default values
			_scriptPath = null; // Null implicates that the embedded javascripts will be used (default)
			_compareMode = OutputCompareMode.HashCode;
			_tracing = false;
			PageStoreMode mode = PageStoreMode.NoStore;
			bool unloadStoredPage = false;
			int cacheTimeout = 5;
			int maxPages = 5;
			bool maxPagesLimitAlert = false;

			if (xml != null)
			{
				XmlAttribute attrib = (XmlAttribute)xml.Attributes.GetNamedItem("scriptPath");
				if (attrib != null)
				{
					// Resolve relative scriptPath url's (starting with "~")
					_scriptPath = Util.ResolveUrl(attrib.Value);
				}

				attrib = (XmlAttribute)xml.Attributes.GetNamedItem("outputCompareMode");
				if (attrib != null)
				{
					switch (attrib.Value.ToLower(System.Globalization.CultureInfo.InvariantCulture))
					{
						case "hashcode":
							_compareMode = OutputCompareMode.HashCode;
							break;
						case "md5":
							_compareMode = OutputCompareMode.MD5;
							break;
						case "fullhtml":
							_compareMode = OutputCompareMode.FullHtml;
							break;
						default:
							throw new ConfigurationException("MagicAjax configuration: value for outputCompareMode must be \"HashCode\" or \"MD5\" or \"FullHtml\".");
					}
				}

				attrib = (XmlAttribute)xml.Attributes.GetNamedItem("tracing");
				if (attrib != null)
				{
					try
					{
						_tracing = bool.Parse(attrib.Value);
					}
					catch
					{
						throw new ConfigurationException("MagicAjax configuration: tracing must be boolean.");
					}
				}

				XmlNode pageStore = xml["pageStore"];
				attrib = (XmlAttribute)pageStore.Attributes.GetNamedItem("mode");
				if (attrib != null)
				{
					switch (attrib.Value.ToLower(System.Globalization.CultureInfo.InvariantCulture))
					{
						case "nostore":
							mode = PageStoreMode.NoStore;
							break;
						case "session":
							mode = PageStoreMode.Session;
							break;
						case "cache":
							mode = PageStoreMode.Cache;
							break;
						default:
							throw new ConfigurationException("MagicAjax configuration: mode for pageStore must be \"NoStore\" or \"Session\" or \"Cache\".");
					}
				}

				attrib = (XmlAttribute)pageStore.Attributes.GetNamedItem("unloadStoredPage");
				if (attrib != null)
				{
					try
					{
						unloadStoredPage = bool.Parse(attrib.Value);
					}
					catch
					{
						throw new ConfigurationException("MagicAjax configuration: unloadStoredPage for pageStore must be boolean.");
					}
				}

				attrib = (XmlAttribute)pageStore.Attributes.GetNamedItem("cacheTimeout");
				if (attrib != null)
				{
					try
					{
						cacheTimeout = Int32.Parse(attrib.Value);
					}
					catch
					{
						throw new ConfigurationException("MagicAjax configuration: cacheTimeout for pageStore must be integer.");
					}
					if (cacheTimeout < 1)
						throw new ConfigurationException("MagicAjax configuration: cacheTimeout for pageStore must be 1 or greater.");
				}

				attrib = (XmlAttribute)pageStore.Attributes.GetNamedItem("maxConcurrentPages");
				if (attrib != null)
				{
					try
					{
						maxPages = Int32.Parse(attrib.Value);
					}
					catch
					{
						throw new ConfigurationException("MagicAjax configuration: maxConcurrentPages for pageStore must be integer.");
					}
					if (maxPages < 1)
						throw new ConfigurationException("MagicAjax configuration: maxConcurrentPages for pageStore must be 1 or greater.");
				}

				attrib = (XmlAttribute)pageStore.Attributes.GetNamedItem("maxPagesLimitAlert");
				if (attrib != null)
				{
					try
					{
						maxPagesLimitAlert = bool.Parse(attrib.Value);
					}
					catch
					{
						throw new ConfigurationException("MagicAjax configuration: maxPagesLimitAlert for pageStore must be boolean.");
					}
				}
			}

			_pageStore = new PageStore(mode, unloadStoredPage, cacheTimeout, maxPages, maxPagesLimitAlert);
			_origScriptPath = _scriptPath;
			_origCompareMode = _compareMode;
			_origTracing = _tracing;
		}
	}
}

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, along with any associated source code and files, is licensed under The MIT License


Written By
Web Developer
Greece Greece
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions