#if NET_2_0
[assembly: InternalsVisibleTo ("System.Web.Extensions, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
+[assembly: InternalsVisibleTo ("System.Web_test_net_2_0, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")]
#endif
#endif
+2008-01-07 Dean Brettle <dean@brettle.com>
+
+ * AssemblyInfo.cs: made InternalsVisibleTo System.Web.test_net_2_0.dll
+ to support ControlAdapterTest.ConfigCapabilitiesNotCalled().
+
2007-11-22 Gert Driesen <drieseng@users.sourceforge.net>
* AssemblyInfo.cs: InternalsVisibleTo is 2.0 only. Fixes 1.0 profile
+2008-03-09 Dean Brettle <dean@brettle.com>
+
+ * System.Web_test.dll.sources: added
+ System.Web.UI.WebControls.Adapters/MenuAdapterTest.cs
+ System.Web.UI.WebControls.Adapters/WebControlAdapterTest.cs
+ System.Web.UI.WebControls.Adapters/HierarchicalDataBoundControlAdapterTest.cs
+ System.Web.UI.WebControls.Adapters/DataBoundControlAdapterTest.cs
+ System.Web.UI.WebControls.Adapters/HideDisabledControlAdapterTest.cs
+ System.Web.UI.Adapters/PageAdapterTest.cs
+ System.Web.UI.Adapters/ControlAdapterTest.cs
+
+ * Makefile (RESOURCE_FILES_2): added
+ System.Web.Configuration_2.0/RandomRoboBotKeywords.txt
+
+ * Makefile (TEST_RESOURCE_FILES): added
+ Test/mainsoft/NunitWebResources/PageWithAdapter.aspx
+
+ * System.Web.dll.sources: added
+ System.Web.Configuration_2.0/CapabilitiesBuild.cs
+ System.Web.Configuration_2.0/CapabilitiesChecksum.cs
+ System.Web.Configuration_2.0/CapabilitiesResult.cs
+ System.Web.Configuration_2.0/ICapabilitiesProcess.cs
+ System.Web.Configuration_2.0/nBrowser/Result.cs
+ System.Web.Configuration_2.0/nBrowser/NodeTypes.cs
+ System.Web.Configuration_2.0/nBrowser/Identification.cs
+ System.Web.Configuration_2.0/nBrowser/File.cs
+ System.Web.Configuration_2.0/nBrowser/Build.cs
+ System.Web.Configuration_2.0/nBrowser/Node.cs
+ System.Web.Configuration_2.0/nBrowser/Exception.cs
+
2008-03-01 Marek Habersack <mhabersack@novell.com>
* Makefile: added a dependency on Mono.Web.dll
resources/transparent.gif \
resources/webform.js \
resources/WebUIValidation_2.0.js \
+ System.Web.Configuration_2.0/RandomRoboBotKeywords.txt \
System.Web.UI.WebControls/GridView.js \
System.Web.UI.WebControls/DetailsView.js \
System.Web.UI.WebControls/TreeView.js \
Test/mainsoft/NunitWebResources/TextBoxTestlPage.aspx \
Test/mainsoft/NunitWebResources/ClearErrorOnError.aspx \
Test/mainsoft/NunitWebResources/RedirectOnError.aspx \
+ Test/mainsoft/NunitWebResources/TestCapability.browser \
+ Test/mainsoft/NunitWebResources/PageWithAdapter.aspx \
Test/mainsoft/MainsoftWebTest/nunitweb_config.xml
RESX_DIST = resources/TranslationResources.resx
+2008-03-09 Dean Brettle <dean@brettle.com>
+
+ * HttpCapabilitiesBase.cs: changed to use nBrowser for *.browser
+ support. Also added internal GetConfigCapabilities_called
+ flag used by ControlAdapterTest.ConfigCapabilitiesNotCalled() to
+ test that GetConfigCapabilities() is not called during normal page
+ processing when there are no files in App_Browsers/.
+
2008-02-28 Marek Habersack <mhabersack@novell.com>
* HandlerFactoryConfiguration.cs: ignore case when matching
public class HttpCapabilitiesBase
#endif
{
- IDictionary capabilities;
+ internal IDictionary capabilities;
public HttpCapabilitiesBase () { }
#endif
return ua;
}
+ private static HttpBrowserCapabilities GetHttpBrowserCapabilitiesFromBrowscapini(string ua)
+ {
+ HttpBrowserCapabilities bcap = new HttpBrowserCapabilities();
+ bcap.capabilities = CapabilitiesLoader.GetCapabilities (ua);
+ return bcap;
+ }
public static HttpCapabilitiesBase GetConfigCapabilities (string configKey, HttpRequest request)
{
- string ua = GetUserAgentForDetection (request);
+ string ua = GetUserAgentForDetection (request);
- HttpBrowserCapabilities bcap = new HttpBrowserCapabilities ();
+ HttpBrowserCapabilities bcap = null;
+#if NET_2_0
+ GetConfigCapabilities_called = true;
+ if (HttpApplicationFactory.AppBrowsersFiles.Length > 0)
+ bcap = HttpApplicationFactory.CapabilitiesProcessor.Process(request);
+ else
+ bcap = GetHttpBrowserCapabilitiesFromBrowscapini(ua);
+#else
+ bcap = GetHttpBrowserCapabilitiesFromBrowscapini(ua);
+#endif
bcap.useragent = ua;
- bcap.capabilities = CapabilitiesLoader.GetCapabilities (ua);
bcap.Init ();
return bcap;
}
+#if NET_2_0
+ // Used by unit tests to determine whether GetConfigCapabilities was called.
+ static internal bool GetConfigCapabilities_called;
+#endif
protected virtual void Init ()
{
}
--- /dev/null
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+namespace System.Web.Configuration
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+
+ internal abstract class CapabilitiesBuild : ICapabilitiesProcess
+ {
+ /// <summary>
+ /// A list of all headers, that the Browser Detective Code will possibly access.
+ /// </summary>
+ private System.Collections.ObjectModel.Collection<string> AllPossibleheaders;
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="list"></param>
+ /// <returns></returns>
+ protected abstract System.Collections.ObjectModel.Collection<string> HeaderNames(System.Collections.ObjectModel.Collection<string> list);
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="userAgent"></param>
+ /// <returns></returns>
+ public System.Web.Configuration.CapabilitiesResult Process(string userAgent)
+ {
+ System.Collections.Specialized.NameValueCollection header;
+ header = new System.Collections.Specialized.NameValueCollection(1);
+ header.Add("User-Agent", userAgent);
+ return Process(header);
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="request"></param>
+ /// <returns></returns>
+ public System.Web.Configuration.CapabilitiesResult Process(System.Web.HttpRequest request)
+ {
+ if (request != null)
+ {
+ return Process(request.Headers);
+ }
+ else
+ {
+ return Process("");
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="header"></param>
+ /// <returns></returns>
+ public abstract System.Web.Configuration.CapabilitiesResult Process(System.Collections.Specialized.NameValueCollection header);
+ /// <summary>
+ /// Creates a Checksum from the Header values used by the Browser Detection System.
+ /// </summary>
+ /// <param name="header">List of Header name/value pairs</param>
+ /// <returns>checksum value to be used for caching/duplicate checks</returns>
+ public virtual string HeaderChecksum(System.Collections.Specialized.NameValueCollection header)
+ {
+ if (AllPossibleheaders == null)
+ {
+ AllPossibleheaders = this.HeaderNames(new System.Collections.ObjectModel.Collection<string>());
+ }
+ System.IO.MemoryStream stream = new System.IO.MemoryStream();
+ System.IO.StreamWriter writer = new System.IO.StreamWriter(stream, System.Text.Encoding.Default);
+
+ for (int i = 0;i <= AllPossibleheaders.Count - 1;i++)
+ {
+ if (String.IsNullOrEmpty(header[AllPossibleheaders[i]]) == false)
+ {
+ writer.WriteLine(header[AllPossibleheaders[i]]);
+ }
+ }
+ writer.Flush();
+ byte[] array = stream.ToArray();
+ writer.Close();
+ return CapabilitiesChecksum.BuildChecksum(array);
+ }
+ /// <summary>
+ /// Provides a Method to Load the Browser Detection class with a default Data file that is
+ /// embeded in the dll.
+ /// </summary>
+ public abstract void LoadDefaultEmbeddedResource();
+
+ public virtual string DataFileVersion
+ {
+ get
+ {
+ return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ }
+ }
+ }
+}
+#endif
--- /dev/null
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+using System;
+using System.Collections;
+using System.Text;
+
+namespace System.Web.Configuration
+{
+ internal class CapabilitiesChecksum
+ {
+ public CapabilitiesChecksum()
+ {
+ }
+ public static string BuildChecksum(string raw)
+ {
+ byte[] array = System.Text.Encoding.Default.GetBytes(raw.ToCharArray());
+ array = System.Security.Cryptography.MD5.Create().ComputeHash(array);
+ string[] c = new string[array.Length];
+ for (int i = 0;i <= array.Length - 1;i++)
+ {
+ c[i] = CapabilitiesChecksum.Hex(array[i]);
+ }
+ array = null;
+ return string.Join("", c);
+ }
+ public static string BuildChecksum(byte[] array)
+ {
+ array = System.Security.Cryptography.MD5.Create().ComputeHash(array);
+ string[] c = new string[array.Length];
+ for (int i = 0;i <= array.Length - 1;i++)
+ {
+ c[i] = CapabilitiesChecksum.Hex(array[i]);
+ }
+ array = null;
+ return string.Join("", c);
+ }
+
+ private static string Hex(byte b)
+ {
+ char[] list = new char[2];
+ BitArray myBA1 = new BitArray(new bool[4] { false, false, false, false });
+ BitArray myBA2 = new BitArray(new bool[4] { false, false, false, false });
+ BitArray myBA3 = new BitArray(new byte[] { b });
+
+ //1 byte = 8 bits
+ //4 bits = 1 Hex Value.
+ myBA1.Set(0, myBA3.Get(0));
+ myBA1.Set(1, myBA3.Get(1));
+ myBA1.Set(2, myBA3.Get(2));
+ myBA1.Set(3, myBA3.Get(3));
+
+ myBA2.Set(0, myBA3.Get(4));
+ myBA2.Set(1, myBA3.Get(5));
+ myBA2.Set(2, myBA3.Get(6));
+ myBA2.Set(3, myBA3.Get(7));
+
+ list[0] = CapabilitiesChecksum.MapToHex(myBA1);
+ list[1] = CapabilitiesChecksum.MapToHex(myBA2);
+ return new string(list, 0, 2);
+ }
+ private static char MapToHex(BitArray a)
+ {
+ //-----------------------------------------------------------------------------------
+ //I could of done bit wise comparisons much more efficiant, but that would of given
+ //me a bigger headach then this. Which I can reason though even half asleep.
+ //-----------------------------------------------------------------------------------
+ if (a.Get(0) == false && a.Get(1) == false && a.Get(2) == false && a.Get(3) == false)
+ {
+ return '0';
+ }
+ else if (a.Get(0) == true && a.Get(1) == false && a.Get(2) == false && a.Get(3) == false)
+ {
+ return '1';
+ }
+ else if (a.Get(0) == false && a.Get(1) == true && a.Get(2) == false && a.Get(3) == false)
+ {
+ return '2';
+ }
+ else if (a.Get(0) == true && a.Get(1) == true && a.Get(2) == false && a.Get(3) == false)
+ {
+ return '3';
+ }
+ else if (a.Get(0) == false && a.Get(1) == false && a.Get(2) == true && a.Get(3) == false)
+ {
+ return '4';
+ }
+ else if (a.Get(0) == true && a.Get(1) == false && a.Get(2) == true && a.Get(3) == false)
+ {
+ return '5';
+ }
+ else if (a.Get(0) == false && a.Get(1) == true && a.Get(2) == true && a.Get(3) == false)
+ {
+ return '6';
+ }
+ else if (a.Get(0) == true && a.Get(1) == true && a.Get(2) == true && a.Get(3) == false)
+ {
+ return '7';
+ }
+ else if (a.Get(0) == false && a.Get(1) == false && a.Get(2) == false && a.Get(3) == true)
+ {
+ return '8';
+ }
+ else if (a.Get(0) == true && a.Get(1) == false && a.Get(2) == false && a.Get(3) == true)
+ {
+ return '9';
+ }
+ else if (a.Get(0) == false && a.Get(1) == true && a.Get(2) == false && a.Get(3) == true)
+ {
+ return 'A';
+ }
+ else if (a.Get(0) == true && a.Get(1) == true && a.Get(2) == false && a.Get(3) == true)
+ {
+ return 'B';
+ }
+ else if (a.Get(0) == false && a.Get(1) == false && a.Get(2) == true && a.Get(3) == true)
+ {
+ return 'C';
+ }
+ else if (a.Get(0) == true && a.Get(1) == false && a.Get(2) == true && a.Get(3) == true)
+ {
+ return 'D';
+ }
+ else if (a.Get(0) == false && a.Get(1) == true && a.Get(2) == true && a.Get(3) == true)
+ {
+ return 'E';
+ }
+ else if (a.Get(0) == true && a.Get(1) == true && a.Get(2) == true && a.Get(3) == true)
+ {
+ return 'F';
+ }
+ //this should never ever happen, unless a bit
+ //gets switched mid way though the checks.
+ throw new System.Exception("shit fell threw");
+ }
+ }
+}
+#endif
--- /dev/null
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+
+ internal class CapabilitiesResult : System.Web.HttpBrowserCapabilities
+ {
+ private string[] RandomRoboBotKeywords;
+ /// <summary>
+ /// Initializes a new instance of the Result class.
+ /// </summary>
+ /// <param name="items">
+ /// This is the data which this class will be handle request made though this class.
+ /// </param>
+ internal CapabilitiesResult(System.Collections.Generic.Dictionary<string, string> items)
+ : base()
+ {
+ base.Capabilities = items;
+
+ //---------------------------------------------------------------
+ //Copies out a list of keywords stored in an Embeded file, which
+ //will be used to help determine if a browser is
+ //IsRandomRoboBotUserAgent.
+ //---------------------------------------------------------------
+ System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
+ System.IO.Stream CP;
+ CP = asm.GetManifestResourceStream("RandomRoboBotKeywords.txt");
+ System.IO.StreamReader Read = new System.IO.StreamReader(CP, System.Text.Encoding.Default);
+ RandomRoboBotKeywords = System.Text.RegularExpressions.Regex.Split(Read.ReadToEnd(), System.Environment.NewLine);
+ Read.Close();
+ Read = null;
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="name"></param>
+ /// <param name="value"></param>
+ internal void AddCapabilities(string name, string value)
+ {
+ this.Capabilities[name] = value;
+ }
+ internal virtual string Replace(string item)
+ {
+ if (item.IndexOf("$") > -1)
+ {
+ //nasty hack to convert regular expression replacement text into Capability item
+ //which we can use to replace with the actual values they are looking for.
+ System.Text.RegularExpressions.MatchCollection regxmatch;
+ regxmatch = System.Text.RegularExpressions.Regex.Matches(item, @"\$\{(?'Capability'\w*)\}");
+ if (regxmatch.Count == 0)
+ {
+ return item;
+ }
+ for (int i = 0;i <= regxmatch.Count - 1;i++)
+ {
+ if (regxmatch[i].Success == true)
+ {
+ string c = regxmatch[i].Result("${Capability}");
+ item = item.Replace("${" + c + "}", this[c]);
+ }
+ }
+ }
+ if (item.IndexOf("%") > -1)
+ {
+ //nasty hack to convert regular expression replacement text into Capability item
+ //which we can use to replace with the actual values they are looking for.
+ System.Text.RegularExpressions.MatchCollection regxmatch;
+ regxmatch = System.Text.RegularExpressions.Regex.Matches(item, @"\%\{(?'Capability'\w*)\}");
+ if (regxmatch.Count == 0)
+ {
+ return item;
+ }
+ for (int i = 0;i <= regxmatch.Count - 1;i++)
+ {
+ if (regxmatch[i].Success == true)
+ {
+ string c = regxmatch[i].Result("${Capability}");
+ item = item.Replace("%{" + c + "}", this[c]);
+ }
+ }
+ }
+ return item;
+ }
+ /// <summary>
+ /// Gets the Operating System that the browser is running on.
+ /// </summary>
+ public string OS
+ {
+ get
+ {
+ return this["os"];
+ }
+ }
+ /// <summary>
+ /// Gets the browsers Build.
+ /// </summary>
+ public string BrowserBuild
+ {
+ get
+ {
+ return this["BrowserBuild"];
+ }
+ }
+ /// <summary>
+ /// Name of the Browser Rendering Engine, when known.
+ /// </summary>
+ public string BrowserRenderingEngine
+ {
+ get
+ {
+ return this["HtmlEngine"];
+ }
+ }
+ /// <summary>
+ /// Gets if the Browser was identified as a bot, as a mater of elimination of all other possible
+ /// options currently availible.
+ /// </summary>
+ public bool IsRobot
+ {
+ get
+ {
+ if (string.Compare(this["IsMobileDevice"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ return false;
+ }
+ else if (string.Compare(this["IsBot"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ return true;
+ }
+ else if (string.Compare(this["crawler"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ return true;
+ }
+ else if (string.Compare(this["Unknown"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ return true;
+ }
+ else if (string.Compare(this.Browser, "Unknown", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ return true;
+ }
+ else if (string.Compare(this.Browser, "IE", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ //too many fake IE's out there this should remove a few of the low
+ //hanging fruit.
+ if (string.IsNullOrEmpty(this.Platform) == true)
+ {
+ return true;
+ }
+ else if (string.Compare(this.Platform, "Unknown", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ return true;
+ }
+ else if (string.Compare(this[""], "....../1.0", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ //I hate Scrapters This one hit me today. Lets see how it like it now geting 403's
+ return true;
+ }
+
+ }
+ return false;
+ }
+ }
+ public bool IsSyndicationReader
+ {
+ get
+ {
+ if (string.Compare(this["IsSyndicationReader"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+ public bool IsUnknown
+ {
+ get
+ {
+ if (string.Compare(this["Unknown"], "true", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+ /// <summary>
+ /// Used to Identify Robobots that are using randomly generated Useragents
+ /// that are nonsensical in nature/gibberish.
+ /// </summary>
+ /// <remarks>
+ /// Current implementation is more of an elimination of common traits, which
+ /// most Useragent/browser have. Which leave us with what can be assumed as
+ /// randomized useragent names, which serve no purpose cept to drive stats
+ /// programs nuts.
+ /// </remarks>
+ public bool IsRandomRobobotUserAgent
+ {
+ get
+ {
+ #region Check for Common Words in UserAgents
+ //---------------------------------------------------------------
+ //Quick Checks to see if the Bot has been identified by a name
+ //from the headers provided.
+ //---------------------------------------------------------------
+ if (this.IsRobot == false)
+ {
+ //---------------------------------------------------------------
+ //Since we can determine its not a Robot. We must have enough
+ //details to prove its not a random useragent, and we move on.
+ //---------------------------------------------------------------
+ return false;
+ }
+ else if (this.IsSyndicationReader == true)
+ {
+ //---------------------------------------------------------------
+ //Since we can determine its not a Rss/Atom Feed Reader. We must
+ //have enough details to prove its not a random useragent, and we
+ //move on.
+ //---------------------------------------------------------------
+ return false;
+ }
+ else if (string.Compare(this.Browser, "Unknown", true, System.Globalization.CultureInfo.CurrentCulture) != 0)
+ {
+ //---------------------------------------------------------------
+ //Browser name was able to be determined then the Useragent had
+ //enough details, thus not a random Useragent.
+ //---------------------------------------------------------------
+ return false;
+ }
+ else if (string.Compare(this.Platform, "Unknown", true, System.Globalization.CultureInfo.CurrentCulture) != 0)
+ {
+ //---------------------------------------------------------------
+ //Assume if a platform was able to be determine then the Useragent
+ //is more then likely not randomized name.
+ //---------------------------------------------------------------
+ return false;
+ }
+ else if (string.IsNullOrEmpty(this.UserAgent) == true)
+ {
+ //---------------------------------------------------------------
+ //Null or empty. ^he Programer was just to lazy which to give it a
+ //name, which is fine with me but doesn't not count as a Randomized
+ //Browser Agent, since it doesn't have a Useragent at all to begin
+ //with.
+ //---------------------------------------------------------------
+ return false;
+ }
+
+ //---------------------------------------------------------------
+ //I assume ones under 8 charactors are not really randomly named
+ //but the coder was just lazy or picked a short name.
+ //---------------------------------------------------------------
+ if (this.UserAgent.Length < 8)
+ {
+ return false;
+ }
+
+ //---------------------------------------------------------------
+ //Up to this point I have not seen a randomly generated Agent string
+ //with a period in it.
+ //---------------------------------------------------------------
+ if (this.UserAgent.IndexOf('.') > -1)
+ {
+ return false;
+ }
+ //---------------------------------------------------------------
+ //Compare keywords often found in useragents to the current useragent
+ //and if we find one we assume its not a randomized useragent.
+ //---------------------------------------------------------------
+ foreach (string keyword in RandomRoboBotKeywords)
+ {
+ if (keyword.Length <= this.UserAgent.Length)
+ {
+ if (this.UserAgent.IndexOf(keyword, StringComparison.CurrentCultureIgnoreCase) != -1)
+ {
+ return false;
+ }
+ }
+ }
+ #endregion
+ //---------------------------------------------------------------
+ //Since it made it though all the checks I assume that the useragent
+ //doesn't match any known format that I can determine, and label it
+ //a randomized Useragent/browser. AKA SPAM / Scraper / Pests Bots.
+ //---------------------------------------------------------------
+ return true;
+ }
+ }
+ /// <summary>
+ /// Gets the keys returned from processing.
+ /// </summary>
+ public System.Collections.Specialized.StringCollection Keys
+ {
+ get
+ {
+ string[] a = new string[this.Capabilities.Keys.Count];
+ this.Capabilities.Keys.CopyTo(a, 0);
+ System.Array.Sort(a);
+ System.Collections.Specialized.StringCollection l;
+ l = new System.Collections.Specialized.StringCollection();
+ l.AddRange(a);
+ return l;
+ }
+ }
+ public string UserAgent
+ {
+ get
+ {
+ return this[""];
+ }
+ }
+ }
+}
+#endif
+2008-03-09 Dean Brettle <dean@brettle.com>
+
+ * nBrowser/Result.cs, nBrowser/NodeTypes.cs, nBrowser/Identification.cs,
+ nBrowser/File.cs, nBrowser/Build.cs, nBrowser/Node.cs,
+ nBrowser/Exception.cs: added. The code under nBrowser handles *.browser
+ files. It is based on Owen "Ocean" Brady's code, with the following
+ changes and improvements. Replaced Result.Adapter
+ property with AdapterTypeMap property which maps control Type to adapter
+ Type. Added Result.MarkupTextWriter property. Added overrides for
+ Result.GetAdapters and Result.GetTagWriter to return MarkupTextWriter
+ and AdapterTypeMap, resp. Changed tree building algorithm to not
+ depend on nodes with id="Default" and to inject defaultBrowser nodes
+ as parents of regular nodes with the same ids. Changed Node.cs to use
+ Item instead of Add when adding a capability or sample header, so that
+ values get replaced instead of appended. Added support for reference
+ nodes (ie. nodes with refID="someID").
+
+ * CapabilitiesResult.cs: load RandomRoboBotKeywords.txt resource
+ using the correct name.
+
+ * RandomRoboBotKeywords.txt: added
+
+ * HttpCapabilitiesBase.cs (CreateHtmlWriter, Adapters): Added
+ support for *.browsers. Adapters property calls internal virtual
+ GetAdapters() method which is overrided in nBrowser.Result
+ returned by nBrowser code. CreateHtmlWriter uses type specified
+ by TagWriter property.
+
2008-03-03 Vladimir Krasnov <vladimirk@mainsoft.com>
* ProvidersHelper.cs: fixed thread safety issue in InstantiateProvider
public HtmlTextWriter CreateHtmlTextWriter (TextWriter w)
{
- return new HtmlTextWriter (w);
+ return (HtmlTextWriter) Activator.CreateInstance (TagWriter, new object[] {w});
}
public void DisableOptimizedCacheKey ()
public IDictionary Adapters {
get {
if (!Get (HaveAdapters)) {
- adapters = new Hashtable ();
+ adapters = GetAdapters();
Set (HaveAdapters);
}
return adapters;
}
}
+
+ internal virtual IDictionary GetAdapters ()
+ {
+ return new Hashtable();
+ }
bool canCombineFormsInDeck;
public virtual bool CanCombineFormsInDeck {
--- /dev/null
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+
+ internal interface ICapabilitiesProcess
+ {
+ System.Web.Configuration.CapabilitiesResult Process(string userAgent);
+ System.Web.Configuration.CapabilitiesResult Process(System.Web.HttpRequest request);
+ System.Web.Configuration.CapabilitiesResult Process(System.Collections.Specialized.NameValueCollection header);
+ }
+}
+#endif
--- /dev/null
+/
+\
+_
+Agent
+Auto
+beta
+book
+bot
+Browse
+bug
+build
+check
+class
+client
+cold
+College
+compatible
+Contribute
+crawl
+Desktop
+discovery
+Download
+Eudora
+example
+explore
+favorg
+Fetch
+file
+finder
+flash
+form
+fox
+free
+Friend
+get
+google
+http
+IE
+Illinois
+Iltrovatore
+Internet
+java
+K-Meleon
+know
+Library
+link
+linux
+load
+locate
+locator
+Lycos
+lynx
+main
+manager
+MASTER
+microsoft
+mind
+Moozilla
+mozilla
+MSIE
+net
+Netscape
+nokia
+Norton
+null
+OpenBSD
+Opera
+play
+Plucker
+Post
+power
+Program
+project
+pure
+proxy
+QuickTime
+Redirector
+Scanner
+scooter
+scrape
+search
+server
+Service
+Site
+sight
+shout
+state
+Sleipnir
+slurp
+Snoopy
+spider
+SPY
+Surf
+source
+telnet
+teoma
+test
+THE
+tool
+tracker
+Tunnel
+Unix
+Update
+URL
+Verified
+Version
+Vista
+Web
+winamp
+Windows
+work
+Xenu
+XML
+Yahoo
+Zeus
+zip
+world
+light
--- /dev/null
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+namespace System.Web.Configuration.nBrowser
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ internal class Build : System.Web.Configuration.CapabilitiesBuild
+ {
+ //This keeps a list of filenames and FileNodes linked
+ private System.Collections.Generic.Dictionary<string, System.Web.Configuration.nBrowser.File> Browserfiles;
+
+ //Just links FileNodes
+ private System.Collections.Generic.List<System.Web.Configuration.nBrowser.File> nbrowserfiles;
+
+ //
+ private System.Collections.Generic.Dictionary<string, string> DefaultKeys;
+ private System.Collections.Generic.Dictionary<string, string> BrowserKeys;
+
+ //
+ private System.Web.Configuration.nBrowser.Node browser;
+
+ /// <summary>
+ ///
+ /// </summary>
+ public Build()
+ : base()
+ {
+ Browserfiles = new System.Collections.Generic.Dictionary<string, System.Web.Configuration.nBrowser.File>();
+ nbrowserfiles = new System.Collections.Generic.List<System.Web.Configuration.nBrowser.File>();
+
+ DefaultKeys = new System.Collections.Generic.Dictionary<string, string>();
+ BrowserKeys = new System.Collections.Generic.Dictionary<string, string>();
+ }
+ /// <summary>
+ /// Reads an entire directory and process's all of the browser files in that
+ /// directory.
+ /// </summary>
+ /// <param name="path"></param>
+ public void AddBrowserDirectory(string path)
+ {
+ //I allow this function to be a little messy
+ //just in case they pass in a path that really a file
+ //name
+ if (System.IO.Directory.Exists(path) == true)
+ {
+ System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(path);
+ System.IO.FileInfo[] file = dir.GetFiles("*.browser");
+ //we are done with it so let the GC have it early as possible
+ dir = null;
+ for (int a = 0;a <= file.Length - 1;a++)
+ {
+ AddBrowserFile(file[a].FullName);
+ }
+ }
+ else if (System.IO.File.Exists(path) == true)
+ {
+ AddBrowserFile(path);
+ }
+ }
+ /// <summary>
+ /// Reads a browser file and builds the Nodes which that file contains.
+ /// </summary>
+ /// <param name="filename"></param>
+ public void AddBrowserFile(string fileName)
+ {
+ if (Browserfiles.ContainsKey(fileName) == false)
+ {
+ nBrowser.File b = new nBrowser.File(fileName);
+ this.AddBrowserFile(b);
+ }
+
+ }
+ private void AddBrowserFile(nBrowser.File file)
+ {
+ if (Browserfiles.ContainsKey(file.FileName) == false)
+ {
+ Browserfiles.Add(file.FileName, file);
+ nbrowserfiles.Add(file);
+
+ string[] keys = file.Keys;
+ for (int i = 0;i <= keys.Length - 1;i++)
+ {
+ if (BrowserKeys.ContainsKey(keys[i]) == false)
+ {
+ BrowserKeys.Add(keys[i], file.FileName);
+ }
+ else
+ {
+ throw new nBrowser.Exception("Duplicate Key \"" + keys[i] + "\" found in " + file.FileName + " and in file " + BrowserKeys[keys[i]]);
+ }
+ }
+ keys = file.DefaultKeys;
+ for (int i = 0;i <= keys.Length - 1;i++)
+ {
+ if (DefaultKeys.ContainsKey(keys[i]) == false)
+ {
+ DefaultKeys.Add(keys[i], file.FileName);
+ }
+ else
+ {
+ throw new nBrowser.Exception("Duplicate Key \"" + keys[i] + "\" found in " + file.FileName + " and in file " + DefaultKeys[keys[i]]);
+ }
+ }
+ }
+ }
+ /// <summary>
+ /// Reads a browser file and builds the Nodes which that file contains.
+ /// </summary>
+ /// <param name="file"></param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059")]
+ public void AddBrowserFile(System.Xml.XmlDocument browser, string fileName)
+ {
+ if (Browserfiles.ContainsKey(fileName) == false)
+ {
+ nBrowser.File file = new nBrowser.File(browser, fileName);
+ this.AddBrowserFile(file);
+ }
+ }
+ /// <summary>
+ /// Returns the root Node of the Browser Tree.
+ /// </summary>
+ /// <returns></returns>
+ public Node Browser()
+ {
+ if (browser != null)
+ {
+ return browser;
+ }
+ browser = new Node();
+ //Custom Sorted List, to allow where Multple files in Diff directorys might have the same
+ //filename. So still to some degree first come first serve but might be close enough
+ //to how microsoft System to match much more closely.
+ System.Collections.Generic.SortedList<string, System.Collections.Generic.List<nBrowser.File>> list;
+ list = new System.Collections.Generic.SortedList<string, System.Collections.Generic.List<nBrowser.File>>();
+
+ for (int i = 0;i <= Browserfiles.Count - 1;i++)
+ {
+ if (list.ContainsKey(nbrowserfiles[i].FileName) == false)
+ {
+ System.Collections.Generic.List<nBrowser.File> l;
+ l = new System.Collections.Generic.List<nBrowser.File>();
+ list.Add(nbrowserfiles[i].FileName, l);
+ }
+ list[nbrowserfiles[i].FileName].Add(nbrowserfiles[i]);
+ }
+ nBrowser.File[] files = new nBrowser.File[Browserfiles.Count];
+
+ int count = 0;
+ for (int i = 0;i <= list.Count - 1;i++)
+ {
+ System.Collections.Generic.List<nBrowser.File> l = list[list.Keys[i]];
+ for (int b = 0;b <= l.Count - 1;b++)
+ {
+ files[count] = l[b];
+ count++;
+ }
+ }
+
+ #region Connect Nodes
+ for (int i = 0;i <= Browserfiles.Count - 1;i++)
+ {
+ for (int a = 0;a <= files[i].Keys.Length - 1;a++)
+ {
+ Node child = files[i].GetNode(files[i].Keys[a]);
+ Node parent = null;
+ if (child.ParentId.Length > 0)
+ {
+ parent = this.GetNode(child.ParentId);
+ if (parent == null)
+ throw new nBrowser.Exception(String.Format("Parent not found with = {0}", child.ParentId));
+ }
+ if (parent == null)
+ parent = browser;
+ parent.AddChild(child);
+ }
+ }
+ #endregion
+
+ #region Inject DefaultBrowser Nodes
+ for (int i = 0;i <= Browserfiles.Count - 1;i++)
+ {
+ for (int a = 0;a <= files[i].DefaultKeys.Length - 1;a++)
+ {
+ Node defaultNode = files[i].GetDefaultNode(files[i].DefaultKeys[a]);
+ Node node = this.GetNode(defaultNode.Id);
+ if (node == defaultNode)
+ {
+ // there is no regular node so the defaultNode is already at
+ // the correct spot in the tree.
+ continue;
+ }
+ Node parentNode = this.GetNode(node.ParentId);
+ if (parentNode == null)
+ parentNode = browser;
+ // insert the default node between the regular node and it's parent.
+ parentNode.RemoveChild(node);
+ defaultNode.AddChild(node);
+ parentNode.AddChild(defaultNode);
+ }
+ }
+ #endregion
+
+ #region Merge Ref Nodes
+ for (int i = 0;i <= Browserfiles.Count - 1;i++)
+ {
+ foreach (Node refNode in files[i].RefNodes) {
+ GetNode(refNode.RefId).MergeFrom(refNode);
+ }
+ }
+ #endregion
+
+ return browser;
+ }
+
+ /// <summary>
+ /// returns a Node Matching the Key supplied, for either a
+ /// DefaultBrowser, or Gatway/Browser node.
+ /// </summary>
+ /// <param name="Key"></param>
+ /// <returns></returns>
+ private Node GetNode(string Key)
+ {
+ if (Key == null || Key.Length == 0)
+ return null;
+
+ string filename;
+ //Must find what file node that this key is located in
+ //so we look it up in the string dictionary's
+ if (!BrowserKeys.TryGetValue(Key, out filename)
+ && !DefaultKeys.TryGetValue(Key, out filename))
+ return null;
+
+ //fxcop sugguested this was faster then
+ //filename!= string.Empty
+ if (filename != null && filename.Length > 0)
+ {
+ //now that we have a name we look it up in the hasttable containing
+ //the actual node.
+ nBrowser.File b = Browserfiles[filename];
+ Node n = b.GetNode(Key);
+ return n;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Returns an Array of Nodes that have been built. To be used for Design/Editors of Browser
+ /// files.
+ /// </summary>
+ /// <returns></returns>
+ public Node[] Nodes()
+ {
+ Node[] browsers;
+ nBrowser.File[] files = new nBrowser.File[Browserfiles.Count];
+ Browserfiles.Values.CopyTo(files, 0);
+ int count = 0;
+ for (int i = 0;i <= files.Length - 1;i++)
+ {
+ count += files[i].Nodes.Length;
+ }
+ browsers = new Node[count];
+ count = 0;
+ for (int i = 0;i <= files.Length - 1;i++)
+ {
+ for (int a = 0;a <= files[i].Nodes.Length - 1;a++)
+ {
+ browsers[count] = files[i].Nodes[a];
+ count++;
+ }
+ }
+ return browsers;
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="header"></param>
+ /// <returns></returns>
+ public override System.Web.Configuration.CapabilitiesResult Process(System.Collections.Specialized.NameValueCollection header)
+ {
+ System.Web.Configuration.nBrowser.Result r = new System.Web.Configuration.nBrowser.Result(new System.Collections.Generic.Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase));
+
+#if trace
+ System.Diagnostics.Trace.WriteLine(string.Join("+", new string[50]));
+ for (int i=0;i <= header.Count -1;i++)
+ {
+ System.Diagnostics.Trace.WriteLine(string.Format("{0}{1}",header.GetKey(i).PadRight(25),header[i]));
+ }
+ System.Diagnostics.Trace.WriteLine(string.Join("+", new string[50]));
+#endif
+ return Browser().Process(header, r, new System.Collections.Generic.List<System.Web.Configuration.nBrowser.Identification>());
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="list"></param>
+ /// <returns></returns>
+ protected override System.Collections.ObjectModel.Collection<string> HeaderNames(System.Collections.ObjectModel.Collection<string> list)
+ {
+ return this.Browser().HeaderNames(list);
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <returns></returns>
+ public override void LoadDefaultEmbeddedResource()
+ {
+ System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
+ System.IO.Stream CP;
+ CP = asm.GetManifestResourceStream("System.Web.Configuration.Resources.CodeProject.browser");
+ System.Xml.XmlDocument Doc = new System.Xml.XmlDocument();
+ Doc.Load(CP);
+ CP.Close();
+
+ this.AddBrowserFile(Doc, "System.Web.Configuration.Resources.CodeProject.browser");
+ }
+ }
+}
+#endif
--- /dev/null
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration.nBrowser
+{
+ using System;
+ using System.Runtime.Serialization;
+ [
+ System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable"),
+ System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")
+ ]
+ internal class Exception : System.Exception
+ {
+ public Exception()
+ : base()
+ {
+ }
+ public Exception(string errorMessage)
+ : base(errorMessage)
+ {
+ }
+ public Exception(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ // Add any type-specific logic for inner exceptions.
+ }
+ protected Exception(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ // Implement type-specific serialization constructor logic.
+ }
+ }
+}
+/*
+Turns off the following Warning in FxCop
+--------------------------------------------------------------------------------------------------------------------
+[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2237:MarkISerializableTypesWithSerializable")]
+The System.Runtime.Serialization.ISerializable interface allows the type to customize its serialization, while
+the Serializable attribute enables the common language runtime to recognize the type as being serializable."
+--------------------------------------------------------------------------------------------------------------------
+System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")
+Multiple constructors are required to correctly implement a custom exception. Missing constructors can make your
+exception unusable in certain scenarios. For example, the serialization constructor is required for handling
+exceptions in XML Web services.
+--------------------------------------------------------------------------------------------------------------------
+*/
+#endif
--- /dev/null
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration.nBrowser
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Web.Configuration.nBrowser;
+
+ class File
+ {
+ private System.Xml.XmlDocument BrowserFile;
+ internal System.Web.Configuration.nBrowser.Node[] Nodes;
+ private System.Collections.Specialized.ListDictionary Lookup;
+ private System.Collections.Specialized.ListDictionary DefaultLookup;
+ internal List<Node> RefNodes;
+
+ public string FileName
+ {
+ get
+ {
+ return pFileName;
+ }
+ }
+ private string pFileName = string.Empty;
+ public File(string file)
+ {
+ pFileName = file;
+
+ BrowserFile = new System.Xml.XmlDocument();
+ //I can put this in a try /catch but I want
+ //this to bubble up.
+ BrowserFile.Load(file);
+
+ this.Load(BrowserFile);
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="file"></param>
+ public File(System.Xml.XmlDocument BrowserFile, string filename)
+ {
+ pFileName = filename;
+ this.Load(BrowserFile);
+ }
+ private void Load(System.Xml.XmlDocument BrowserFile)
+ {
+ Lookup = new System.Collections.Specialized.ListDictionary();
+ DefaultLookup = new System.Collections.Specialized.ListDictionary();
+ RefNodes = new List<Node>();
+ System.Xml.XmlNode node;
+ //I know this might allocate more nodes then needed but never less.
+ Nodes = new Node[BrowserFile.DocumentElement.ChildNodes.Count];
+ for (int a = 0;a <= BrowserFile.DocumentElement.ChildNodes.Count - 1;a++)
+ {
+ node = BrowserFile.DocumentElement.ChildNodes[a];
+
+ if (node.NodeType == System.Xml.XmlNodeType.Comment)
+ {
+ continue;
+ }
+ Nodes[a] = new Node(node);
+ Nodes[a].FileName = FileName;
+ if (Nodes[a].NameType != NodeType.DefaultBrowser)
+ {
+ //fxcop sugguested this was faster then
+ //Nodes[a].refID != string.Empty
+ if (Nodes[a].RefId.Length > 0)
+ {
+ RefNodes.Add(Nodes[a]);
+ }
+ else if (Lookup.Contains(Nodes[a].Id) == false)
+ {
+ Lookup.Add(Nodes[a].Id, a);
+ }
+ else
+ {
+ throw new nBrowser.Exception("Duplicate ID found \"" + Nodes[a].Id + "\"");
+ }
+ }
+ else
+ {
+ //fxcop sugguested this was faster then
+ //Nodes[a].refID != string.Empty
+ if (Nodes[a].RefId.Length > 0)
+ {
+ RefNodes.Add(Nodes[a]);
+ }
+ else if (DefaultLookup.Contains(Nodes[a].Id) == false)
+ {
+ DefaultLookup.Add(Nodes[a].Id, a);
+ }
+ else
+ {
+ throw new nBrowser.Exception("Duplicate ID found \"" + Nodes[a].Id + "\"");
+ }
+ }
+ }
+ }
+ /// <summary>
+ /// Returns a Array of strings, which represent the Id Attributes of all the
+ /// Browser/Gatway Nodes
+ /// </summary>
+ public string[] Keys
+ {
+ get
+ {
+
+ string[] k = new string[Lookup.Keys.Count];
+ //12-29-05
+ //This will copy the Keys In Alphabetical Order
+ //Lookup.Keys.CopyTo(k,0);
+ //This Method is ment to copy the Keys in the order
+ //that they were in the xml file.
+ int b = 0;
+ for (int i = 0;i <= Nodes.Length - 1;i++)
+ {
+ if (Nodes[i] != null && Nodes[i].NameType != NodeType.DefaultBrowser
+ && Nodes[i].RefId.Length == 0)
+ {
+ k[b] = Nodes[i].Id;
+ b++;
+ }
+ }
+ return k;
+ }
+ }
+ /// <summary>
+ /// Returns a Array of strings, which represent the Id Attributes of all the
+ /// DefaultBrowser Nodes
+ /// </summary>
+ public string[] DefaultKeys
+ {
+ get
+ {
+ string[] k = new string[DefaultLookup.Keys.Count];
+ //12-29-05
+ //This will copy the Keys In Alphabetical Order
+ //DefaultLookup.Keys.CopyTo(k,0);
+ //This Method is ment to copy the Keys in the order
+ //that they were in the xml file.
+ int b = 0;
+ for (int i = 0;i <= Nodes.Length - 1;i++)
+ {
+ if (Nodes[i] != null && Nodes[i].NameType == NodeType.DefaultBrowser)
+ {
+ k[b] = Nodes[i].Id;
+ b++;
+ }
+ }
+ return k;
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="Key"></param>
+ /// <returns></returns>
+ internal Node GetNode(string Key)
+ {
+ object o = Lookup[Key];
+ if (o == null)
+ return GetDefaultNode (Key);
+ return Nodes[(int)o];
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="Key"></param>
+ /// <returns></returns>
+ internal Node GetDefaultNode(string Key)
+ {
+ object o = DefaultLookup[Key];
+ if (o == null)
+ return null;
+ return Nodes[(int)o];
+ }
+ }
+}
+#endif
--- /dev/null
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration.nBrowser
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+
+ class Identification
+ {
+ private bool MatchType = true;
+ private string MatchName = string.Empty;
+ private string MatchGroup = string.Empty;
+ //FxCop will complain that this is assigned to but never used.
+ //Reason I keep it around is to see the actual regex expresion
+ //used without having to drill down deep in regex object to find it
+ private string MatchPattern = string.Empty;
+ private System.Text.RegularExpressions.Regex RegexPattern;
+ private System.Text.RegularExpressions.Match PatternMatch;
+
+ /// <summary>
+ /// Sets up Initial Identification Object, So that it is easier debuging
+ /// and passing Regular expression objects around.
+ /// </summary>
+ /// <param name="matchType">True = Match, False = NonMatch</param>
+ /// <param name="matchGroup">Two Options, capability, header</param>
+ /// <param name="matchName">Header Name</param>
+ /// <param name="matchPattern">Regular Expression Pattern</param>
+ public Identification(bool matchType, string matchGroup, string matchName, string matchPattern)
+ {
+ this.MatchType = matchType;
+ this.MatchGroup = matchGroup;
+ this.MatchName = matchName;
+ this.MatchPattern = matchPattern;
+ RegexPattern = new System.Text.RegularExpressions.Regex(matchPattern);
+ }
+ /// <summary>
+ /// Builds a Match Object from the result of the regular expression
+ /// </summary>
+ /// <param name="Header">Header Value which the regular expression will evaluate.</param>
+ /// <returns>A Match object created from the regular expression and the passed in header.</returns>
+ public System.Text.RegularExpressions.Match Match(string Header)
+ {
+ if (string.IsNullOrEmpty(Header) == false)
+ {
+ PatternMatch = RegexPattern.Match(Header);
+ return PatternMatch;
+ }
+ else
+ {
+ PatternMatch = RegexPattern.Match(string.Empty);
+ return PatternMatch;
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public bool Success
+ {
+ get
+ {
+ if (PatternMatch == null)
+ {
+ throw new nBrowser.Exception("Missing Regular Expression Value, Match Function was not previously called");
+ }
+ if (MatchType == true)
+ {
+ return PatternMatch.Success;
+ }
+ else
+ {
+ return !PatternMatch.Success;
+ }
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public bool HasCaptureGroups
+ {
+ get
+ {
+ if (PatternMatch == null)
+ {
+ throw new nBrowser.Exception("Missing Regular Expression Value, Match Function was not previously called");
+ }
+ if (PatternMatch.Groups.Count > 0)
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="Template"></param>
+ /// <returns></returns>
+ public string Result(string Template)
+ {
+ if (PatternMatch == null)
+ {
+ throw new nBrowser.Exception("Missing Regular Expression Value, Match Function was not previously called");
+ }
+ if (MatchType == true && PatternMatch.Success == true)
+ {
+ return PatternMatch.Result(Template);
+ }
+ return string.Empty;
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public void Reset()
+ {
+ PatternMatch = null;
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public string Name
+ {
+ get
+ {
+ return this.MatchName;
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public string Group
+ {
+ get
+ {
+ return this.MatchGroup;
+ }
+ }
+ public string Pattern
+ {
+ get
+ {
+ return MatchPattern;
+ }
+ }
+ }
+}
+#endif
--- /dev/null
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+namespace System.Web.Configuration.nBrowser
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ internal class Node
+ {
+ #region Public Properties
+ /// <summary>
+ ///
+ /// </summary>
+ public NodeType NameType
+ {
+ get
+ {
+ return pName;
+ }
+ set
+ {
+ pName = value;
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public string Id
+ {
+ get
+ {
+ return pId;
+ }
+ set
+ {
+ pId = value;
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public string ParentId
+ {
+ get
+ {
+ return pParentID;
+ }
+ set
+ {
+ pParentID = value;
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public string RefId
+ {
+ get
+ {
+ return pRefID;
+ }
+ set
+ {
+ pRefID = value;
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public string MarkupTextWriterType
+ {
+ get
+ {
+ return pMarkupTextWriterType;
+ }
+ set
+ {
+ pMarkupTextWriterType = value;
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public string FileName
+ {
+ get
+ {
+ return pFileName;
+ }
+ set
+ {
+ pFileName = value;
+ }
+ }
+ #endregion
+
+ private NodeType pName = NodeType.None;
+ private string pId = string.Empty;
+ private string pParentID = string.Empty;
+ private string pRefID = string.Empty;
+ private string pMarkupTextWriterType = string.Empty;
+ private string pFileName = string.Empty;
+
+ private System.Xml.XmlNode xmlNode;
+ private Identification[] Identification;
+ private Identification[] Capture;
+ private System.Collections.Specialized.NameValueCollection Capabilities;
+ private System.Collections.Specialized.NameValueCollection Adapter;
+ private System.Collections.Generic.List<string> ChildrenKeys;
+ private System.Collections.Generic.List<string> DefaultChildrenKeys;
+ private System.Collections.Generic.SortedList<string, nBrowser.Node> Children;
+ private System.Collections.Generic.SortedList<string, nBrowser.Node> DefaultChildren;
+ private System.Collections.Specialized.NameValueCollection sampleHeaders;
+
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="xmlNode"></param>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1059")]
+ public Node(System.Xml.XmlNode xmlNode)
+ {
+ this.xmlNode = xmlNode;
+ this.ResetChildern();
+ this.Reset();
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ internal Node()
+ {
+ this.ResetChildern();
+ Identification = new System.Web.Configuration.nBrowser.Identification[1];
+ Identification[0] = new System.Web.Configuration.nBrowser.Identification(true, "header", "User-Agent", ".");
+ this.Id = "[Base Node]";
+ this.NameType = NodeType.Browser;
+
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ private void ProcessIdentification(System.Xml.XmlNode node)
+ {
+ //I know not all of these will be used but enough will
+ Identification = new System.Web.Configuration.nBrowser.Identification[node.ChildNodes.Count];
+
+ int i = -1;
+ for (int a = 0;a <= node.ChildNodes.Count - 1;a++)
+ {
+ switch (node.ChildNodes[a].NodeType)
+ {
+ case System.Xml.XmlNodeType.Text:
+ continue;
+ case System.Xml.XmlNodeType.Comment:
+ continue;
+ }
+
+ string patterngroup = string.Empty;
+ string patternname = string.Empty;
+
+ if (string.Compare(node.ChildNodes[a].Name, "userAgent", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ patterngroup = "header";
+ patternname = "User-Agent";
+ }
+ else if (string.Compare(node.ChildNodes[a].Name, "header", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ patterngroup = node.ChildNodes[a].Name;
+ patternname = node.ChildNodes[a].Attributes["name"].Value;
+ }
+ else if (string.Compare(node.ChildNodes[a].Name, "capability", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ patterngroup = node.ChildNodes[a].Name;
+ patternname = node.ChildNodes[a].Attributes["name"].Value;
+ }
+ else
+ {
+ throw new nBrowser.Exception("Invalid Node found in Identification");
+ }
+
+ if (node.ChildNodes[a].Attributes["match"] != null)
+ {
+ i++;
+ Identification[i] = new System.Web.Configuration.nBrowser.Identification(true, patterngroup, patternname, node.ChildNodes[a].Attributes["match"].Value);
+ }
+ else if (node.ChildNodes[a].Attributes["nonMatch"] != null)
+ {
+ i++;
+ Identification[i] = new System.Web.Configuration.nBrowser.Identification(false, patterngroup, patternname, node.ChildNodes[a].Attributes["nonMatch"].Value);
+ }
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ private void ProcessCapture(System.Xml.XmlNode node)
+ {
+ //I know not all of these will be used but enough will
+ Capture = new System.Web.Configuration.nBrowser.Identification[node.ChildNodes.Count];
+
+ int i = -1;
+ for (int a = 0;a <= node.ChildNodes.Count - 1;a++)
+ {
+ switch (node.ChildNodes[a].NodeType)
+ {
+ case System.Xml.XmlNodeType.Text:
+ continue;
+ case System.Xml.XmlNodeType.Comment:
+ continue;
+ }
+
+ string pattern = string.Empty;
+ string patterngroup = string.Empty;
+ string patternname = string.Empty;
+
+ if (node.ChildNodes[a].Name == "userAgent")
+ {
+ patterngroup = "header";
+ patternname = "User-Agent";
+ }
+ else
+ {
+ patterngroup = node.ChildNodes[a].Name;
+ patternname = node.ChildNodes[a].Attributes["name"].Value;
+ }
+ pattern = node.ChildNodes[a].Attributes["match"].Value;
+ i++;
+ Capture[i] = new System.Web.Configuration.nBrowser.Identification(true, patterngroup, patternname, pattern);
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ private void ProcessCapabilities(System.Xml.XmlNode node)
+ {
+ Capabilities = new System.Collections.Specialized.NameValueCollection(node.ChildNodes.Count);
+
+ for (int a = 0;a <= node.ChildNodes.Count - 1;a++)
+ {
+ if (node.ChildNodes[a].NodeType == System.Xml.XmlNodeType.Comment)
+ {
+ continue;
+ }
+ string name = string.Empty;
+ string value = string.Empty;
+ for (int b = 0;b <= node.ChildNodes[a].Attributes.Count - 1;b++)
+ {
+ switch (node.ChildNodes[a].Attributes[b].Name)
+ {
+ case "name":
+ name = node.ChildNodes[a].Attributes[b].Value;
+ break;
+ case "value":
+ value = node.ChildNodes[a].Attributes[b].Value;
+ break;
+ }
+ }
+ if (name.Length > 0)
+ {
+ Capabilities[name] = value;
+ }
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ private void ProcessControlAdapters(System.Xml.XmlNode node)
+ {
+ Adapter = new System.Collections.Specialized.NameValueCollection();
+ for (int b = 0;b <= node.Attributes.Count - 1;b++)
+ {
+ switch (node.Attributes[b].Name)
+ {
+ case "markupTextWriterType":
+ MarkupTextWriterType = node.Attributes[b].Value;
+ break;
+ }
+ }
+ for (int a = 0;a <= node.ChildNodes.Count - 1;a++)
+ {
+ if (node.ChildNodes[a].NodeType == System.Xml.XmlNodeType.Comment)
+ {
+ continue;
+ }
+ else if (node.ChildNodes[a].NodeType == System.Xml.XmlNodeType.Text)
+ {
+ continue;
+ }
+ System.Xml.XmlNode x = node.ChildNodes[a];
+ string controlType = string.Empty;
+ string adapterType = string.Empty;
+ for (int i = 0;i <= x.Attributes.Count - 1;i++)
+ {
+ if (string.Compare(x.Attributes[i].Name, "controlType", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ controlType = x.Attributes[i].Value;
+ }
+ else if (string.Compare(x.Attributes[i].Name, "adapterType", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ adapterType = x.Attributes[i].Value;
+ }
+ }
+ if (controlType.Length > 0 && adapterType.Length > 0)
+ {
+ Adapter[controlType] = adapterType;
+ }
+ }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="node"></param>
+ private void ProcessSampleHeaders(System.Xml.XmlNode node)
+ {
+ sampleHeaders = new System.Collections.Specialized.NameValueCollection(node.ChildNodes.Count);
+
+ for (int a = 0;a <= node.ChildNodes.Count - 1;a++)
+ {
+ if (node.ChildNodes[a].NodeType == System.Xml.XmlNodeType.Comment)
+ {
+ continue;
+ }
+ string name = string.Empty;
+ string value = string.Empty;
+ for (int b = 0;b <= node.ChildNodes[a].Attributes.Count - 1;b++)
+ {
+ switch (node.ChildNodes[a].Attributes[b].Name)
+ {
+ case "name":
+ name = node.ChildNodes[a].Attributes[b].Value;
+ break;
+ case "value":
+ value = node.ChildNodes[a].Attributes[b].Value;
+ break;
+ }
+ }
+ if (name.Length > 0)
+ {
+ sampleHeaders[name] = value;
+ }
+ }
+ }
+ internal void ResetChildern()
+ {
+ Children = new System.Collections.Generic.SortedList<string, nBrowser.Node>();
+ DefaultChildren = new System.Collections.Generic.SortedList<string, nBrowser.Node>();
+ ChildrenKeys = new System.Collections.Generic.List<string>();
+ DefaultChildrenKeys = new System.Collections.Generic.List<string>();
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public bool HasChildren
+ {
+ get
+ {
+ if (Children.Count > -1)
+ {
+ return true;
+ }
+ return false;
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public void Reset()
+ {
+ //Making sure we start off on a good footing.
+ Capture = null;
+ Capabilities = null;
+ Adapter = null;
+ if (string.Compare(this.xmlNode.Name, "browser", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ this.NameType = NodeType.Browser;
+ }
+ else if (string.Compare(this.xmlNode.Name, "defaultBrowser", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ this.NameType = NodeType.DefaultBrowser;
+ }
+ else if (string.Compare(this.xmlNode.Name, "gateway", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ this.NameType = NodeType.Gateway;
+ }
+
+
+ //-------------------------------------------------------------------------
+ //Looping though the Attributes is easier since and more efficient
+ //then doing finds for specific attribute names. This also handles the
+ //cases where there are no attributes really well. Also it doesn't care
+ //about the order in witch the attributes are found either
+ //-------------------------------------------------------------------------
+ for (int a = 0;a <= xmlNode.Attributes.Count - 1;a++)
+ {
+ //Reason I am not using a switch here because I do not have the ability
+ //to make sure the items are in the same upper/lower case as I am expecting
+ //so I default to ignore case and compare.
+ if (string.Compare(xmlNode.Attributes[a].Name, "id", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ Id = xmlNode.Attributes[a].Value.ToLower(System.Globalization.CultureInfo.CurrentCulture);
+ }
+ else if (string.Compare(xmlNode.Attributes[a].Name, "parentID", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ ParentId = xmlNode.Attributes[a].Value.ToLower(System.Globalization.CultureInfo.CurrentCulture);
+ }
+ else if (string.Compare(xmlNode.Attributes[a].Name, "refID", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ RefId = xmlNode.Attributes[a].Value.ToLower(System.Globalization.CultureInfo.CurrentCulture);
+ }
+ }
+ //I include bother upper and lower case so I do not run into trying to compare case and dealing
+ //with CultureInfo stuff, Less hoops, should be faster I hope.
+ const string values = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
+ for (int a = 0;a <= Id.Length - 1;a++)
+ {
+ if (values.IndexOf(Id.Substring(a, 1)) == -1)
+ {
+ throw new nBrowser.Exception("Invalid Charactors In ID name");
+ }
+ }
+ for (int a = 0;a <= ParentId.Length - 1;a++)
+ {
+ if (values.IndexOf(ParentId.Substring(a, 1)) == -1)
+ {
+ throw new nBrowser.Exception("Invalid Charactors In parentID name");
+ }
+ }
+ for (int a = 0;a <= RefId.Length - 1;a++)
+ {
+ if (values.IndexOf(RefId.Substring(a, 1)) == -1)
+ {
+ throw new nBrowser.Exception("Invalid Charactors In refID name");
+ }
+ }
+
+ for (int a = 0;a <= xmlNode.ChildNodes.Count - 1;a++)
+ {
+ //Reason I am not using a switch here because I do not have the ability
+ //to make sure the items are in the same upper/lower case as I am expecting
+ //so I default to ignore case and compare.
+ if (string.Compare(xmlNode.ChildNodes[a].Name, "identification", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ ProcessIdentification(xmlNode.ChildNodes[a]);
+ }
+ else if (string.Compare(xmlNode.ChildNodes[a].Name, "capture", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ ProcessCapture(xmlNode.ChildNodes[a]);
+ }
+ else if (string.Compare(xmlNode.ChildNodes[a].Name, "capabilities", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ ProcessCapabilities(xmlNode.ChildNodes[a]);
+ }
+ else if (string.Compare(xmlNode.ChildNodes[a].Name, "controlAdapters", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ ProcessControlAdapters(xmlNode.ChildNodes[a]);
+ }
+ else if (string.Compare(xmlNode.ChildNodes[a].Name, "sampleHeaders", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ ProcessSampleHeaders(xmlNode.ChildNodes[a]);
+ }
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="child"></param>
+ public void AddChild(Node child)
+ {
+ if (child == null)
+ {
+ return;
+ }
+ if (child.NameType == nBrowser.NodeType.Browser || child.NameType == nBrowser.NodeType.Gateway)
+ {
+ Children.Add(child.Id, child);
+ ChildrenKeys.Add(child.Id);
+ }
+ else if (child.NameType == NodeType.DefaultBrowser)
+ {
+ DefaultChildren.Add(child.Id, child);
+ DefaultChildrenKeys.Add(child.Id);
+ }
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="child"></param>
+ public void RemoveChild(Node child)
+ {
+ if (child == null)
+ {
+ return;
+ }
+ if (child.NameType == nBrowser.NodeType.Browser || child.NameType == nBrowser.NodeType.Gateway)
+ {
+ Children.Remove(child.Id);
+ ChildrenKeys.Remove(child.Id);
+ }
+ else if (child.NameType == NodeType.DefaultBrowser)
+ {
+ DefaultChildren.Remove(child.Id);
+ DefaultChildrenKeys.Remove(child.Id);
+ }
+ }
+
+
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="header"></param>
+ /// <param name="result"></param>
+ /// <param name="List"></param>
+ /// <returns></returns>
+ internal nBrowser.Result Process(System.Collections.Specialized.NameValueCollection header, nBrowser.Result result, System.Collections.Generic.List<System.Web.Configuration.nBrowser.Identification> List)
+ {
+ //----------------------------------------------------------------------
+ //This is just coded over from MS version since if you pass in an empty
+ //string for the key it returns the UserAgent header as a response.
+ //----------------------------------------------------------------------
+ result.AddCapabilities("", header["User-Agent"]);
+
+ //this step shouldn't really be necessary, if it was checked
+ //prior to calling this method, but we assume it hasn't and
+ //recheck anyways.
+ if (BrowserIdentification(header, result) == false)
+ {
+ return result;
+ }
+ #region Browser Identification Successfull
+ //----------------------------------------------------------------------
+ //By reaching this point, it either means there were no Identification
+ //items to be processed or that all the Identification items have been
+ //passed. So just for debuging I want to output this Groups unique ID.
+ //----------------------------------------------------------------------
+ result.AddTrack("[" + this.NameType + "]\t" + this.Id);
+
+ //----------------------------------------------------------------------
+ //Just adding all the Adapters to the current list.
+ //----------------------------------------------------------------------
+ if (Adapter != null)
+ {
+ for (int i = 0;i <= Adapter.Count - 1;i++)
+ {
+ result.AddAdapter(Adapter.GetKey(i), Adapter[i]);
+ }
+ }
+
+ //----------------------------------------------------------------------
+ //Set the MarkupTextWriter in the result if set in this node.
+ //----------------------------------------------------------------------
+ if (MarkupTextWriterType != null && MarkupTextWriterType.Length > 0)
+ {
+ // Look for the type using a case-sensitive search
+ result.MarkupTextWriter = Type.GetType(MarkupTextWriterType);
+ // If we don't find it, try again using a case-insensitive search and throw
+ // and exception if we can't find it.
+ if (result.MarkupTextWriter == null)
+ result.MarkupTextWriter = Type.GetType(MarkupTextWriterType, true, true);
+ }
+
+ //----------------------------------------------------------------------
+ //Adds all the Identifiction matches to the List of Identification
+ //list.
+ //----------------------------------------------------------------------
+ if (this.NameType != NodeType.DefaultBrowser)
+ {
+ for (int i = 0;i <= Identification.Length - 1;i++)
+ {
+ if (Identification[i].HasCaptureGroups == true)
+ {
+ List.Add(Identification[i]);
+ }
+ }
+ }
+ #endregion
+ #region Capture
+ if (Capture != null)
+ {
+ //----------------------------------------------------------------------
+ //Adds all the sucessfull Capture matches to the List of generic
+ //Identification list.
+ //----------------------------------------------------------------------
+ for (int i = 0;i <= Capture.Length - 1;i++)
+ {
+ //shouldn't happen often, the null should
+ //signal the end of the list, I keep procssing
+ //the rest just in case
+ if (Capture[i] == null)
+ {
+ continue;
+ }
+ //take no chances get back to base state.
+ Capture[i].Reset();
+ if (Capture[i].Group == "header")
+ {
+ Capture[i].Match(header[Capture[i].Name]);
+ }
+ else if (Capture[i].Group == "capability")
+ {
+ Capture[i].Match(result[Capture[i].Name]);
+ }
+ if (Capture[i].Success == true && Capture[i].HasCaptureGroups == true)
+ {
+ List.Add(Capture[i]);
+ }
+ }
+ }
+ #endregion
+ #region Capabilities
+ if (Capabilities != null)
+ {
+ //----------------------------------------------------------------------
+ //This section is what the whole exercise is about. Determining
+ //the Browser Capabilities. We know already that the current
+ //browser matches the criteria, now its a mater of updating
+ //the results with the new Capabilties listed.
+ //----------------------------------------------------------------------
+ for (int i = 0;i <= Capabilities.Count - 1;i++)
+ {
+ //----------------------------------------------------------------------
+ //Most items do not have any regular expression in them
+ //so we can add them directly to the results.
+ //----------------------------------------------------------------------
+ if (Capabilities[i].IndexOf("$") == -1 && Capabilities[i].IndexOf("%") == -1)
+ {
+ result.AddCapabilities(Capabilities.Keys[i], Capabilities[i]);
+ }
+ else
+ {
+ //----------------------------------------------------------------------
+ //We need to further process these Capabilities to
+ //insert the proper information.
+ //----------------------------------------------------------------------
+ string v = string.Empty;
+
+ //----------------------------------------------------------------------
+ //Loop though the list of Identifiction/Capture Matches
+ //in reverse order. Meaning the newest Items in the list
+ //get checked first, then working to the oldest. Often times
+ //Minor /Major revisition numbers will be listed multple times
+ //and only the newest one (most recent matches) are the ones
+ //we want to insert.
+ //----------------------------------------------------------------------
+ if (Capabilities[i].IndexOf("$") >= -1)
+ {
+ for (int a = List.Count - 1;a >= 0;a--)
+ {
+ v = ((System.Web.Configuration.nBrowser.Identification)List[a]).Result(Capabilities[i]);
+ //----------------------------------------------------------------------
+ //exit the loop once we are able to extract a result.
+ //----------------------------------------------------------------------
+ if (v.Length > 0 && v.IndexOf("$") == -1)
+ {
+ break;
+ }
+ }
+ }
+ //----------------------------------------------------------------------
+ //Checks to make sure we extract the result we where looking for.
+ //----------------------------------------------------------------------
+ if (v.IndexOf("$") > -1 || v.IndexOf("%") > -1)
+ {
+ //----------------------------------------------------------------------
+ //Microsoft has a nasty habbit of using capability items in regular expressions
+ //so I have to figure a nice way to working around it
+ // <capability name="msdomversion" value="${majorversion}${minorversion}" />
+ //----------------------------------------------------------------------
+
+ //double checks the values against the current Capabilities. to
+ //find any last minute matches. that are not defined by regluar
+ //expressions
+ v = result.Replace(v);
+ }
+
+ if (v.Length > 0 && v.IndexOf("$") == -1 && v.IndexOf("%") == -1)
+ {
+ result.AddCapabilities(Capabilities.Keys[i], v);
+ }
+ else
+ {
+ //----------------------------------------------------------------------
+ //This happens pretty often, especially when mobile phone browsers
+ //are in use, and different proxie servers send back varying amount
+ //of details, when Items are missing, this will often pop.
+ //----------------------------------------------------------------------
+ //Console.WriteLine(this.Id +"\t"+v);
+ }
+ }
+ }
+ }
+ #endregion
+ if (Adapter != null)
+ {
+ for (int i = 0;i <= Adapter.Count - 1;i++)
+ {
+ result.AddAdapter(Adapter.GetKey(i), Adapter[i]);
+ }
+ }
+ //----------------------------------------------------------------------
+ //Run the Default Children after the Parent Node is finished with
+ //what it is doing
+ //----------------------------------------------------------------------
+ for (int i = 0;i <= DefaultChildren.Count - 1;i++)
+ {
+ string key = DefaultChildrenKeys[i];
+ Node node = DefaultChildren[key];
+ if (node.NameType == NodeType.DefaultBrowser)
+ {
+ node.Process(header, result, List);
+ }
+ }
+ //----------------------------------------------------------------------
+ //processing all the children Browsers of this Parent if there are any.
+ //----------------------------------------------------------------------
+ //In nBrowser files, the Gateways should of been sorted so they are all
+ //at the top so that they can be ran first.
+ //----------------------------------------------------------------------
+ //According to the msdn2 documentation Gateways are suppost to be
+ //all processed first. before the browser objects.
+ for (int i = 0;i <= Children.Count - 1;i++)
+ {
+ string key = ChildrenKeys[i];
+ Node node = Children[key];
+ if (node.NameType == NodeType.Gateway)
+ {
+ node.Process(header, result, List);
+ }
+ }
+ for (int i = 0;i <= Children.Count - 1;i++)
+ {
+ string key = ChildrenKeys[i];
+ Node node = Children[key];
+ if (node.NameType == NodeType.Browser)
+ {
+ if (node.BrowserIdentification(header, result) == true)
+ {
+ node.Process(header, result, List);
+ break;
+ }
+ }
+ }
+
+ #region Remove Identification & Caputers from lists
+ //----------------------------------------------------------------------
+ //
+ //---------------------------------------------------------------------
+ if (Identification != null)
+ {
+ for (int i = 0;i <= Identification.Length - 1;i++)
+ {
+ //shouldn't happen often, the null should
+ //signal the end of the list, I keep procssing
+ //the rest just in case
+ if (Identification[i] == null)
+ {
+ continue;
+ }
+ if (Identification[i].HasCaptureGroups == true)
+ {
+ List.Remove(Identification[i]);
+ }
+ }
+ }
+ //----------------------------------------------------------------------
+ //
+ //---------------------------------------------------------------------
+ if (Capture != null)
+ {
+ for (int i = 0;i <= Capture.Length - 1;i++)
+ {
+ //shouldn't happen often, the null should
+ //signal the end of the list, I keep procssing
+ //the rest just in case
+ if (Capture[i] == null)
+ {
+ continue;
+ }
+ if (Capture[i].Success == true && Capture[i].HasCaptureGroups == true)
+ {
+ List.Remove(Capture[i]);
+ }
+ }
+ }
+ #endregion
+
+ return result;
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="header"></param>
+ /// <param name="result"></param>
+ /// <returns></returns>
+ public bool BrowserIdentification(System.Collections.Specialized.NameValueCollection header, System.Web.Configuration.CapabilitiesResult result)
+ {
+ if (Id.Length > 0 && RefId.Length > 0)
+ {
+ throw new nBrowser.Exception("Id and refID Attributes givin when there should only be one set not both");
+ }
+ if (RefId.Length > 0)
+ {
+ return true;
+ }
+ if (this.NameType == NodeType.DefaultBrowser)
+ {
+ return true;
+ }
+ if (Identification == null || Identification.Length == 0)
+ {
+ throw new nBrowser.Exception("Missing Identification Section where one is required");
+ }
+ if (header == null)
+ {
+ throw new nBrowser.Exception("Null Value where NameValueCollection expected ");
+ }
+ if (result == null)
+ {
+ throw new nBrowser.Exception("Null Value where Result expected ");
+ }
+
+#if trace
+ System.Diagnostics.Trace.WriteLine(string.Format("{0}[{1}]", ("[" + this.Id + "]").PadRight(45), this.ParentId));
+#endif
+
+ for (int i = 0;i <= Identification.Length - 1;i++)
+ {
+
+ //shouldn't happen often, the null should
+ //signal the end of the list, I keep procssing
+ //the rest just in case
+ if (Identification[i] == null)
+ {
+ continue;
+ }
+ //take no chances get back to base state.
+ Identification[i].Reset();
+ string v = string.Empty;
+ if (string.Compare(Identification[i].Group, "header", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ v = header[Identification[i].Name];
+ }
+ else if (string.Compare(Identification[i].Group, "capability", true, System.Globalization.CultureInfo.CurrentCulture) == 0)
+ {
+ v = result[Identification[i].Name];
+ }
+ //Not all headers will be sent by all browsers.
+ //so often a header search will return Null.
+ if (v == null)
+ {
+ v = string.Empty;
+ }
+ Identification[i].Match(v);
+ //----------------------------------------------------------------------
+ //we exit this method return the orginal Result back to the calling method.
+ //----------------------------------------------------------------------
+ if (Identification[i].Success == false)
+ {
+#if trace
+ System.Diagnostics.Trace.WriteLine(string.Format("{0}{1}", "Failed:".PadRight(45), Identification[i].Pattern));
+#endif
+ //just making sure to cleanup before we leave.
+ Identification[i].Reset();
+#if trace
+ System.Diagnostics.Trace.WriteLine("");
+#endif
+ return false;
+ }
+ else
+ {
+#if trace
+ System.Diagnostics.Trace.WriteLine(string.Format("{0}{1}", "Passed:".PadRight(45), Identification[i].Pattern));
+#endif
+ }
+ }
+#if trace
+ System.Diagnostics.Trace.WriteLine("");
+#endif
+ return true;
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public System.Collections.Specialized.NameValueCollection SampleHeader
+ {
+ get
+ {
+ return sampleHeaders;
+ }
+ }
+ /// <summary>
+ /// Used to Display a Tree Like View of how the Nodes are organized.
+ /// </summary>
+ /// <param name="writer"></param>
+ /// <param name="Position"></param>
+ public void Tree(System.Xml.XmlTextWriter xmlwriter, int position)
+ {
+ if (position == 0)
+ {
+ xmlwriter.WriteStartDocument();
+ xmlwriter.WriteStartElement(this.NameType.ToString());
+ xmlwriter.WriteRaw(System.Environment.NewLine);
+ }
+
+ string f = this.FileName;
+ f = f.Substring(f.LastIndexOfAny("\\".ToCharArray()) + 1);
+ xmlwriter.WriteStartElement(this.NameType.ToString());
+ xmlwriter.WriteAttributeString("FileName", f);
+ xmlwriter.WriteAttributeString("ID", this.Id);
+ xmlwriter.WriteRaw(System.Environment.NewLine);
+
+ if (position != int.MaxValue)
+ {
+ position++;
+ }
+ for (int i = 0;i <= DefaultChildren.Count - 1;i++)
+ {
+ string key = (string)DefaultChildrenKeys[i];
+ Node node = DefaultChildren[key];
+ if (node.NameType == nBrowser.NodeType.DefaultBrowser)
+ {
+ node.Tree(xmlwriter, position);
+ }
+ }
+
+ for (int i = 0;i <= Children.Count - 1;i++)
+ {
+ string key = (string)ChildrenKeys[i];
+ Node node = Children[key];
+ if (node.NameType == nBrowser.NodeType.Gateway)
+ {
+ node.Tree(xmlwriter, position);
+ }
+ }
+
+ for (int i = 0;i <= Children.Count - 1;i++)
+ {
+ string key = (string)ChildrenKeys[i];
+ Node node = Children[key];
+ if (node.NameType == nBrowser.NodeType.Browser)
+ {
+ node.Tree(xmlwriter, position);
+ }
+ }
+ if (position != int.MinValue)
+ {
+ position--;
+ }
+ xmlwriter.WriteEndElement();
+ xmlwriter.WriteRaw(System.Environment.NewLine);
+ if (position == 0)
+ {
+ xmlwriter.WriteEndDocument();
+ xmlwriter.Flush();
+ }
+ }
+ public System.Collections.ObjectModel.Collection<string> HeaderNames(System.Collections.ObjectModel.Collection<string> list)
+ {
+ if (Identification != null)
+ {
+ for (int i = 0;i <= Identification.Length - 1;i++)
+ {
+ if (Identification[i] == null)
+ {
+ continue;
+ }
+ if (Identification[i].Group == "header")
+ {
+ if (list.Contains(Identification[i].Name) == false)
+ {
+ list.Add(Identification[i].Name);
+ }
+ }
+ }
+ }
+ if (Capture != null)
+ {
+ for (int i = 0;i <= Capture.Length - 1;i++)
+ {
+ if (Capture[i] == null)
+ {
+ continue;
+ }
+ if (Capture[i].Group == "header")
+ {
+ if (list.Contains(Capture[i].Name) == false)
+ {
+ list.Add(Capture[i].Name);
+ }
+ }
+ }
+ }
+ for (int i = 0;i <= DefaultChildren.Count - 1;i++)
+ {
+ string key = (string)DefaultChildrenKeys[i];
+ Node node = DefaultChildren[key];
+ if (node.NameType == nBrowser.NodeType.DefaultBrowser)
+ {
+ list = node.HeaderNames(list);
+ }
+ }
+
+ for (int i = 0;i <= Children.Count - 1;i++)
+ {
+ string key = (string)ChildrenKeys[i];
+ Node node = Children[key];
+ if (node.NameType == nBrowser.NodeType.Gateway)
+ {
+ list = node.HeaderNames(list);
+ }
+ }
+
+ for (int i = 0;i <= Children.Count - 1;i++)
+ {
+ string key = (string)ChildrenKeys[i];
+ Node node = Children[key];
+ if (node.NameType == nBrowser.NodeType.Browser)
+ {
+ list = node.HeaderNames(list);
+ }
+ }
+ return list;
+ }
+
+ /// <summary>
+ /// Merge capabilities, captures, markupTextWriters, and adapters from another Node into this Node.
+ /// </summary>
+ /// <param name="n">node to merge with this node</param>
+ public void MergeFrom(Node n)
+ {
+ foreach (string capName in n.Capabilities)
+ Capabilities[capName] = n.Capabilities[capName];
+
+ int newLength = 0;
+ if (Capture != null)
+ newLength += Capture.Length;
+ if (n.Capture != null)
+ newLength += n.Capture.Length;
+ Identification[] newCapture = new Identification[newLength];
+ if (Capture != null)
+ Array.Copy(Capture, 0, newCapture, 0, Capture.Length);
+ if (n.Capture != null)
+ Array.Copy(n.Capture, 0, newCapture, Capture.Length, n.Capture.Length);
+ Capture = newCapture;
+
+ if (n.MarkupTextWriterType != null && n.MarkupTextWriterType.Length > 0)
+ MarkupTextWriterType = n.MarkupTextWriterType;
+
+ foreach (string controlType in n.Adapter)
+ Adapter[controlType] = n.Adapter[controlType];
+ }
+ }
+}
+#endif
--- /dev/null
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+namespace System.Web.Configuration.nBrowser
+{
+ internal enum NodeType
+ {
+ None = 0,
+ Browser = 1,
+ Gateway = 2,
+ DefaultBrowser = 3
+ }
+}
+#endif
--- /dev/null
+#if NET_2_0
+/*
+Used to determine Browser Capabilities by the Browsers UserAgent String and related
+Browser supplied Headers.
+Copyright (C) 2002-Present Owen Brady (Ocean at xvision.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+namespace System.Web.Configuration.nBrowser
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+
+ internal class Result : System.Web.Configuration.CapabilitiesResult
+ {
+ private System.Collections.Generic.Dictionary<Type, Type> AdapterTypeMap;
+ private System.Collections.Specialized.StringCollection Track;
+ internal Type MarkupTextWriter;
+
+ internal Result(System.Collections.Generic.Dictionary<string, string> items)
+ : base(items)
+ {
+ AdapterTypeMap = new System.Collections.Generic.Dictionary<Type, Type>();
+ Track = new System.Collections.Specialized.StringCollection();
+ MarkupTextWriter = typeof (System.Web.UI.HtmlTextWriter);
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="track"></param>
+ internal void AddTrack(string track)
+ {
+ Track.Add(track);
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="controlTypeName"></param>
+ /// <param name="adapterTypeName"></param>
+ internal void AddAdapter(string controlTypeName, string adapterTypeName)
+ {
+ Type controlType = System.Type.GetType(controlTypeName); // case-sensitive
+ if (controlType == null)
+ controlType = System.Type.GetType(controlTypeName, true, true); // case-insensitive, throw if not found
+ Type adapterType = System.Type.GetType(adapterTypeName); // case-sensitive
+ if (adapterType == null)
+ adapterType = System.Type.GetType(adapterTypeName, true, true); // case-insensitive, throw if not found
+
+ AdapterTypeMap[controlType] = adapterType;
+ }
+ /// <summary>
+ ///
+ /// </summary>
+ public System.Collections.Specialized.StringCollection Tracks
+ {
+ get
+ {
+ return Track;
+ }
+ }
+
+ internal override Type GetTagWriter ()
+ {
+ return MarkupTextWriter;
+ }
+
+ internal override System.Collections.IDictionary GetAdapters ()
+ {
+ return AdapterTypeMap;
+ }
+ }
+}
+#endif
+2008-01-15 Dean Brettle <dean@brettle.com>
+
+ * ControlAdapter.cs: made control field internal so
+ derived internal classes can access it without using base.Control
+ which can involved several typecasts.
+
+2008-01-12 Dean Brettle <dean@brettle.com>
+
+ * PageAdapter.cs: implemented all members.
+
+2008-01-07 Dean Brettle <dean@brettle.com>
+
+ * ControlAdapter.cs: implemented all members.
+
2005-08-24 Chris Toshok <toshok@ximian.com>
- * PageAdapter.cs, ControlAdapter: add MonoTODO's.
+ * PageAdapter.cs, ControlAdapter.cs: add MonoTODO's.
2005-08-18 Dick Porter <dick@ximian.com>
{
public abstract class ControlAdapter
{
+ internal ControlAdapter (Control c)
+ {
+ control = c;
+ }
+
protected ControlAdapter ()
{
}
- [MonoTODO("Not implemented")]
protected HttpBrowserCapabilities Browser
{
get {
- throw new NotImplementedException ();
+ return Page.Request.Browser;
}
}
- [MonoTODO("Not implemented")]
+ internal Control control;
+
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
- protected Control Control
+ protected internal Control Control
{
- get {
- throw new NotImplementedException ();
+ protected get {
+ return control;
+ }
+ set {
+ control = value;
}
}
- [MonoTODO("Not implemented")]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[Browsable (false)]
protected Page Page
{
get {
- throw new NotImplementedException ();
+ return Control.Page;
}
}
- [MonoTODO("Not implemented")]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
[Browsable (false)]
protected PageAdapter PageAdapter
{
get {
- throw new NotImplementedException ();
+ return Control.Page.PageAdapter;
}
}
- [MonoTODO("Not implemented")]
protected internal virtual void BeginRender (HtmlTextWriter w)
{
- throw new NotImplementedException ();
+ w.BeginRender();
}
- [MonoTODO("Not implemented")]
protected internal virtual void CreateChildControls ()
{
- throw new NotImplementedException ();
}
- [MonoTODO("Not implemented")]
protected internal virtual void EndRender (HtmlTextWriter w)
{
- throw new NotImplementedException ();
+ w.EndRender ();
}
- [MonoTODO("Not implemented")]
protected internal virtual void LoadAdapterControlState (object state)
{
- throw new NotImplementedException ();
}
- [MonoTODO("Not implemented")]
protected internal virtual void LoadAdapterViewState (object state)
{
- throw new NotImplementedException ();
}
- [MonoTODO("Not implemented")]
protected internal virtual void OnInit (EventArgs e)
{
- throw new NotImplementedException ();
+ Control.OnInit(e);
}
- [MonoTODO("Not implemented")]
protected internal virtual void OnLoad (EventArgs e)
{
- throw new NotImplementedException ();
+ Control.OnLoad(e);
}
- [MonoTODO("Not implemented")]
protected internal virtual void OnPreRender (EventArgs e)
{
- throw new NotImplementedException ();
+ Control.OnPreRender(e);
}
- [MonoTODO("Not implemented")]
protected internal virtual void OnUnload (EventArgs e)
{
- throw new NotImplementedException ();
+ Control.OnUnload(e);
}
- [MonoTODO("Not implemented")]
protected internal virtual void Render (HtmlTextWriter w)
{
- throw new NotImplementedException ();
+ Control.Render (w);
}
- [MonoTODO("Not implemented")]
protected internal virtual void RenderChildren (HtmlTextWriter w)
{
- throw new NotImplementedException ();
+ Control.RenderChildren (w);
}
- [MonoTODO("Not implemented")]
protected internal virtual object SaveAdapterControlState ()
{
- throw new NotImplementedException ();
+ return null;
}
- [MonoTODO("Not implemented")]
protected internal virtual object SaveAdapterViewState ()
{
- throw new NotImplementedException ();
+ return null;
}
}
}
{
}
- [MonoTODO("Not implemented")]
- public virtual StringCollection CacheVaryByHeaders
+ internal PageAdapter (Page p) : base (p)
{
- get {
- throw new NotImplementedException ();
- }
}
- [MonoTODO("Not implemented")]
- public virtual StringCollection CacheVaryByParams
- {
- get {
- throw new NotImplementedException ();
- }
+ public virtual StringCollection CacheVaryByHeaders {
+ get { return null; }
+ }
+
+ public virtual StringCollection CacheVaryByParams {
+ get { return null; }
}
- [MonoTODO("Not implemented")]
protected string ClientState
{
get {
- throw new NotImplementedException ();
+ return Page.GetSavedViewState ();
}
}
- [MonoTODO("Not implemented")]
public virtual NameValueCollection DeterminePostBackMode ()
{
- throw new NotImplementedException ();
+ return Page.DeterminePostBackMode ();
}
- [MonoTODO("Not implemented")]
public virtual ICollection GetRadioButtonsByGroup (string groupName)
{
- throw new NotImplementedException ();
+ if (radio_button_group == null)
+ return new ArrayList();
+ ArrayList radioButtons = (ArrayList) radio_button_group [groupName];
+ if (radioButtons == null)
+ return new ArrayList();
+ return radioButtons;
}
- [MonoTODO("Not implemented")]
public virtual PageStatePersister GetStatePersister ()
{
- throw new NotImplementedException ();
+ return new HiddenFieldPageStatePersister ((Page)Control);
}
- [MonoTODO("Not implemented")]
public virtual void RegisterRadioButton (RadioButton radioButton)
{
- throw new NotImplementedException ();
+ if (radio_button_group == null)
+ radio_button_group = new ListDictionary();
+ ArrayList radioButtons = (ArrayList) radio_button_group [radioButton.GroupName];
+ if (radioButtons == null)
+ radio_button_group [radioButton.GroupName] = radioButtons = new ArrayList();
+ if (!radioButtons.Contains(radioButton))
+ radioButtons.Add(radioButton);
}
- [MonoTODO("Not implemented")]
public virtual void RenderBeginHyperlink (HtmlTextWriter w,
string targetUrl,
bool encodeUrl,
string softKeyLabel)
{
- throw new NotImplementedException ();
+ InternalRenderBeginHyperlink (w, targetUrl, encodeUrl, softKeyLabel, null);
}
- [MonoTODO("Not implemented")]
public virtual void RenderBeginHyperlink (HtmlTextWriter w,
string targetUrl,
bool encodeUrl,
string softKeyLabel,
string accessKey)
{
- throw new NotImplementedException ();
+ if (accessKey != null && accessKey.Length > 1)
+ throw new ArgumentOutOfRangeException("accessKey");
+ InternalRenderBeginHyperlink (w, targetUrl, encodeUrl, softKeyLabel, accessKey);
+ }
+
+ void InternalRenderBeginHyperlink (HtmlTextWriter w,
+ string targetUrl,
+ bool encodeUrl,
+ string softKeyLabel,
+ string accessKey)
+ {
+ w.AddAttribute (HtmlTextWriterAttribute.Href, targetUrl, encodeUrl);
+ if (accessKey != null)
+ w.AddAttribute (HtmlTextWriterAttribute.Accesskey, accessKey);
+ w.RenderBeginTag (HtmlTextWriterTag.A);
}
- [MonoTODO("Not implemented")]
+
public virtual void RenderEndHyperlink (HtmlTextWriter w)
{
- throw new NotImplementedException ();
+ w.RenderEndTag();
}
- [MonoTODO("Not implemented")]
public virtual void RenderPostBackEvent (HtmlTextWriter w,
string target,
string argument,
string softKeyLabel,
string text)
{
- throw new NotImplementedException ();
+ RenderPostBackEvent (w, target, argument, softKeyLabel, text, Page.Request.FilePath, null, true);
}
- [MonoTODO("Not implemented")]
public virtual void RenderPostBackEvent (HtmlTextWriter w,
string target,
string argument,
string postUrl,
string accessKey)
{
- throw new NotImplementedException ();
+ RenderPostBackEvent (w, target, argument, softKeyLabel, text, postUrl, accessKey, true);
}
- [MonoTODO("Not implemented")]
protected void RenderPostBackEvent (HtmlTextWriter w,
string target,
string argument,
string accessKey,
bool encode)
{
- throw new NotImplementedException ();
+ string url = String.Format ("{0}?__VIEWSTATE={1}&__EVENTTARGET={2}&__EVENTARGUMENT={3}&__PREVIOUSPAGE={4}",
+ postUrl, HttpUtility.UrlEncode (Page.GetSavedViewState ()), target, argument, Page.Request.FilePath);
+ RenderBeginHyperlink (w, url, encode, softKeyLabel, accessKey);
+ w.Write(text);
+ RenderEndHyperlink(w);
}
- [MonoTODO("Not implemented")]
public virtual string TransformText (string text)
{
- throw new NotImplementedException ();
+ return text;
}
- [MonoTODO("Not implemented")]
protected internal virtual string GetPostBackFormReference (string formID)
{
- throw new NotImplementedException ();
+ return String.Format("document.forms['{0}']", formID);
}
+
+ private ListDictionary radio_button_group;
}
}
#endif
+2008-01-15 Dean Brettle <dean@brettle.com>
+
+ * WebControlAdapter.cs, HierarchicalDataBoundControlAdapter.cs,
+ DataBoundControlAdapter.cs: changed to use ControlAdapter.control
+ instead of using base.Control or using a new control field.
+
+ * MenuAdapter.cs: added internal constructor that takes a Menu
+ parameter. The constructor is used when writing unit tests.
+
+ * MenuAdapter.cs (OnInit, OnPreRender, RenderBeginTag,
+ RenderContents, RenderEndTag): delegate to base instead of
+ Control.
+
+ * MenuAdapter.cs (LoadAdapterControlState, SaveAdapterControlState,
+ RaisePostBackEvent, RenderItem): implemented.
+
+2008-01-13 Dean Brettle <dean@brettle.com>
+
+ * WebControlAdapter.cs (RenderContents): changed to call
+ control.RenderContents() instead of control.Render().
+
+ * WebControlAdapter.cs, HierarchicalDataBoundControlAdapter.cs,
+ DataBoundControlAdapter.cs, HideDisabledControlAdapter.cs: added
+ internal constructor that takes a parameter of the corresponding
+ Control type. The construct is used when writing unit tests.
+
2005-08-24 Chris Toshok <toshok@ximian.com>
* MenuAdapter.cs (OnInit): Call "Page.RegisterRequiresControlState
public DataBoundControlAdapter ()
{
}
+
+ internal DataBoundControlAdapter (DataBoundControl c) : base (c)
+ {
+ }
protected internal virtual void PerformDataBinding (IEnumerable data)
{
protected new DataBoundControl Control
{
get {
- return (DataBoundControl)base.Control;
+ return (DataBoundControl)control;
}
}
}
{
}
+ internal HideDisabledControlAdapter (WebControl c) : base (c)
+ {
+ }
+
protected internal override void Render(HtmlTextWriter writer)
{
if (!Control.IsEnabled)
{
}
+ internal HierarchicalDataBoundControlAdapter (HierarchicalDataBoundControl c) : base (c)
+ {
+ }
+
protected internal virtual void PerformDataBinding ()
{
Control.PerformDataBinding ();
protected new HierarchicalDataBoundControl Control
{
get {
- return (HierarchicalDataBoundControl)base.Control;
+ return (HierarchicalDataBoundControl)control;
}
}
}
public MenuAdapter ()
{
}
-
- protected internal override void OnInit(EventArgs e)
+
+ internal MenuAdapter (Menu c) : base (c)
{
- /* registers the associated control as one that requires control state */
- Page.RegisterRequiresControlState (Control);
+ }
- /* and calls control.OnInit */
- Control.OnInit (e);
+ protected internal override void OnInit (EventArgs e)
+ {
+ base.OnInit (e);
}
protected internal override void OnPreRender(EventArgs e)
{
- Control.OnPreRender (e);
+ base.OnPreRender (e);
}
- [MonoTODO]
protected virtual void RaisePostBackEvent (string eventArgument)
{
- throw new NotImplementedException ();
+ Control.RaisePostBackEvent (eventArgument);
}
protected override void RenderBeginTag (HtmlTextWriter writer)
{
- Control.RenderBeginTag (writer);
+ base.RenderBeginTag (writer);
}
protected override void RenderContents (HtmlTextWriter writer)
{
- // FIXME: we need to iterate over the
- // MenuItems here, calling
- // MenuAdapter.RenderItem for each one.
-
- Control.RenderContents (writer);
+ base.RenderContents (writer);
}
protected override void RenderEndTag (HtmlTextWriter writer)
{
- Control.RenderEndTag (writer);
+ base.RenderEndTag (writer);
}
- [MonoTODO ("Not implemented")]
protected internal virtual void RenderItem (HtmlTextWriter writer,
MenuItem item,
int position)
{
- throw new NotImplementedException ();
+ Control.RenderItem (writer, item, position);
}
- [MonoTODO ("Not implemented")]
protected internal override void LoadAdapterControlState (object state)
{
- throw new NotImplementedException ();
}
- [MonoTODO ("Not implemented")]
protected internal override object SaveAdapterControlState ()
{
- throw new NotImplementedException ();
+ return null;
}
- [MonoTODO ("Not implemented")]
- void System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(string eventArgument)
+ void System.Web.UI.IPostBackEventHandler.RaisePostBackEvent (string eventArgument)
{
- throw new NotImplementedException ();
+ RaisePostBackEvent (eventArgument);
}
protected new Menu Control
{
get {
- return (Menu)base.Control;
+ return (Menu)control;
}
}
}
{
public class WebControlAdapter : ControlAdapter
{
- public WebControlAdapter()
+ public WebControlAdapter ()
+ {
+ }
+
+ internal WebControlAdapter (WebControl wc) : base (wc)
{
}
protected virtual void RenderBeginTag (HtmlTextWriter writer)
{
- control.RenderBeginTag (writer);
+ Control.RenderBeginTag (writer);
}
protected virtual void RenderContents(HtmlTextWriter writer)
{
- control.Render (writer);
+ Control.RenderContents (writer);
}
protected virtual void RenderEndTag(HtmlTextWriter writer)
{
- control.RenderEndTag (writer);
+ Control.RenderEndTag (writer);
}
protected new WebControl Control
{
get {
- return control;
+ return (WebControl)control;
}
}
protected bool IsEnabled
{
get {
- return control.IsEnabled;
+ return Control.IsEnabled;
}
}
-
- WebControl control;
}
}
+2008-03-09 Dean Brettle <dean@brettle.com>
+
+ * DetailsView.cs, ListControl.cs, DataBoundControl.cs,
+ FormView.cs, HierarchicalDataBoundControl.cs, WebControl.cs:
+ added support for using ControlAdapters when present.
+
+ * WebControl.cs: fixed implementation of IsEnabled to match
+ documentation.
+
+ * Menu.cs (RenderMenuBody): call Adapter.RenderItem() instead of
+ RenderMenuItem() if an adapter is present. MenuAdapter.RenderItem()
+ calls back to new Menu.RenderItem() internal method which calls
+ RenderMenuItem() with the appropriate parameters.
+
2008-02-25 Igor Zelmanovich <igorz@mainsoft.com>
* GridView.cs:
using System.Web.Util;
using System.ComponentModel;
using System.Security.Permissions;
+using System.Web.UI.WebControls.Adapters;
namespace System.Web.UI.WebControls {
}
// The PerformDataBinding method binds the data in the
// retrievedData collection to elements of the data-bound control.
- PerformDataBinding (data);
+ InternalPerformDataBinding (data);
+ }
+
+ protected void InternalPerformDataBinding (IEnumerable data)
+ {
+ DataBoundControlAdapter adapter = (DataBoundControlAdapter)Adapter;
+ if (adapter != null)
+ adapter.PerformDataBinding (data);
+ else
+ PerformDataBinding (data);
}
protected virtual DataSourceSelectArguments CreateDataSourceSelectArguments ()
if (RequiresDataBinding) {\r
OnDataBinding (EventArgs.Empty);\r
RequiresDataBinding = false;\r
- PerformDataBinding (null);\r
+ InternalPerformDataBinding (null);\r
MarkAsDataBound ();\r
OnDataBound (EventArgs.Empty);\r
}\r
if (RequiresDataBinding) {
OnDataBinding (EventArgs.Empty);
RequiresDataBinding = false;
- PerformDataBinding (null);
+ InternalPerformDataBinding (null);
MarkAsDataBound ();
OnDataBound (EventArgs.Empty);
}
#if NET_2_0
using System.Collections;
using System.ComponentModel;
+using System.Web.UI.WebControls.Adapters;
namespace System.Web.UI.WebControls
{
Initialize ();
}
+ protected void InternalPerformDataBinding ()
+ {
+ HierarchicalDataBoundControlAdapter adapter
+ = (HierarchicalDataBoundControlAdapter)Adapter;
+ if (adapter != null)
+ adapter.PerformDataBinding ();
+ else
+ PerformDataBinding ();
+ }
+
protected internal virtual void PerformDataBinding ()
{
}
protected override void PerformSelect ()
{
OnDataBinding (EventArgs.Empty);
- PerformDataBinding ();
+ InternalPerformDataBinding ();
// The PerformDataBinding method has completed.
RequiresDataBinding = false;
MarkAsDataBound ();
#if !NET_2_0
IEnumerable list = DataSourceResolver.ResolveDataSource (DataSource, DataMember);
+ PerformDataBinding (list);
#else
IEnumerable list = GetData ().ExecuteSelect (DataSourceSelectArguments.Empty);
+ InternalPerformDataBinding (list);
#endif
- PerformDataBinding (list);
}
int count = items.Count;
for (int n = 0; n < count; n++) {
MenuItem item = items [n];
- RenderMenuItem (writer, item, (n + 1 == count) ? notLast : true, n == 0);
+ Adapters.MenuAdapter adapter = Adapter as Adapters.MenuAdapter;
+ if (adapter != null)
+ adapter.RenderItem (writer, item, n);
+ else
+ RenderMenuItem (writer, item, (n + 1 == count) ? notLast : true, n == 0);
}
if (!vertical)
return "javascript:Menu_" + handlerName + "('" + param1 + "','" + param2 + "'," + param3 + ")";
}
+ internal void RenderItem (HtmlTextWriter writer, MenuItem item, int position) {
+ // notLast should be true if item or any of its ancestors is not a
+ // last child.
+ bool notLast = false;
+ MenuItem parent;
+ MenuItem child = item;
+ while (null != (parent = child.Parent)) {
+ if (child.Index != parent.ChildItems.Count - 1) {
+ notLast = true;
+ break;
+ }
+ child = parent;
+ }
+
+ RenderMenuItem (writer, item, notLast, position == 0);
+ }
+
void RenderMenuItem (HtmlTextWriter writer, MenuItem item, bool notLast, bool isFirst) {
bool displayChildren = DisplayChildren (item);
bool dynamicChildren = displayChildren && (item.Depth + 1 >= StaticDisplayLevels);
protected internal bool IsEnabled
{
get {
- if (Enabled)
- return true;
- if(!HasControls())
- return false;
- for (int i = 0; i < Controls.Count; i++) {
- WebControl wc = Controls [i] as WebControl;
- if (wc != null && wc.IsEnabled)
- return true;
+ WebControl wc = this;
+ while (wc != null) {
+ if (!wc.Enabled)
+ return false;
+ wc = wc.Parent as WebControl;
}
- return false;
+ return true;
}
}
#endif
#endif
override void Render (HtmlTextWriter writer)
{
+#if NET_2_0
+ if (Adapter != null) {
+ Adapters.WebControlAdapter wca = (Adapters.WebControlAdapter) Adapter;
+ wca.Render(writer);
+ return;
+ }
+#endif
RenderBeginTag (writer);
RenderContents (writer);
RenderEndTag (writer);
+2008-03-09 Dean Brettle <dean@brettle.com>
+
+ * Page.cs (SavePageControlState, LoadPageControlState): save/load
+ adapter state in 2.0 profile.
+
+ * Page.cs (CreateHtmlTextWriter): call Browser.CreateHtmlTextWriter()
+ in 2.0 profile.
+
+ * Page.cs (RenderPage): call CreateHtmlTextWriter() to get the writer
+ in 2.0 profile.
+
+ * Page.cs (DeterminePostBackMode, InitOutputCache,
+ RenderClientScriptFormDeclaration, InternalProcessRequest,
+ PageStatePersister): added support for PageAdapters.
+
+ * Control.cs (Adapter, ResolveAdapter): implemented. Adapter calls
+ ResolveAdapter and remembers result. ResolveAdapter checks for adapters
+ of the Type hierarchy until it finds one.
+
+ * Control.cs (SaveViewStateRecursive, LoadViewStateRecursive): save/load
+ adapter state in 2.0 profile.
+
+ * HtmlTextWriter.cs (BeginRender, EndRender): added empty virtual methods
+ required by 2.0 profile. These are called by corresponding methods of
+ System.Web.UI.Adapters.ControlAdapter.
+
+ * Page.cs, Control.cs: don't access Request.Browser if it couldn't have
+ any adapters/writers because there are no files in App_Browsers/.
+
2008-03-09 Marek Habersack <mhabersack@novell.com>
* TemplateControlParser.cs: 2.0 allows controls with extensions
}
#if NET_2_0
- [MonoTODO ("Not implemented, always returns null")]
- protected ControlAdapter Adapter {
+ private ControlAdapter adapter = null;
+ private bool has_adapter = true;
+ protected internal ControlAdapter Adapter {
get {
- // for the time being, fool the
- // Control machinery into thinking we
- // don't have an Adapter. This will
- // allow us to write all the rest of
- // the Adapter handling code without
- // having to worry about *having*
- // adapters.
- return null;
+ if (has_adapter) {
+ if (adapter == null) {
+ adapter = ResolveAdapter();
+ }
+ if (adapter == null)
+ has_adapter = false;
+ else
+ adapter.Control = this;
+ }
+ return adapter;
}
}
#if NET_2_0
protected virtual ControlAdapter ResolveAdapter ()
{
- throw new NotImplementedException ();
+ if (Context == null)
+ return null;
+
+ if (!Context.Request.BrowserMightHaveAdapters)
+ return null;
+
+ // Search up the type hierarchy until we find a control with an adapter.
+ Type adapterType = null;
+ Type controlType = GetType();
+ IDictionary typeMap = Context.Request.Browser.Adapters;
+ while (adapterType == null && controlType != typeof(object)) {
+ adapterType = (Type)typeMap [controlType];
+ controlType = controlType.BaseType;
+ }
+
+ ControlAdapter a = null;
+ if (adapterType != null)
+ a = (ControlAdapter)Activator.CreateInstance (adapterType);
+ return a;
}
#endif
}
}
+#if NET_2_0
+ object thisAdapterViewState = null;
+ if (Adapter != null)
+ thisAdapterViewState = Adapter.SaveAdapterViewState ();
+#endif
object thisState = SaveViewState ();
+
if (thisState == null && controlList == null && controlStates == null) {
if (trace != null) {
#if MONO_TRACE
#endif
trace.SaveViewState (this, thisState);
}
+#if NET_2_0
+ thisState = new object[] { thisState, thisAdapterViewState };
+#endif
return new Triplet (thisState, controlList, controlStates);
}
}
#endif
Triplet savedInfo = (Triplet) savedState;
+#if NET_2_0
+ object[] controlAndAdapterViewStates = (object [])savedInfo.First;
+ if (Adapter != null)
+ Adapter.LoadAdapterViewState (controlAndAdapterViewStates [1]);
+ LoadViewState (controlAndAdapterViewStates [0]);
+#else
LoadViewState (savedInfo.First);
+#endif
ArrayList controlList = savedInfo.Second as ArrayList;
if (controlList == null)
{
throw new NotImplementedException ();
}
+
+ public virtual void BeginRender ()
+ {
+ }
+ public virtual void EndRender ()
+ {
+ }
#endif
}
-}
\ No newline at end of file
+}
[EditorBrowsable (EditorBrowsableState.Advanced)]
protected virtual HtmlTextWriter CreateHtmlTextWriter (TextWriter tw)
{
- return new HtmlTextWriter (tw);
+#if NET_2_0
+ if (Request.BrowserMightHaveSpecialWriter)
+ return Request.Browser.CreateHtmlTextWriter(tw);
+ else
+#endif
+ return new HtmlTextWriter (tw);
}
[EditorBrowsable (EditorBrowsableState.Never)]
}
[EditorBrowsable (EditorBrowsableState.Advanced)]
- protected virtual NameValueCollection DeterminePostBackMode ()
+ protected
+#if NET_2_0
+ internal
+#endif
+ virtual NameValueCollection DeterminePostBackMode ()
{
// if request was transfered from other page such Transfer
if (_context.IsProcessingInclude)
foreach (string h in hdrs)
cache.VaryByHeaders [h.Trim ()] = true;
}
+#if NET_2_0
+ if (PageAdapter != null)
+ {
+ if (PageAdapter.CacheVaryByParams != null) {
+ foreach (string p in PageAdapter.CacheVaryByParams)
+ cache.VaryByParams [p] = true;
+ }
+ if (PageAdapter.CacheVaryByHeaders != null) {
+ foreach (string h in PageAdapter.CacheVaryByHeaders)
+ cache.VaryByHeaders [h] = true;
+ }
+ }
+#endif
}
cache.Duration = duration;
void RenderClientScriptFormDeclaration (HtmlTextWriter writer, string formUniqueID)
{
- writer.WriteLine ("\tvar {0};\n\tif (document.getElementById) {{ {0} = document.getElementById ('{1}'); }}", theForm, formUniqueID);
- writer.WriteLine ("\telse {{ {0} = document.{1}; }}", theForm, formUniqueID);
+#if NET_2_0
+ if (PageAdapter != null) {
+ writer.WriteLine ("\tvar {0} = {1};\n", theForm, PageAdapter.GetPostBackFormReference(formUniqueID));
+ } else
+#endif
+ {
+ writer.WriteLine ("\tvar {0};\n\tif (document.getElementById) {{ {0} = document.getElementById ('{1}'); }}", theForm, formUniqueID);
+ writer.WriteLine ("\telse {{ {0} = document.{1}; }}", theForm, formUniqueID);
+ }
#if TARGET_J2EE
// TODO implement callback on portlet
string serverUrl = Request.RawUrl;
void InternalProcessRequest ()
{
- _requestValueCollection = this.DeterminePostBackMode();
+#if NET_2_0
+ if (PageAdapter != null) {
+ _requestValueCollection = PageAdapter.DeterminePostBackMode();
+ }
+ else
+#endif
+ {
+ _requestValueCollection = this.DeterminePostBackMode();
+ }
#if NET_2_0
// http://msdn2.microsoft.com/en-us/library/ms178141.aspx
//--
Trace.Write ("aspx.page", "Begin Render");
- HtmlTextWriter output = new HtmlTextWriter (Response.Output);
+ HtmlTextWriter output = CreateHtmlTextWriter (Response.Output);
RenderControl (output);
Trace.Write ("aspx.page", "End Render");
}
#endif
PageStatePersister PageStatePersister {
get {
+#if NET_2_0
+ if (page_state_persister == null && PageAdapter != null)
+ page_state_persister = PageAdapter.GetStatePersister();
+#endif
if (page_state_persister == null)
#if TARGET_J2EE
if (getFacesContext () != null)
{
if (requireStateControls == null) return null;
object[] state = new object [requireStateControls.Count];
-
+ object[] adapterState = new object [requireStateControls.Count];
bool allNull = true;
- for (int n=0; n<state.Length; n++) {
+ for (int n=0; n<requireStateControls.Count; n++) {
state [n] = ((Control) requireStateControls [n]).SaveControlState ();
if (state [n] != null) allNull = false;
if (trace != null)
trace.SaveControlState ((Control) requireStateControls [n], state [n]);
+ ControlAdapter adapter = ((Control) requireStateControls [n]).Adapter;
+ if (adapter != null)
+ adapterState [n] = adapter.SaveAdapterControlState ();
+ if (adapterState [n] != null) allNull = false;
}
if (allNull) return null;
- else return state;
+ else return new Pair (state, adapterState);
}
void LoadPageControlState (object data)
{
- _savedControlState = (object []) data;
-
+ _savedControlState = null;
+ if (data == null) return;
+ Pair statePair = (Pair)data;
+ _savedControlState = (object[]) statePair.First;
+ object[] adapterState = (object[]) statePair.Second;
+
if (requireStateControls == null) return;
- int max = Math.Min (requireStateControls.Count, _savedControlState != null ? _savedControlState.Length : requireStateControls.Count);
- for (int n=0; n < max; n++) {
+ int min = Math.Min (requireStateControls.Count, _savedControlState != null ? _savedControlState.Length : requireStateControls.Count);
+ for (int n=0; n < min; n++) {
Control ctl = (Control) requireStateControls [n];
ctl.LoadControlState (_savedControlState != null ? _savedControlState [n] : null);
+ if (ctl.Adapter != null)
+ ctl.Adapter.LoadAdapterControlState (adapterState != null ? adapterState [n] : null);
}
}
../../build/common/Consts.cs
../../build/common/Locale.cs
../../build/common/MonoTODOAttribute.cs
+System.Web.Configuration_2.0/CapabilitiesBuild.cs
+System.Web.Configuration_2.0/CapabilitiesChecksum.cs
+System.Web.Configuration_2.0/CapabilitiesResult.cs
+System.Web.Configuration_2.0/ICapabilitiesProcess.cs
+System.Web.Configuration_2.0/nBrowser/Result.cs
+System.Web.Configuration_2.0/nBrowser/NodeTypes.cs
+System.Web.Configuration_2.0/nBrowser/Identification.cs
+System.Web.Configuration_2.0/nBrowser/File.cs
+System.Web.Configuration_2.0/nBrowser/Build.cs
+System.Web.Configuration_2.0/nBrowser/Node.cs
+System.Web.Configuration_2.0/nBrowser/Exception.cs
System.Web/ApplicationShutdownReason.cs
System.Web/BeginEventHandler.cs
System.Web.Caching/AggregateCacheDependency.cs
System.Web/WebROCollection.cs
System.Web/WebSysDescriptionAttribute.cs
System.Web/XmlSiteMapProvider.cs
-
const int HaveSupportsUncheck = 102;
const int HaveSupportsXmlHttp = 103;
const int HaveTables = 104; // 18;
- //const int HaveTagWriter = 105; // 19;
+ const int HaveTagWriter = 105; // 19;
const int HaveType = 106;
const int HaveUseOptimizedCacheKey = 107;
const int HaveVBScript = 108; // 20;
Version msDomVersion;
string platform;
bool tables;
- //Type tagWriter;
+ Type tagWriter;
bool vbscript;
string version;
Version w3CDomVersion;
public Type TagWriter {
get {
- return typeof (HtmlTextWriter);
+ if (!Get (HaveTagWriter)) {
+ tagWriter = GetTagWriter ();
+ Set (HaveTagWriter);
+ }
+ return tagWriter;
}
}
+
+ internal virtual Type GetTagWriter ()
+ {
+ return typeof (HtmlTextWriter);
+ }
public string Type {
get {
+2008-03-09 Dean Brettle <dean@brettle.com>
+
+ * HttpApplicationFactory.cs: Added support for detecting
+ App_Browsers/*.browser files and using them to determine capabilities.
+ Also restart the app if the App_Browsers, App_Code, or App_GlobalResources
+ directories are created.
+
+ * BrowserCapabilities.cs (TagWriter): get value via internal virtual
+ GetTagWriter() method, which is overridden in nBrowser.Result.
+
+ * HttpRequest.cs (BrowserMightHaveSpecialWriter, BrowserMightHaveAdapters):
+ internal properties added to allow Page and Control methods to avoid
+ accessing Request.Browser to get browser-specific HtmlTextWriters or
+ ControlAdapters. Those things only exist when there are App_Browsers
+ files.
+
2008-03-09 Marek Habersack <mhabersack@novell.com>
* HttpUtility.cs: HTML-decode the query string prior to parsing
static bool app_shutdown = false;
#if NET_2_0
static bool app_disabled = false;
+ static string[] app_browsers_files = new string[0];
#endif
Stack available = new Stack ();
Stack available_for_end = new Stack ();
// Todo: Compile code from App_Code here
AppCodeCompiler acc = new AppCodeCompiler ();
acc.Compile ();
+
+ // Note whether there are any App_Browsers/*.browser files. If there
+ // are we will be using *.browser files for sniffing instead of browscap.ini
+ string app_browsers_path = Path.Combine (physical_app_path, "App_Browsers");
+ app_browsers_files = new string[0];
+ if (Directory.Exists (app_browsers_path)) {
+ app_browsers_files = Directory.GetFiles (app_browsers_path, "*.browser");
+ }
#endif
if (app_file != null) {
foreach (string dir in HttpApplication.BinDirectories)
WatchLocationForRestart (dir, "*.dll");
#if NET_2_0
+ // Restart if the App_* directories are created...
+ WatchLocationForRestart (".", "App_Code");
+ WatchLocationForRestart (".", "App_Browsers");
+ WatchLocationForRestart (".", "App_GlobalResources");
+ // ...or their contents is changed.
WatchLocationForRestart ("App_Code", "*", true);
WatchLocationForRestart ("App_Browsers", "*");
WatchLocationForRestart ("App_GlobalResources", "*");
get { return app_disabled; }
set { app_disabled = value; }
}
+
+ internal static string[] AppBrowsersFiles {
+ get { return app_browsers_files; }
+ }
+
+ static System.Web.Configuration.nBrowser.Build capabilities_processor = null;
+ static object capabilities_processor_lock = new object();
+ internal static System.Web.Configuration.ICapabilitiesProcess CapabilitiesProcessor {
+ get {
+ lock (capabilities_processor_lock) {
+ if (capabilities_processor == null) {
+ capabilities_processor = new System.Web.Configuration.nBrowser.Build();
+ foreach (string f in app_browsers_files)
+ capabilities_processor.AddBrowserFile(f);
+ }
+ }
+ return capabilities_processor;
+ }
+ }
#endif
internal static void DisableWatchers ()
}
}
+#if NET_2_0
+ internal bool BrowserMightHaveSpecialWriter {
+ get {
+ return (browser_capabilities != null
+ || HttpApplicationFactory.AppBrowsersFiles.Length > 0);
+ }
+ }
+
+ internal bool BrowserMightHaveAdapters {
+ get {
+ return (browser_capabilities != null
+ || HttpApplicationFactory.AppBrowsersFiles.Length > 0);
+ }
+ }
+#endif
+
public HttpClientCertificate ClientCertificate {
get {
if (client_cert == null)
mainsoft/NunitWeb/NunitWeb/Response.cs
mainsoft/NunitWeb/NunitWeb/StandardUrl.cs
mainsoft/NunitWeb/NunitWeb/WebTest.cs
+System.Web/AppBrowsersTest.cs
System.Web/HttpBrowserCapabilitiesTest.cs
System.Web/HttpCacheVaryByContentEncodingsTest.cs
System.Web/HttpCacheVaryByHeadersTest.cs
System.Web/HttpCookieTest.cs
System.Web/HttpRequestTest.cs
System.Web/HttpResponseTest.cs
+System.Web/HttpRuntimeTest.cs
System.Web/HttpServerUtilityTest.cs
System.Web/HttpUtilityTest.cs
System.Web/SiteMapProviderTest.cs
System.Web.UI/DataBindingCollectionTest.cs
System.Web.UI/DataBindingHandlerAttributeTest.cs
System.Web.UI/LiteralControlTest.cs
+System.Web.UI.Adapters/ControlAdapterTest.cs
+System.Web.UI.Adapters/PageAdapterTest.cs
System.Web.UI.HtmlControls/HtmlAnchorTest.cs
System.Web.UI.HtmlControls/HtmlButtonTest.cs
System.Web.UI.HtmlControls/HtmlContainerControlTest.cs
System.Web.UI/TestUrlPropertyAttribute.cs
System.Web.UI/ToolboxDataAttributeTest.cs
System.Web.UI/XhtmlTextWriterTest.cs
+System.Web.UI.WebControls.Adapters/DataBoundControlAdapterTest.cs
+System.Web.UI.WebControls.Adapters/HierarchicalDataBoundControlAdapterTest.cs
+System.Web.UI.WebControls.Adapters/WebControlAdapterTest.cs
+System.Web.UI.WebControls.Adapters/HideDisabledControlAdapterTest.cs
+System.Web.UI.WebControls.Adapters/MenuAdapterTest.cs
System.Web.UI.WebControls/AccessDataSourceTest.cs
System.Web.UI.WebControls/AdCreatedEventArgsTest.cs
System.Web.UI.WebControls/AutoGeneratedFieldTest.cs
--- /dev/null
+2008-01-12 Dean Brettle <dean@brettle.com>
+
+ * PageAdapterTest.cs: added tests for PageAdapter.
+
+2008-01-07 Dean Brettle <dean@brettle.com>
+
+ * ControlAdapterTest.cs (ConfigCapabilitiesNotCalled): added test to
+ ensure that HttpCapabilitiesBase.ConfigCapabilities() is not called
+ during normal page processing if no files are in App_Browsers.
+
+
+2008-01-07 Dean Brettle <dean@brettle.com>
+
+ * ControlAdapterTest.cs: added tests for ControlAdapter.
--- /dev/null
+//
+// Tests for System.Web.UI.Adapters.ControlAdapter
+//
+// Author:
+// Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.Adapters
+{
+ [TestFixture]
+ public class ControlAdapterTest
+ {
+ [Test]
+ public void BeginRender ()
+ {
+ MyControlAdapter a = new MyControlAdapter ();
+ MyHtmlTextWriter w = new MyHtmlTextWriter ();
+ a.CallBeginRender (w);
+ Assert.IsTrue (w.begin_render_called, "BeginRender #1");
+ }
+
+ [Test]
+ public void EndRender ()
+ {
+ MyControlAdapter a = new MyControlAdapter ();
+ MyHtmlTextWriter w = new MyHtmlTextWriter ();
+ a.CallEndRender (w);
+ Assert.IsTrue (w.end_render_called, "EndRender #1");
+ }
+
+ [Test]
+ public void Render ()
+ {
+ MyControl c = new MyControl();
+ MyHtmlTextWriter w = new MyHtmlTextWriter ();
+ c.AdapterCallRender (w);
+ Assert.IsTrue (c.render_called, "Render #1");
+ }
+
+ [Test]
+ public void RenderChildren ()
+ {
+ MyControl c = new MyControl ();
+ MyHtmlTextWriter w = new MyHtmlTextWriter ();
+ c.AdapterCallRenderChildren (w);
+ Assert.IsTrue (c.render_children_called, "RenderChildren #1");
+ }
+
+ [Test]
+ public void OnInit ()
+ {
+ MyControl c = new MyControl ();
+ EventArgs e = new EventArgs ();
+ c.AdapterCallOnInit (e);
+ Assert.AreEqual (e, c.on_init_arg, "OnInit #1");
+ }
+
+ [Test]
+ public void OnLoad ()
+ {
+ MyControl c = new MyControl ();
+ EventArgs e = new EventArgs ();
+ c.AdapterCallOnLoad (e);
+ Assert.AreEqual (e, c.on_load_arg, "OnLoad #1");
+ }
+
+ [Test]
+ public void OnPreRender ()
+ {
+ MyControl c = new MyControl ();
+ EventArgs e = new EventArgs ();
+ c.AdapterCallOnPreRender (e);
+ Assert.AreEqual (e, c.on_pre_render_arg, "OnPreRender #1");
+ }
+
+ [Test]
+ public void OnUnload ()
+ {
+ MyControl c = new MyControl ();
+ EventArgs e = new EventArgs ();
+ c.AdapterCallOnUnload (e);
+ Assert.AreEqual (e, c.on_unload_arg, "OnUnload #1");
+ }
+
+ [Test]
+ public void Page ()
+ {
+ MyControl c = new MyControl ();
+ c.Page = new Page ();
+ c.AdapterGetPage ();
+ Assert.AreEqual (c.Page, c.AdapterGetPage (), "Page #1");
+ }
+
+ [Test]
+ public void PageAdapter ()
+ {
+ MyControl c = new MyControl ();
+ PageAdapter pa = new MyPageAdapter ();
+ c.Page = new MyPage (pa);
+ c.AdapterGetPageAdapter ();
+ Assert.AreEqual (c.Page.PageAdapter, c.AdapterGetPageAdapter (), "PageAdapter #1");
+ }
+
+ [Test]
+ [Category ("NunitWeb")]
+ public void Browser ()
+ {
+ WebTest t = new WebTest (PageInvoker.CreateOnInit (Browser_OnInit));
+ t.Run ();
+ }
+
+ public static void Browser_OnInit (Page p)
+ {
+ MyControl c = new MyControl ();
+ p.Controls.Add (c);
+
+ Assert.AreEqual (p.Request.Browser, c.AdapterGetBrowser (), "Browser #1");
+ }
+
+
+ [Test]
+ [Category ("NunitWeb")]
+ public void ConfigCapabilitiesNotCalled ()
+ {
+ WebTest t = new WebTest (new HandlerInvoker (ConfigCapabilitiesNotCalled_Reset));
+ t.Run ();
+ t = new WebTest (PageInvoker.CreateOnInit (ConfigCapabilitiesNotCalled_OnInit));
+ t.Run ();
+ }
+
+ public static void ConfigCapabilitiesNotCalled_Reset ()
+ {
+ HttpCapabilitiesBase.GetConfigCapabilities_called = false;
+ }
+
+ private static EventHandler end_request_handler;
+
+ public static void ConfigCapabilitiesNotCalled_OnInit (Page p)
+ {
+ end_request_handler = new EventHandler (ConfigCapabilitiesNotCalled_EndRequest);
+ HttpContext.Current.ApplicationInstance.EndRequest += end_request_handler;
+ }
+
+ public static void ConfigCapabilitiesNotCalled_EndRequest (object sender, EventArgs args)
+ {
+ // Ensure that this handler doesn't stick around for other tests.
+ HttpContext.Current.ApplicationInstance.EndRequest -= end_request_handler;
+
+ // GetConfigCapabilities() should not have been called because there are no
+ // files in App_Browsers/.
+ Assert.IsFalse (HttpCapabilitiesBase.GetConfigCapabilities_called,
+ "ConfigCapabilitiesNotCalled #1");
+ }
+
+#region Support classes
+
+ class MyPageAdapter : PageAdapter
+ {
+ internal MyPageAdapter () : base ()
+ {
+ }
+ }
+
+ class MyPage : Page
+ {
+ internal MyPage (PageAdapter pa) : base ()
+ {
+ page_adapter = pa;
+ }
+
+ private PageAdapter page_adapter;
+
+ protected override ControlAdapter ResolveAdapter ()
+ {
+ return page_adapter;
+ }
+ }
+
+ class MyControl : Control
+ {
+ internal bool render_called = false;
+ protected override void Render (HtmlTextWriter w)
+ {
+ render_called = true;
+ }
+
+ internal bool render_children_called = false;
+ protected override void RenderChildren (HtmlTextWriter w)
+ {
+ render_children_called = true;
+ }
+
+ internal EventArgs on_init_arg = null;
+ protected override void OnInit (EventArgs e)
+ {
+ on_init_arg = e;
+ }
+
+ internal EventArgs on_load_arg = null;
+ protected override void OnLoad (EventArgs e)
+ {
+ on_load_arg = e;
+ }
+
+ internal EventArgs on_pre_render_arg = null;
+ protected override void OnPreRender (EventArgs e)
+ {
+ on_pre_render_arg = e;
+ }
+
+ internal EventArgs on_unload_arg = null;
+ protected override void OnUnload (EventArgs e)
+ {
+ on_unload_arg = e;
+ }
+
+ internal MyControlAdapter adapter = new MyControlAdapter ();
+ protected override ControlAdapter ResolveAdapter ()
+ {
+ return adapter;
+ }
+
+ internal void AdapterCallRender (HtmlTextWriter w)
+ {
+ ((MyControlAdapter)Adapter).CallRender (w);
+ }
+
+ internal void AdapterCallRenderChildren (HtmlTextWriter w)
+ {
+ ((MyControlAdapter)Adapter).CallRenderChildren (w);
+ }
+
+ internal void AdapterCallOnInit (EventArgs e)
+ {
+ ((MyControlAdapter)Adapter).CallOnInit (e);
+ }
+
+ internal void AdapterCallOnLoad (EventArgs e)
+ {
+ ((MyControlAdapter)Adapter).CallOnLoad (e);
+ }
+
+ internal void AdapterCallOnPreRender (EventArgs e)
+ {
+ ((MyControlAdapter)Adapter).CallOnPreRender (e);
+ }
+
+ internal void AdapterCallOnUnload (EventArgs e)
+ {
+ ((MyControlAdapter)Adapter).CallOnUnload (e);
+ }
+
+ internal Page AdapterGetPage ()
+ {
+ return ((MyControlAdapter)Adapter).GetPage ();
+ }
+
+ internal PageAdapter AdapterGetPageAdapter ()
+ {
+ return ((MyControlAdapter)Adapter).GetPageAdapter ();
+ }
+
+ internal HttpBrowserCapabilities AdapterGetBrowser ()
+ {
+ return ((MyControlAdapter)Adapter).GetBrowser ();
+ }
+ }
+
+ class MyControlAdapter : ControlAdapter
+ {
+ internal MyControlAdapter () : base ()
+ {
+ }
+
+ internal void CallBeginRender (HtmlTextWriter w)
+ {
+ BeginRender (w);
+ }
+
+ internal void CallEndRender (HtmlTextWriter w)
+ {
+ EndRender (w);
+ }
+
+ internal void CallRender (HtmlTextWriter w)
+ {
+ Render (w);
+ }
+
+ internal void CallRenderChildren (HtmlTextWriter w)
+ {
+ RenderChildren (w);
+ }
+
+ internal void CallOnInit (EventArgs e)
+ {
+ OnInit (e);
+ }
+
+ internal void CallOnLoad (EventArgs e)
+ {
+ OnLoad (e);
+ }
+
+ internal void CallOnPreRender (EventArgs e)
+ {
+ OnPreRender (e);
+ }
+
+ internal void CallOnUnload (EventArgs e)
+ {
+ OnUnload (e);
+ }
+
+ internal Page GetPage ()
+ {
+ return Page;
+ }
+
+ internal PageAdapter GetPageAdapter ()
+ {
+ return PageAdapter;
+ }
+
+ internal HttpBrowserCapabilities GetBrowser ()
+ {
+ return Browser;
+ }
+ }
+
+ class MyHtmlTextWriter : HtmlTextWriter
+ {
+ internal MyHtmlTextWriter () : base (new StringWriter ())
+ {
+ }
+
+ internal bool begin_render_called = false;
+ public override void BeginRender ()
+ {
+ begin_render_called = true;
+ }
+
+ internal bool end_render_called = false;
+ public override void EndRender ()
+ {
+ end_render_called = true;
+ }
+ }
+#endregion
+ }
+}
+#endif
--- /dev/null
+//
+// Tests for System.Web.UI.Adapters.PageAdapter
+//
+// Author:
+// Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.Adapters
+{
+ [TestFixture]
+ public class PageAdapterTest
+ {
+ private MyPageAdapter mpa;
+ private MyPage page;
+
+ [TestFixtureSetUp]
+ public void SetUpTest ()
+ {
+#if VISUAL_STUDIO
+ WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.PageWithAdapter.aspx", "PageWithAdapter.aspx");
+#else
+ WebTest.CopyResource (GetType (), "PageWithAdapter.aspx", "PageWithAdapter.aspx");
+#endif
+ }
+
+ [SetUp]
+ public void SetUp()
+ {
+ page = new MyPage();
+ mpa = new MyPageAdapter (page);
+ }
+
+ [Test]
+ public void CacheVaryByHeaders ()
+ {
+ Assert.IsNull (mpa.CacheVaryByHeaders, "CacheVaryByHeaders #1");
+ }
+
+ [Test]
+ public void CacheVaryByParams ()
+ {
+ Assert.IsNull (mpa.CacheVaryByParams, "CacheVaryByParams #1");
+ }
+
+ [Test]
+ public void GetStatePersister ()
+ {
+ PageStatePersister persister = mpa.GetStatePersister ();
+ Assert.AreEqual (typeof(HiddenFieldPageStatePersister),
+ persister.GetType (), "GetStatePersister #1");
+ }
+
+ [Test]
+ public void GetPostBackFormReference ()
+ {
+ Assert.AreEqual("document.forms['test']", mpa.GetPostBackFormReference ("test"),
+ "GetPostBackFormReference #1");
+ }
+
+ [Test]
+ public void DeterminePostBackMode ()
+ {
+ Assert.AreEqual(page.DeterminePostBackMode (), mpa.DeterminePostBackMode (),
+ "DeterminePostBackMode #1");
+ }
+
+ [Test]
+ public void RenderBeginHyperlink_NoEncode ()
+ {
+ StringWriter sw = new StringWriter ();
+ HtmlTextWriter htw = new HtmlTextWriter (sw);
+ mpa.RenderBeginHyperlink (htw, "url with &, <, and \"", false, "softKeyLabel");
+ Assert.AreEqual("<a href=\"url with &, <, and \"\">", sw.ToString(),
+ "RenderBeginHyperlink_NoEncode #1");
+ }
+
+ [Test]
+ public void RenderBeginHyperlink_Encode ()
+ {
+ StringWriter sw = new StringWriter ();
+ HtmlTextWriter htw = new HtmlTextWriter (sw);
+ mpa.RenderBeginHyperlink (htw, "url with &, <, and \"", true, "softKeyLabel");
+ Assert.AreEqual("<a href=\"url with &, <, and "\">", sw.ToString(),
+ "RenderBeginHyperlink_Encode #1");
+ }
+
+ [Test]
+ public void RenderBeginHyperlink_NoEncode_AccessKey ()
+ {
+ StringWriter sw = new StringWriter ();
+ HtmlTextWriter htw = new HtmlTextWriter (sw);
+ mpa.RenderBeginHyperlink (htw, "url with &, <, and \"", false, "softKeyLabel", "X");
+ Assert.AreEqual("<a href=\"url with &, <, and \"\" accesskey=\"X\">",
+ sw.ToString(), "RenderBeginHyperlink_NoEncode_AccessKey #1");
+ }
+
+ [Test]
+ public void RenderBeginHyperlink_Encode_AccessKey ()
+ {
+ StringWriter sw = new StringWriter ();
+ HtmlTextWriter htw = new HtmlTextWriter (sw);
+ mpa.RenderBeginHyperlink (htw, "url with &, <, and \"", true, "softKeyLabel", "X");
+ Assert.AreEqual("<a href=\"url with &, <, and "\" accesskey=\"X\">",
+ sw.ToString(), "RenderBeginHyperlink_Encode_AccessKey #1");
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentOutOfRangeException))]
+ public void RenderBeginHyperlink_LongAccessKey ()
+ {
+ StringWriter sw = new StringWriter ();
+ HtmlTextWriter htw = new HtmlTextWriter (sw);
+ mpa.RenderBeginHyperlink (htw, "url with &, <, and \"", true, "softKeyLabel", "accessKey");
+ }
+
+ [Test]
+ public void EndHyperlink ()
+ {
+ StringWriter sw = new StringWriter ();
+ HtmlTextWriter htw = new HtmlTextWriter (sw);
+ mpa.RenderBeginHyperlink (htw, "url", false, null);
+ mpa.RenderEndHyperlink (htw);
+ Assert.AreEqual("<a href=\"url\"></a>", sw.ToString(), "RenderEndHyperlink #1");
+ }
+
+ [Test]
+ [Category ("NunitWeb")]
+ public void RenderPostBackEvent ()
+ {
+ WebTest t = new WebTest ("PageWithAdapter.aspx");
+ PageDelegates pd = new PageDelegates ();
+ pd.SaveStateComplete = RenderPostBackEvent_OnSaveStateComplete;
+ t.Invoker = new PageInvoker (pd);
+ string html = t.Run ();
+ File.WriteAllText("response.html", html);
+ }
+
+ public static void RenderPostBackEvent_OnSaveStateComplete (Page p)
+ {
+ TestPageWithAdapter pageWithAdapter = (TestPageWithAdapter) p;
+ TestAdapter testAdapter = (TestAdapter)pageWithAdapter.PageAdapter;
+ {
+ StringWriter sw = new StringWriter ();
+ HtmlTextWriter htw = new HtmlTextWriter (sw);
+ testAdapter.RenderPostBackEvent (htw, "target", "argument", "softKeyLabel", "text", "postUrl", "X", true);
+ Assert.AreEqual("<a href=\"postUrl?__VIEWSTATE=DAAAAA%3d%3d&__EVENTTARGET=target&__EVENTARGUMENT=argument&__PREVIOUSPAGE=/NunitWeb/PageWithAdapter.aspx\" accesskey=\"X\">text</a>",
+ sw.ToString(), "RenderPostBackEvent #1");
+ }
+ {
+ StringWriter sw = new StringWriter ();
+ HtmlTextWriter htw = new HtmlTextWriter (sw);
+ testAdapter.RenderPostBackEvent (htw, "target", "argument", "softKeyLabel", "text", "postUrl", "X", false);
+ Assert.AreEqual("<a href=\"postUrl?__VIEWSTATE=DAAAAA%3d%3d&__EVENTTARGET=target&__EVENTARGUMENT=argument&__PREVIOUSPAGE=/NunitWeb/PageWithAdapter.aspx\" accesskey=\"X\">text</a>",
+ sw.ToString(), "RenderPostBackEvent #2");
+ }
+ {
+ StringWriter sw = new StringWriter ();
+ HtmlTextWriter htw = new HtmlTextWriter (sw);
+ testAdapter.RenderPostBackEvent (htw, "target", "argument", "softKeyLabel", "text", "postUrl", "X");
+ Assert.AreEqual("<a href=\"postUrl?__VIEWSTATE=DAAAAA%3d%3d&__EVENTTARGET=target&__EVENTARGUMENT=argument&__PREVIOUSPAGE=/NunitWeb/PageWithAdapter.aspx\" accesskey=\"X\">text</a>",
+ sw.ToString(), "RenderPostBackEvent #3");
+ }
+ {
+ StringWriter sw = new StringWriter ();
+ HtmlTextWriter htw = new HtmlTextWriter (sw);
+ testAdapter.RenderPostBackEvent (htw, "target", "argument", "softKeyLabel", "text");
+ Assert.AreEqual("<a href=\"/NunitWeb/PageWithAdapter.aspx?__VIEWSTATE=DAAAAA%3d%3d&__EVENTTARGET=target&__EVENTARGUMENT=argument&__PREVIOUSPAGE=/NunitWeb/PageWithAdapter.aspx\">text</a>",
+ sw.ToString(), "RenderPostBackEvent #4");
+ }
+
+ }
+
+ [Test]
+ public void RadioButtons ()
+ {
+ ArrayList group = new ArrayList (mpa.GetRadioButtonsByGroup ("Group1"));
+ Assert.AreEqual (0, group.Count, "RadioButtons #0");
+
+ RadioButton g1b1 = new RadioButton ();
+ g1b1.GroupName = "Group1";
+ mpa.RegisterRadioButton(g1b1);
+ RadioButton g1b2 = new RadioButton ();
+ g1b2.GroupName = "Group1";
+ mpa.RegisterRadioButton(g1b2);
+ RadioButton g2b1 = new RadioButton ();
+ g2b1.GroupName = "Group2";
+ mpa.RegisterRadioButton (g2b1);
+ RadioButton noGroupB1 = new RadioButton ();
+ mpa.RegisterRadioButton (noGroupB1);
+
+ Assert.AreEqual (0, mpa.GetRadioButtonsByGroup ("Non-existent group").Count, "RadioButtons #1");
+
+ ArrayList group1 = new ArrayList (mpa.GetRadioButtonsByGroup ("Group1"));
+ Assert.AreEqual (2, group1.Count, "RadioButtons #2");
+ Assert.IsTrue (group1.Contains (g1b1), "RadioButtons #3");
+ Assert.IsTrue (group1.Contains (g1b2), "RadioButtons #4");
+
+ ArrayList group2 = new ArrayList (mpa.GetRadioButtonsByGroup ("Group2"));
+ Assert.AreEqual (1, group2.Count, "RadioButtons #5");
+ Assert.IsTrue (group2.Contains (g2b1), "RadioButtons #6");
+
+ ArrayList noGroup = new ArrayList (mpa.GetRadioButtonsByGroup (""));
+ Assert.AreEqual (1, noGroup.Count, "RadioButtons #7");
+ Assert.IsTrue (noGroup.Contains (noGroupB1), "RadioButtons #8");
+ }
+
+ [Test]
+ public void ClientState ()
+ {
+ page.RawViewState = "test";
+ Assert.AreEqual ("test", mpa.ClientState, "ClientState #1");
+ }
+
+ [Test]
+ public void TransformText ()
+ {
+ Assert.AreEqual ("test", mpa.TransformText("test"), "TransformText #1");
+ Assert.IsNull (mpa.TransformText(null), "TransformText #2");
+ }
+
+ [TestFixtureTearDown]
+ public void TearDown ()
+ {
+ WebTest.Unload ();
+ }
+
+ class MyPageAdapter : PageAdapter
+ {
+ internal MyPageAdapter (Page p) : base (p)
+ {
+ }
+
+ new internal string ClientState {
+ get { return base.ClientState; }
+ }
+ }
+
+ class MyPage : Page
+ {
+ internal MyPage () : base ()
+ {
+ }
+
+ NameValueCollection post_back_mode = new NameValueCollection ();
+
+ override protected internal NameValueCollection DeterminePostBackMode ()
+ {
+ return post_back_mode;
+ }
+ }
+ }
+
+}
+#endif
--- /dev/null
+2008-01-15 Dean Brettle <dean@brettle.com>
+
+ * MenuAdapterTest.cs: added
+
+2008-01-13 Dean Brettle <dean@brettle.com>
+
+ * WebControlAdapterTest.cs, HierarchicalDataBoundControlAdapterTest.cs,
+ DataBoundControlAdapterTest.cs, HideDisabledControlAdapterTest.cs: added
--- /dev/null
+//
+// Tests for System.Web.UI.WebControls.Adapters.DataBoundControlAdapter
+//
+// Author:
+// Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.WebControls.Adapters
+{
+ [TestFixture]
+ public class DataBoundControlAdapterTest
+ {
+ MyDataBoundControl c;
+ MyDataBoundControlAdapter a;
+
+ [SetUp]
+ public void SetUp ()
+ {
+ c = new MyDataBoundControl ();
+ a = new MyDataBoundControlAdapter (c);
+ }
+
+ [Test]
+ public void PerformDataBinding ()
+ {
+ ArrayList data = new ArrayList ();
+ a.PerformDataBinding (data);
+ Assert.AreEqual (data, c.data, "PerformDataBinding #1");
+ }
+
+ [Test]
+ public void Control ()
+ {
+ Assert.AreEqual (c, a.Control, "Control #1");
+ }
+
+#region Support classes
+
+ class MyDataBoundControl : DataBoundControl
+ {
+ internal IEnumerable data;
+
+ protected internal override void PerformDataBinding (IEnumerable data)
+ {
+ this.data = data;
+ }
+
+ }
+
+ class MyDataBoundControlAdapter : DataBoundControlAdapter
+ {
+ internal MyDataBoundControlAdapter (DataBoundControl c) : base (c)
+ {
+ }
+
+ new internal DataBoundControl Control {
+ get { return base.Control; }
+ }
+ }
+#endregion
+ }
+}
+#endif
--- /dev/null
+//
+// Tests for System.Web.UI.WebControls.Adapters.HideDisabledControlAdapter
+//
+// Author:
+// Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.WebControls.Adapters
+{
+ [TestFixture]
+ public class HideDisabledControlAdapterTest
+ {
+ [Test]
+ public void Render ()
+ {
+ WebControl parent = new MyWebControl();
+ MyWebControl c = new MyWebControl ();
+ HideDisabledControlAdapter a = new HideDisabledControlAdapter (c);
+ StringWriter sw;
+ HtmlTextWriter w;
+
+ sw = new StringWriter();
+ w = new HtmlTextWriter(sw);
+ a.Render (w);
+ Assert.AreEqual ("RenderBeginTag\nRenderContents\nRenderEndTag\n", sw.ToString(), "Render #1");
+
+
+ sw = new StringWriter();
+ w = new HtmlTextWriter(sw);
+ c.Enabled = false;
+ a.Render (w);
+ Assert.AreEqual ("", sw.ToString(), "Render #2");
+
+ sw = new StringWriter();
+ w = new HtmlTextWriter(sw);
+ parent.Enabled = false;
+ c.Enabled = true;
+ parent.Controls.Add(c);
+ a.Render (w);
+ Assert.AreEqual ("", sw.ToString(), "Render #3");
+ }
+
+#region Support classes
+
+ class MyWebControl : WebControl
+ {
+ public override void RenderBeginTag (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderBeginTag");
+ }
+
+ protected internal override void RenderContents (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderContents");
+ }
+
+ public override void RenderEndTag (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderEndTag");
+ }
+ }
+#endregion
+ }
+}
+#endif
--- /dev/null
+//
+// Tests for System.Web.UI.WebControls.Adapters.HierarchicalDataBoundControlAdapter
+//
+// Author:
+// Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.WebControls.Adapters
+{
+ [TestFixture]
+ public class HierarchicalDataBoundControlAdapterTest
+ {
+ MyHierarchicalDataBoundControl c;
+ MyHierarchicalDataBoundControlAdapter a;
+
+ [SetUp]
+ public void SetUp ()
+ {
+ c = new MyHierarchicalDataBoundControl ();
+ a = new MyHierarchicalDataBoundControlAdapter (c);
+ }
+
+ [Test]
+ public void PerformDataBinding ()
+ {
+ a.PerformDataBinding ();
+ Assert.IsTrue (c.perform_data_binding_called, "PerformDataBinding #1");
+ }
+
+ [Test]
+ public void Control ()
+ {
+ Assert.AreEqual (c, a.Control, "Control #1");
+ }
+
+#region Support classes
+
+ class MyHierarchicalDataBoundControl : HierarchicalDataBoundControl
+ {
+ internal bool perform_data_binding_called;
+
+ protected internal override void PerformDataBinding ()
+ {
+ perform_data_binding_called = true;
+ }
+
+ }
+
+ class MyHierarchicalDataBoundControlAdapter : HierarchicalDataBoundControlAdapter
+ {
+ internal MyHierarchicalDataBoundControlAdapter (HierarchicalDataBoundControl c) : base (c)
+ {
+ }
+
+ new internal HierarchicalDataBoundControl Control {
+ get { return base.Control; }
+ }
+ }
+#endregion
+ }
+}
+#endif
--- /dev/null
+//
+// Tests for System.Web.UI.WebControls.Adapters.MenuAdapter
+//
+// Author:
+// Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.WebControls.Adapters
+{
+ [TestFixture]
+ public class MenuAdapterTest
+ {
+ MyMenu c;
+ MyMenuAdapter a;
+ StringWriter sw;
+ HtmlTextWriter w;
+ Page p;
+ EventArgs e;
+
+ [SetUp]
+ public void SetUp ()
+ {
+ p = new Page ();
+ c = new MyMenu ();
+ a = new MyMenuAdapter (c);
+ p.Controls.Add(c);
+ sw = new StringWriter ();
+ w = new HtmlTextWriter (sw);
+ e = new EventArgs();
+ }
+
+ [Test]
+ public void OnInit ()
+ {
+ a.OnInit (e);
+ Assert.IsTrue (p.RequiresControlState (c), "OnInit #1");
+ Assert.AreEqual (e, c.on_init_arg, "OnInit #2");
+ }
+
+ [Test]
+ public void OnPreRender ()
+ {
+ a.OnPreRender (e);
+ Assert.AreEqual (e, c.on_pre_render_arg, "OnPreRender #1");
+ }
+
+ [Test]
+ public void RaisePostBackEvent ()
+ {
+ ((IPostBackEventHandler)a).RaisePostBackEvent ("eventArg");
+ Assert.AreEqual ("eventArg", c.raise_post_back_event_arg, "RaisePostBackEvent #1");
+ }
+
+ [Test]
+ public void RenderBeginTag ()
+ {
+ a.RenderBeginTag (w);
+ Assert.AreEqual ("RenderBeginTag\n", sw.ToString (), "RenderBeginTag #1");
+ }
+
+ [Test]
+ public void RenderContentsTag ()
+ {
+ a.RenderContents (w);
+ Assert.AreEqual ("RenderContents\n", sw.ToString (), "RenderContents #1");
+ }
+
+ [Test]
+ public void RenderEndTag ()
+ {
+ a.RenderEndTag (w);
+ Assert.AreEqual ("RenderEndTag\n", sw.ToString (), "RenderEndTag #1");
+ }
+
+ [Test]
+ public void RenderItem ()
+ {
+ MenuItem item = new MenuItem("menu item text");
+ a.RenderItem (w, item, 0);
+ Assert.IsTrue (sw.ToString ().IndexOf("menu item text") != -1, "RenderItem #1");
+ }
+
+ [Test]
+ public void Control ()
+ {
+ Assert.AreEqual (c, a.Control, "Control #1");
+ }
+
+
+
+#region Support classes
+
+ class MyMenu : Menu
+ {
+
+ internal EventArgs on_init_arg;
+ protected internal override void OnInit (EventArgs e)
+ {
+ on_init_arg = e;
+ base.OnInit (e);
+ }
+
+ internal EventArgs on_pre_render_arg;
+ protected internal override void OnPreRender (EventArgs e)
+ {
+ on_pre_render_arg = e;
+ base.OnPreRender (e);
+ }
+
+ internal string raise_post_back_event_arg;
+ protected internal override void RaisePostBackEvent (string eventArgument)
+ {
+ raise_post_back_event_arg = eventArgument;
+ }
+
+ public override void RenderBeginTag (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderBeginTag");
+ }
+
+ protected internal override void RenderContents (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderContents");
+ }
+
+ public override void RenderEndTag (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderEndTag");
+ }
+
+ }
+
+ class MyMenuAdapter : MenuAdapter
+ {
+ internal MyMenuAdapter (Menu c) : base (c)
+ {
+ }
+
+ new internal void RenderBeginTag (HtmlTextWriter w)
+ {
+ base.RenderBeginTag (w);
+ }
+
+ new internal void RenderContents (HtmlTextWriter w)
+ {
+ base.RenderContents (w);
+ }
+
+ new internal void RenderEndTag (HtmlTextWriter w)
+ {
+ base.RenderEndTag (w);
+ }
+
+ new internal Menu Control {
+ get { return base.Control; }
+ }
+ }
+
+#endregion
+ }
+}
+#endif
--- /dev/null
+//
+// Tests for System.Web.UI.WebControls.Adapters.WebControlAdapter
+//
+// Author:
+// Dean Brettle (dean@brettle.com)
+//
+// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+#if NET_2_0
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Drawing;
+using System.IO;
+using System.Globalization;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
+using System.Web.Configuration;
+using MonoTests.SystemWeb.Framework;
+
+
+namespace MonoTests.System.Web.UI.WebControls.Adapters
+{
+ [TestFixture]
+ public class WebControlAdapterTest
+ {
+ MyWebControl c;
+ MyWebControlAdapter a;
+ StringWriter sw;
+ HtmlTextWriter w;
+
+ [SetUp]
+ public void SetUp ()
+ {
+ c = new MyWebControl ();
+ a = new MyWebControlAdapter (c);
+ sw = new StringWriter ();
+ w = new HtmlTextWriter (sw);
+ }
+
+ [Test]
+ public void RenderBeginTag ()
+ {
+ a.RenderBeginTag (w);
+ Assert.AreEqual ("RenderBeginTag\n", sw.ToString (), "RenderBeginTag #1");
+ }
+
+ [Test]
+ public void RenderContentsTag ()
+ {
+ a.RenderContents (w);
+ Assert.AreEqual ("RenderContents\n", sw.ToString (), "RenderContents #1");
+ }
+
+ [Test]
+ public void RenderEndTag ()
+ {
+ a.RenderEndTag (w);
+ Assert.AreEqual ("RenderEndTag\n", sw.ToString (), "RenderEndTag #1");
+ }
+
+ [Test]
+ public void Render ()
+ {
+ a.Render (w);
+ Assert.AreEqual ("RenderBeginTag\nRenderContents\nRenderEndTag\n", sw.ToString (), "Render #1");
+ }
+
+ [Test]
+ public void Control ()
+ {
+ Assert.AreEqual (c, a.Control, "Control #1");
+ }
+
+ [Test]
+ public void IsEnabled ()
+ {
+ MyWebControl parent = new MyWebControl ();
+ parent.Controls.Add (c);
+ Assert.IsTrue (a.IsEnabled, "IsEnabled #1");
+ parent.Enabled = false;
+ Assert.IsFalse (a.IsEnabled, "IsEnabled #2");
+ parent.Enabled = true;
+ c.Enabled = false;
+ Assert.IsFalse (a.IsEnabled, "IsEnabled #3");
+ }
+
+#region Support classes
+
+ class MyWebControl : WebControl
+ {
+ public override void RenderBeginTag (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderBeginTag");
+ }
+
+ protected internal override void RenderContents (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderContents");
+ }
+
+ public override void RenderEndTag (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderEndTag");
+ }
+
+ }
+
+ class MyWebControlAdapter : WebControlAdapter
+ {
+ internal MyWebControlAdapter (WebControl wc) : base (wc)
+ {
+ }
+
+ new internal void RenderBeginTag (HtmlTextWriter w)
+ {
+ base.RenderBeginTag(w);
+ }
+
+ new internal void RenderContents (HtmlTextWriter w)
+ {
+ base.RenderContents(w);
+ }
+
+ new internal void RenderEndTag (HtmlTextWriter w)
+ {
+ base.RenderEndTag(w);
+ }
+
+ new internal void Render (HtmlTextWriter w)
+ {
+ base.Render(w);
+ }
+
+ new internal WebControl Control {
+ get { return base.Control; }
+ }
+
+ new internal bool IsEnabled {
+ get { return base.IsEnabled; }
+ }
+ }
+#endregion
+ }
+}
+#endif
+2008-03-09 Dean Brettle <dean@brettle.com>
+
+ * MenuTest.cs (Menu_RenderStaticItems): added tests to check that
+ result was the same when using the base MenuAdapter as when using
+ no adapter.
+
+ * MenuTest.cs (Menu_RenderStaticItemsWithAdapter): added test
+ to ensure that MenuAdapter.RenderItem() is called.
+
+ * HierarchicalDataBoundControlTest.cs, WebControlTest.cs,
+ DataBoundControlTest.cs: added test for use of ControlAdapters
+ when present.
+
+ * WebControl.cs: added test for IsEnabled.
+
2008-01-08 Igor Zelmanovich <igorz@mainsoft.com>
* DetailsViewTest.cs:
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
+using System.Web.UI.WebControls.Adapters;
using System.Text;
using System.Collections;
using System.Data;
public DataSourceSelectArguments GetSelectArguments () {
return SelectArguments;
}
+
+ internal DataBoundControlAdapter dataBoundControlAdapter;
+ protected override global::System.Web.UI.Adapters.ControlAdapter ResolveAdapter ()
+ {
+ return dataBoundControlAdapter;
+ }
+
}
[TestFixtureTearDown]
c.DoEnsureDataBound ();
}
+ class MyDataBoundControlAdapter : DataBoundControlAdapter
+ {
+ internal bool perform_data_binding_called;
+ protected override void PerformDataBinding (IEnumerable data)
+ {
+ perform_data_binding_called = true;
+ }
+ }
+
+ [Test]
+ public void PerformDataBinding_UsesAdapter ()
+ {
+ MyDataBoundControl c = new MyDataBoundControl ();
+ MyDataBoundControlAdapter a = new MyDataBoundControlAdapter();;
+ c.dataBoundControlAdapter = a;
+ c.DataBind ();
+ Assert.IsTrue (a.perform_data_binding_called, "PerformDataBinding_UsesAdapter");
+ }
+
}
}
#endif
using System.Web;\r
using System.Web.UI;\r
using System.Web.UI.WebControls;\r
+using System.Web.UI.WebControls.Adapters;\r
using System.IO;\r
using System.Drawing;\r
using System.Threading;\r
{\r
ValidateDataSource (dataSource);\r
}\r
+
+ internal HierarchicalDataBoundControlAdapter dataBoundControlAdapter;
+ protected override global::System.Web.UI.Adapters.ControlAdapter ResolveAdapter ()
+ {
+ return dataBoundControlAdapter;
+ }
}\r
\r
[Test]\r
MyHierarchicalDataBoundControl hc = new MyHierarchicalDataBoundControl ();\r
hc.DoValidateDataSource (null);\r
}\r
+
+ class MyHierarchicalDataBoundControlAdapter : HierarchicalDataBoundControlAdapter
+ {
+ internal bool perform_data_binding_called;
+ protected override void PerformDataBinding ()
+ {
+ perform_data_binding_called = true;
+ }
+ }
+
+ [Test]
+ public void PerformDataBinding_UsesAdapter ()
+ {
+ MyHierarchicalDataBoundControl c = new MyHierarchicalDataBoundControl ();
+ MyHierarchicalDataBoundControlAdapter a = new MyHierarchicalDataBoundControlAdapter();;
+ c.dataBoundControlAdapter = a;
+ c.DataBind ();
+ Assert.IsTrue (a.perform_data_binding_called, "PerformDataBinding_UsesAdapter");
+ }
\r
}\r
}\r
WebTest.CopyResource (GetType (), "menuclass.aspx", "menuclass.aspx");\r
WebTest.CopyResource (GetType (), "PostBackMenuTest.aspx", "PostBackMenuTest.aspx");\r
#endif\r
- }\r
-\r
+ }
+
[Test]\r
public void Menu_DefaultProperties ()\r
{\r
[Category ("NunitWeb")]\r
public void Menu_RenderStaticItems () {\r
string RenderedPageHtml, RenderedControlHtml, OriginControlHtml;\r
- RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItems_Vertical)).Run ();\r
- RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
#region OriginControlHtml\r
OriginControlHtml = @"<a href=""#Menu_SkipLink""><img alt=""Skip Navigation Links"" src=""/NunitWeb/WebResource.axd?d=QxfUEifeQdL5PTiZOF8HlA2&t=632900536532114160"" width=""0"" height=""0"" style=""border-width:0px;"" /></a><table id=""Menu"" class=""Menu_2"" cellpadding=""0"" cellspacing=""0"" border=""0"">\r
<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun0"">\r
</tr>\r
</table><a id=""Menu_SkipLink""></a>";\r
#endregion\r
+ RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItems_Vertical)).Run ();\r
+ RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItems_Vertical");\r
- RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItems_Horizontal)).Run ();\r
+ RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItemsWithBaseAdapter_Vertical)).Run ();\r
RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
+ HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItemsWithDefaultAdapter_Vertical");\r
+
#region OriginControlHtml\r
OriginControlHtml = @"<a href=""#Menu_SkipLink""><img alt=""Skip Navigation Links"" src=""/NunitWeb/WebResource.axd?d=QxfUEifeQdL5PTiZOF8HlA2&t=632900536532114160"" width=""0"" height=""0"" style=""border-width:0px;"" /></a><table id=""Menu"" class=""Menu_2"" cellpadding=""0"" cellspacing=""0"" border=""0"">\r
<tr>\r
</tr>\r
</table><a id=""Menu_SkipLink""></a>";\r
#endregion\r
+ RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItems_Horizontal)).Run ();\r
+ RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItems_Horizontal");\r
+ RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItemsWithBaseAdapter_Horizontal)).Run ();\r
+ RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
+ HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItemsWithBaseAdapter_Horizontal");\r
+ }\r
+
+ class MyMenuAdapter : global::System.Web.UI.WebControls.Adapters.MenuAdapter
+ {
+ protected internal override void RenderItem (HtmlTextWriter writer,
+ MenuItem item,
+ int position)
+ {
+ writer.Write ("{");
+ base.RenderItem (writer, item, position);
+ writer.Write ("}");
+ }
+ }\r
+
+ [Test]\r
+ [Category ("NunitWeb")]\r
+ public void Menu_RenderStaticItemsWithAdapter () {
+ string RenderedPageHtml, RenderedControlHtml, OriginControlHtml;\r
+ RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItemsWithAdapter_Vertical)).Run ();
+ RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
+ #region OriginControlHtml\r
+ OriginControlHtml = @"<a href=""#Menu_SkipLink""><img alt=""Skip Navigation Links"" src=""/NunitWeb/WebResource.axd?d=QxfUEifeQdL5PTiZOF8HlA2&t=632900536532114160"" width=""0"" height=""0"" style=""border-width:0px;"" /></a><table id=""Menu"" class=""Menu_2"" cellpadding=""0"" cellspacing=""0"" border=""0"">\r
+ {<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun0"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value')"">one-black</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr><tr>\r
+ <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ {<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun1"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value')"" style=""margin-left:16px;"">two-black-1</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr><tr>\r
+ <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ {<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun2"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value')"" style=""margin-left:32px;"">three-black-1</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr><tr>\r
+ <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ {<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun3"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value\\four-black-1-value')"" style=""margin-left:48px;"">four-black-1</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr>}{<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun4"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value\\four-black-2-value')"" style=""margin-left:48px;"">four-black-2</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr>}\r
+ </table></td>\r
+ </tr>}{<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun5"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value')"" style=""margin-left:32px;"">three-black-2</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr><tr>\r
+ <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ {<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun6"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value\\four-black-3-value')"" style=""margin-left:48px;"">four-black-3</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr>}{<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun7"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value\\four-black-4-value')"" style=""margin-left:48px;"">four-black-4</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr>}\r
+ </table></td>\r
+ </tr>}\r
+ </table></td>\r
+ </tr>}{<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun8"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value')"" style=""margin-left:16px;"">two-black-2</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr><tr>\r
+ <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ {<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun9"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value')"" style=""margin-left:32px;"">three-black-3</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr><tr>\r
+ <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ {<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun10"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value\\four-black-5-value')"" style=""margin-left:48px;"">four-black-5</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr>}{<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun11"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value\\four-black-6-value')"" style=""margin-left:48px;"">four-black-6</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr>}\r
+ </table></td>\r
+ </tr>}{<tr onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun12"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value')"" style=""margin-left:32px;"">three-black-4</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr><tr>\r
+ <td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ {<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun13"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value\\four-black-7-value')"" style=""margin-left:48px;"">four-black-7</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr>}{<tr onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun14"">\r
+ <td><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;width:100%;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value\\four-black-8-value')"" style=""margin-left:48px;"">four-black-8</a></td>\r
+ </tr>\r
+ </table></td>\r
+ </tr>}\r
+ </table></td>\r
+ </tr>}\r
+ </table></td>\r
+ </tr>}\r
+ </table></td>\r
+ </tr>}\r
+</table><a id=""Menu_SkipLink""></a>";\r
+ #endregion\r
+ HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItemsWithAdapter_Vertical");\r
+ RenderedPageHtml = new WebTest (PageInvoker.CreateOnLoad (Menu_RenderStaticItemsWithAdapter_Horizontal)).Run ();\r
+ RenderedControlHtml = HtmlDiff.GetControlFromPageHtml (RenderedPageHtml);\r
+ #region OriginControlHtml\r
+ OriginControlHtml = @"<a href=""#Menu_SkipLink""><img alt=""Skip Navigation Links"" src=""/NunitWeb/WebResource.axd?d=QxfUEifeQdL5PTiZOF8HlA2&t=632900536532114160"" width=""0"" height=""0"" style=""border-width:0px;"" /></a><table id=""Menu"" class=""Menu_2"" cellpadding=""0"" cellspacing=""0"" border=""0"">\r
+ <tr>\r
+ {<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun0""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value')"">one-black</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ <tr>\r
+ {<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun1""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value')"" style=""margin-left:16px;"">two-black-1</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ <tr>\r
+ {<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun2""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value')"" style=""margin-left:32px;"">three-black-1</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ <tr>\r
+ {<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun3""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value\\four-black-1-value')"" style=""margin-left:48px;"">four-black-1</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td>}{<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun4""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-1-value\\four-black-2-value')"" style=""margin-left:48px;"">four-black-2</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td>}\r
+ </tr>\r
+ </table></td>}{<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun5""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value')"" style=""margin-left:32px;"">three-black-2</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ <tr>\r
+ {<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun6""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value\\four-black-3-value')"" style=""margin-left:48px;"">four-black-3</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td>}{<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun7""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-1-value\\three-black-2-value\\four-black-4-value')"" style=""margin-left:48px;"">four-black-4</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td>}\r
+ </tr>\r
+ </table></td>}\r
+ </tr>\r
+ </table></td>}{<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun8""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value')"" style=""margin-left:16px;"">two-black-2</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ <tr>\r
+ {<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun9""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value')"" style=""margin-left:32px;"">three-black-3</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ <tr>\r
+ {<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun10""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value\\four-black-5-value')"" style=""margin-left:48px;"">four-black-5</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td>}{<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun11""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-3-value\\four-black-6-value')"" style=""margin-left:48px;"">four-black-6</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td>}\r
+ </tr>\r
+ </table></td>}{<td onmouseover=""Menu_HoverRoot(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun12""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value')"" style=""margin-left:32px;"">three-black-4</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td><td><table border=""0"" cellpadding=""0"" cellspacing=""0"" width=""100%"">\r
+ <tr>\r
+ {<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun13""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value\\four-black-7-value')"" style=""margin-left:48px;"">four-black-7</a></td>\r
+ </tr>\r
+ </table></td><td style=""width:3px;""></td>}{<td onmouseover=""Menu_HoverStatic(this)"" onmouseout=""Menu_Unhover(this)"" onkeyup=""Menu_Key(this)"" id=""Menun14""><table cellpadding=""0"" cellspacing=""0"" border=""0"" width=""100%"">\r
+ <tr>\r
+ <td style=""white-space:nowrap;""><a class=""Menu_1"" href=""javascript:__doPostBack('Menu','one-black-value\\two-black-2-value\\three-black-4-value\\four-black-8-value')"" style=""margin-left:48px;"">four-black-8</a></td>\r
+ </tr>\r
+ </table></td>}\r
+ </tr>\r
+ </table></td>}\r
+ </tr>\r
+ </table></td>}\r
+ </tr>\r
+ </table></td>}\r
+ </tr>\r
+</table><a id=""Menu_SkipLink""></a>";\r
+ #endregion\r
+ HtmlDiff.AssertAreEqual (OriginControlHtml, RenderedControlHtml, "Menu_RenderStaticItemsWithAdapter_Horizontal");\r
}\r
-\r
+
public static void Menu_RenderStaticItems_Vertical (Page p) {\r
- Menu m = CreateMenuForRenderTests ();\r
+ Menu m = CreateMenuForRenderTests (null);\r
m.StaticDisplayLevels = 4;\r
AddMenuToPage (p, m);\r
}\r
\r
public static void Menu_RenderStaticItems_Horizontal (Page p) {\r
- Menu m = CreateMenuForRenderTests ();\r
+ Menu m = CreateMenuForRenderTests (null);\r
m.Orientation = Orientation.Horizontal;\r
m.StaticDisplayLevels = 4;\r
AddMenuToPage (p, m);\r
}\r
\r
+ public static void Menu_RenderStaticItemsWithBaseAdapter_Vertical (Page p) {\r
+ Menu m = CreateMenuForRenderTests (new MyWebControl.Adapters.MenuAdapter());\r
+ m.StaticDisplayLevels = 4;\r
+ AddMenuToPage (p, m);\r
+ }\r
+\r
+ public static void Menu_RenderStaticItemsWithBaseAdapter_Horizontal (Page p) {\r
+ Menu m = CreateMenuForRenderTests (new MyWebControl.Adapters.MenuAdapter());\r
+ m.Orientation = Orientation.Horizontal;\r
+ m.StaticDisplayLevels = 4;\r
+ AddMenuToPage (p, m);\r
+ }\r
+
+ public static void Menu_RenderStaticItemsWithAdapter_Vertical (Page p) {\r
+ Menu m = CreateMenuForRenderTests (new MyMenuAdapter());\r
+ m.StaticDisplayLevels = 4;\r
+ AddMenuToPage (p, m);\r
+ }\r
+\r
+ public static void Menu_RenderStaticItemsWithAdapter_Horizontal (Page p) {\r
+ Menu m = CreateMenuForRenderTests (new MyMenuAdapter());\r
+ m.Orientation = Orientation.Horizontal;\r
+ m.StaticDisplayLevels = 4;\r
+ AddMenuToPage (p, m);\r
+ }\r
+
private static void AddMenuToPage (Page p, Menu m) {\r
LiteralControl lcb = new LiteralControl (HtmlDiff.BEGIN_TAG);\r
LiteralControl lce = new LiteralControl (HtmlDiff.END_TAG);\r
p.Form.Controls.Add (lcb);\r
p.Form.Controls.Add (m);\r
p.Form.Controls.Add (lce);\r
- }\r
-\r
- private static Menu CreateMenuForRenderTests () {\r
- Menu menu = new Menu ();\r
+ }
+
+ class MyMenu : Menu
+ {
+ internal MyMenu (MyWebControl.Adapters.MenuAdapter adapter) : base ()
+ {
+ menu_adapter = adapter;
+ }
+
+ MyWebControl.Adapters.MenuAdapter menu_adapter;
+ protected override global::System.Web.UI.Adapters.ControlAdapter ResolveAdapter ()
+ {
+ return menu_adapter;
+ }
+ }\r
+\r
+ private static Menu CreateMenuForRenderTests (MyWebControl.Adapters.MenuAdapter adapter) {\r
+ Menu menu = new MyMenu (adapter);\r
menu.ID = "Menu";\r
MenuItem R, N1, N2, SN1, SN2, SN3, SN4;\r
R = new MenuItem ("one-black", "one-black-value");\r
using System.Web.UI;
using System.Web.UI.WebControls;
using MonoTests.stand_alone.WebHarness;
+#if NET_2_0
+using System.Web.UI.WebControls.Adapters;
+#endif
namespace MonoTests.System.Web.UI.WebControls
{
c.Attributes ["HOla"] = "hi";
Assert.AreEqual ("hi", c.Attributes ["hoLA"], "#01");
}
+
+#if NET_2_0
+ class MyWebControlAdapter : WebControlAdapter
+ {
+ protected override void RenderBeginTag (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderBeginTag");
+ }
+
+ protected override void RenderContents (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderContents");
+ }
+
+ protected override void RenderEndTag (HtmlTextWriter w)
+ {
+ w.WriteLine("RenderEndTag");
+ }
+ }
+
+ class MyWebControl : WebControl
+ {
+ WebControlAdapter my_web_control_adapter = new MyWebControlAdapter();
+ protected override global::System.Web.UI.Adapters.ControlAdapter ResolveAdapter ()
+ {
+ return my_web_control_adapter;
+ }
+ }
+
+ [Test]
+ public void Render ()
+ {
+ MyWebControl c = new MyWebControl ();
+ StringWriter sw = new StringWriter ();
+ HtmlTextWriter w = new HtmlTextWriter (sw);
+ c.Render (w);
+ Assert.AreEqual ("RenderBeginTag\nRenderContents\nRenderEndTag\n", sw.ToString (), "Render #1");
+ }
+
+ [Test]
+ public void IsEnabled ()
+ {
+ WebControl parent = new MyWebControl ();
+ WebControl child = new MyWebControl ();
+ parent.Controls.Add (child);
+ Assert.IsTrue (child.IsEnabled, "IsEnabled #1");
+ parent.Enabled = false;
+ Assert.IsFalse (child.IsEnabled, "IsEnabled #2");
+ parent.Enabled = true;
+ child.Enabled = false;
+ Assert.IsFalse (child.IsEnabled, "IsEnabled #3");
+ }
+#endif
}
}
+2008-03-09 Dean Brettle <dean@brettle.com>
+
+ * PageTest.cs: add tests for using a PageAdapter.
+
+ * ControlTest.cs: moved commented out ResolveAdapter_1 test to
+ ../System.Web/AppBrowsersTest.cs. Fixed typo in test name.
+ Added Customcontroladapter.Adapter property for use by AppBrowsersTest.
+
2007-12-31 Vladimir Krasnov <vladimirk@mainsoft.com>
* PageTest.cs: added tests for Response.End/Redirect
Stream strem = ctrl.OpenFile ("~/Fake.tmp");
}
- //// MonoTests.SystemWeb.Framework limitation for Add_browsers - directory include in project
- //[Test]
- //[Category ("NunitWeb")]
- //public void ResolveAdapter_1 ()
- //{
- // WebTest.CopyResource (GetType (), "adapters.browser", "App_Browsers/adapters.browser");
- // WebTest t = new WebTest (PageInvoker.CreateOnInit (ResolveAdapter_Init));
- // string html = t.Run ();
- //}
- //public static void ResolveAdapter_Init (Page p)
- //{
- // Customadaptercontrol ctrl = new Customadaptercontrol ();
- // p.Controls.Add (ctrl);
- // ctrl.Load += new EventHandler (ctrl_Load);
- //}
- //static void ctrl_Load (object sender, EventArgs e)
- //{
- // Assert.IsNotNull (((Customadaptercontrol) sender).ResolveAdapter (), "ResolveAdapter Failed#1");
- // Assert.AreEqual ("Customadapter", ((Customadaptercontrol) sender).ResolveAdapter ().ToString (), "ResolveAdapter Failed#2");
- //}
-
[Test]
[Category ("NunitWeb")]
public void ResolveClientUrl ()
}
#if NET_2_0
[Test]
- public void Contorl_Adapter ()
+ public void Control_Adapter ()
{
MyNC ctr = new MyNC ();
Assert.AreEqual (null, ctr.Adapter (), "Adapter");
#if NET_2_0
public class Customadaptercontrol : Control
{
+ public new ControlAdapter Adapter {
+ get { return base.Adapter; }
+ }
+
public new ControlAdapter ResolveAdapter ()
{
return base.ResolveAdapter ();
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Collections;
+using System.Collections.Specialized;
using System.Net;
+
+
namespace MonoTests.System.Web.UI {
+
class TestPage : Page {
private HttpContext ctx;
WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.PageLifecycleTest.aspx", "PageLifecycleTest.aspx");
WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.PageValidationTest.aspx", "PageValidationTest.aspx");
WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.AsyncPage.aspx", "AsyncPage.aspx");
- WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.AsyncPage.aspx", "AsyncPage.aspx");
+ WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.PageWithAdapter.aspx", "PageWithAdapter.aspx");
WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.RedirectOnError.aspx", "RedirectOnError.aspx");
WebTest.CopyResource (GetType (), "MonoTests.System.Web.UI.WebControls.Resources.ClearErrorOnError.aspx", "ClearErrorOnError.aspx");
#else
WebTest.CopyResource (GetType (), "PageLifecycleTest.aspx", "PageLifecycleTest.aspx");
WebTest.CopyResource (GetType (), "PageValidationTest.aspx", "PageValidationTest.aspx");
WebTest.CopyResource (GetType (), "AsyncPage.aspx", "AsyncPage.aspx");
- WebTest.CopyResource (GetType (), "AsyncPage.aspx", "AsyncPage.aspx");
+ WebTest.CopyResource (GetType (), "PageWithAdapter.aspx", "PageWithAdapter.aspx");
WebTest.CopyResource (GetType (), "RedirectOnError.aspx", "RedirectOnError.aspx");
WebTest.CopyResource (GetType (), "ClearErrorOnError.aspx", "ClearErrorOnError.aspx");
#endif
Assert.AreEqual (1, page.GetValidators ("VG1").Count, "Page_ValidationGroup#5");
Assert.AreEqual (1, page.GetValidators ("VG2").Count, "Page_ValidationGroup#6");
}
+
+ [Test]
+ [Category("NunitWeb")]
+ public void InitOutputCache_UsesAdapter ()
+ {
+ WebTest t = new WebTest ("PageWithAdapter.aspx");
+
+ t.Invoker = PageInvoker.CreateOnLoad (InitOutputCache_UsesAdapter_OnLoad);
+ t.Run ();
+ }
+
+ public static void InitOutputCache_UsesAdapter_OnLoad (Page p)
+ {
+ Assert.IsTrue (p.Response.Cache.VaryByHeaders ["header-from-aspx"],
+ "InitOutputCache_UsesAdapter #1");
+ Assert.IsTrue (p.Response.Cache.VaryByParams ["param-from-aspx"],
+ "InitOutputCache_UsesAdapter #2");
+ Assert.IsTrue (p.Response.Cache.VaryByHeaders ["header-from-adapter"],
+ "InitOutputCache_UsesAdapter #3");
+ Assert.IsTrue (p.Response.Cache.VaryByParams ["param-from-adapter"],
+ "InitOutputCache_UsesAdapter #4");
+ }
+
+ [Test]
+ [Category("NunitWeb")]
+ public void PageStatePersister_UsesAdapter ()
+ {
+ WebTest t = new WebTest ("PageWithAdapter.aspx");
+ t.Invoker = PageInvoker.CreateOnLoad (PageStatePersister_UsesAdapter_OnLoad);
+ t.Run ();
+ }
+
+ public static void PageStatePersister_UsesAdapter_OnLoad (Page p)
+ {
+ TestPageWithAdapter pageWithAdapter = (TestPageWithAdapter) p;
+ Assert.IsTrue (pageWithAdapter.PageStatePersister is TestPersister,
+ "PageStatePersister_UsesAdapter #1");
+ }
+
+ [Test]
+ [Category("NunitWeb")]
+ public void ScriptUsesAdapter ()
+ {
+ WebTest t = new WebTest ("PageWithAdapter.aspx");
+ string html = t.Run ();
+ Assert.IsTrue(html.IndexOf("var theForm = /* testFormReference */document.forms[") != -1, "ScriptUsesAdapter #1");
+ }
+
+ [Test]
+ [Category("NunitWeb")]
+ public void DeterminePostBackMode_UsesAdapter ()
+ {
+ WebTest t = new WebTest ("PageWithAdapter.aspx");
+ t.Run ();
+ t.Request = new FormRequest (t.Response, "form1");
+ t.Invoker = PageInvoker.CreateOnInit(DeterminePostBackMode_UsesAdapter_OnInit);
+ t.Run ();
+ }
+
+ public static void DeterminePostBackMode_UsesAdapter_OnInit (Page p)
+ {
+ HtmlInputHidden h = new HtmlInputHidden();
+ h.ID = "DeterminePostBackModeTestField";
+ p.Controls.Add(h);
+ p.Load += new EventHandler(DeterminePostBackMode_UsesAdapter_OnLoad);
+ }
+
+ public static void DeterminePostBackMode_UsesAdapter_OnLoad(object source, EventArgs args)
+ {
+ Page p = (Page)source;
+ HtmlInputHidden h = (HtmlInputHidden)p.FindControl("DeterminePostBackModeTestField");
+ Assert.AreEqual("DeterminePostBackModeTestValue", h.Value,
+ "DeterminePostBackMode #1");
+ }
#endif
#if NET_2_0
WebTest.Unload ();
}
}
+
+#if NET_2_0
+ class TestAdapter : global::System.Web.UI.Adapters.PageAdapter
+ {
+ public override StringCollection CacheVaryByParams {
+ get {
+ StringCollection paramNames = new StringCollection();
+ paramNames.AddRange (new string[] {"param-from-adapter"});
+ return paramNames;
+ }
+ }
+
+ public override StringCollection CacheVaryByHeaders {
+ get {
+ StringCollection headerNames = new StringCollection();
+ headerNames.AddRange (new string[] {"header-from-adapter"});
+ return headerNames;
+ }
+ }
+
+ PageStatePersister persister;
+ public override PageStatePersister GetStatePersister ()
+ {
+ if (persister == null)
+ persister = new TestPersister(Page);
+ return persister;
+ }
+
+ protected internal override string GetPostBackFormReference (string formId)
+ {
+ return String.Format("/* testFormReference */{0}",
+ base.GetPostBackFormReference (formId));
+ }
+
+ public override NameValueCollection DeterminePostBackMode ()
+ {
+ NameValueCollection origRequestValues = base.DeterminePostBackMode ();
+ if (origRequestValues == null)
+ return null;
+ NameValueCollection requestValues = new NameValueCollection ();
+ requestValues.Add (origRequestValues);
+ requestValues ["DeterminePostBackModeTestField"]
+ = "DeterminePostBackModeTestValue";
+ return requestValues;
+ }
+
+ internal new void RenderPostBackEvent (HtmlTextWriter w,
+ string target,
+ string argument,
+ string softKeyLabel,
+ string text,
+ string postUrl,
+ string accessKey,
+ bool encode)
+ {
+ base.RenderPostBackEvent (w, target, argument, softKeyLabel, text, postUrl,
+ accessKey, encode);
+ }
+
+ }
+
+ class TestPersister : HiddenFieldPageStatePersister
+ {
+ public TestPersister (Page p) : base (p)
+ {
+ }
+ }
+
+ public class TestPageWithAdapter : Page
+ {
+ private global::System.Web.UI.Adapters.PageAdapter page_adapter;
+
+ public TestPageWithAdapter () : base ()
+ {
+ page_adapter = new TestAdapter ();
+ WebTest t = WebTest.CurrentTest;
+ if (t != null)
+ t.Invoke (this);
+ }
+
+ protected override global::System.Web.UI.Adapters.ControlAdapter ResolveAdapter ()
+ {
+ return page_adapter;
+ }
+
+ public new PageStatePersister PageStatePersister {
+ get { return base.PageStatePersister; }
+ }
+
+ }
+#endif
}
--- /dev/null
+//
+// System.Web.HttpBrowserCapabilitiesTest.cs - Unit tests for System.Web.HttpBrowserCapabilities
+//
+// Author:
+// Adar Wesley <adarw@mainsoft.com>
+//
+// Copyright (C) 2007 Mainsoft, Inc (http://www.mainsoft.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+#if NET_2_0
+using System;
+using System.Web;
+using System.Web.UI;
+using System.IO;
+using NUnit.Framework;
+using MonoTests.SystemWeb.Framework;
+using MonoTests.System.Web.UI;
+using System.Text;
+using System.Web.Configuration;
+using System.Threading;
+
+namespace MonoTests.System.Web
+{
+ [TestFixture]
+ [Ignore ("Pending fix for bug 351878")]
+ public class AppBrowsersTest
+ {
+ [TestFixtureSetUp]
+ public void TestFixtureSetUp ()
+ {
+ WebTest.CleanApp();
+ WebTest.CopyResource(typeof(HttpBrowserCapabilitiesTest), "TestCapability.browser",
+ Path.Combine("App_Browsers", "TestCapability.browser"));
+ WebTest.CopyResource (GetType (), "adapters.browser",
+ Path.Combine("App_Browsers", "adapters.browser"));
+ }
+
+ [TestFixtureTearDown]
+ public void TestFixtureTearDown ()
+ {
+ WebTest.CleanApp();
+ }
+
+ [Test]
+ [Category ("NunitWeb")]
+ public void AppBrowsersCapabilities ()
+ {
+ WebTest t = new WebTest (PageInvoker.CreateOnLoad (AppBrowsersCapabilities_OnLoad));
+ t.Request.UserAgent = "testUserAgent";
+ t.Run ();
+ }
+
+ public static void AppBrowsersCapabilities_OnLoad (Page p)
+ {
+ HttpRequest request = p.Request;
+ HttpCapabilitiesBase caps = request.Browser;
+
+ Assert.IsFalse (String.IsNullOrEmpty(caps.Browser), "Browser");
+ Assert.AreEqual ("testUserAgent", request.UserAgent, "AppBrowsersCapabilities #1");
+ Assert.AreEqual ("testUserAgent", caps[""], "AppBrowsersCapabilities #2");
+ Assert.AreEqual ("default", caps["notChanged"], "AppBrowsersCapabilities #3");
+ Assert.AreEqual ("uaInOrig:testUserAgent", caps["capturedInOrigNode"], "AppBrowsersCapabilities #4");
+ Assert.AreEqual ("added", caps["addedInRefNode"], "AppBrowsersCapabilities #5");
+ Assert.AreEqual ("changed", caps["changedInRefNode"], "AppBrowsersCapabilities #6");
+ Assert.AreEqual ("uaInRef:testUserAgent", caps["capturedInRefNode"], "AppBrowsersCapabilities #7");
+ }
+
+ [Test]
+ [Category ("NunitWeb")]
+ public void TagWriter()
+ {
+ WebTest t = new WebTest (PageInvoker.CreateOnLoad (TagWriter_OnLoad));
+ t.Run ();
+ }
+
+ public static void TagWriter_OnLoad (Page p)
+ {
+ HttpRequest request = p.Request;
+ HttpCapabilitiesBase caps = request.Browser;
+
+ Assert.AreEqual (typeof(CustomHtmlTextWriter), caps.TagWriter, "TagWriter #1");
+ }
+
+ [Test]
+ [Category ("NunitWeb")]
+ public void CreateHtmlTextWriter()
+ {
+ WebTest t = new WebTest (PageInvoker.CreateOnLoad (CreateHtmlTextWriter_OnLoad));
+ t.Run ();
+ Assert.IsTrue(t.Response.Body.Contains(@"renderedby=""CustomHtmlTextWriter"""),
+ "CreateHtmlTextWriter #2");
+ }
+
+ public static void CreateHtmlTextWriter_OnLoad (Page p)
+ {
+ HttpRequest request = p.Request;
+ HttpCapabilitiesBase caps = request.Browser;
+
+ Assert.AreEqual (typeof(CustomHtmlTextWriter),
+ caps.CreateHtmlTextWriter(new StringWriter()).GetType(),
+ "CreateHtmlTextWriter #1");
+ }
+
+ [Test]
+ [Category ("NunitWeb")]
+ public void Adapter ()
+ {
+ WebTest t = new WebTest (PageInvoker.CreateOnInit (Adapter_Init));
+ string html = t.Run ();
+ }
+
+ public static void Adapter_Init (Page p)
+ {
+ Customadaptercontrol ctrl = new Customadaptercontrol ();
+ p.Controls.Add (ctrl);
+ ctrl.Load += new EventHandler (Adapter_ctrl_Load);
+ }
+
+ static void Adapter_ctrl_Load (object sender, EventArgs e)
+ {
+ Assert.IsNotNull (((Customadaptercontrol) sender).Adapter, "Adapter Failed#1");
+ Assert.AreEqual ("MonoTests.System.Web.UI.Customadapter", ((Customadaptercontrol) sender).Adapter.ToString (),
+ "Adapter Failed#2");
+ }
+
+ [Test]
+ [Category ("NunitWeb")]
+ public void ResolveAdapter_1 ()
+ {
+ WebTest t = new WebTest (PageInvoker.CreateOnInit (ResolveAdapter_Init));
+ string html = t.Run ();
+ }
+
+ public static void ResolveAdapter_Init (Page p)
+ {
+ Customadaptercontrol ctrl = new Customadaptercontrol ();
+ p.Controls.Add (ctrl);
+ ctrl.Load += new EventHandler (ResolveAdapter_ctrl_Load);
+
+ Customadaptercontrol derivedCtrl = new DerivedCustomadaptercontrol ();
+ p.Controls.Add (derivedCtrl);
+ derivedCtrl.Load += new EventHandler (ResolveAdapter_derivedCtrl_Load);
+ }
+
+ static void ResolveAdapter_ctrl_Load (object sender, EventArgs e)
+ {
+ Assert.IsNotNull (((Customadaptercontrol) sender).ResolveAdapter (), "ResolveAdapter Failed#1");
+ Assert.AreEqual ("MonoTests.System.Web.UI.Customadapter", ((Customadaptercontrol) sender).ResolveAdapter ().ToString (),
+ "ResolveAdapter Failed#2");
+ }
+
+ static void ResolveAdapter_derivedCtrl_Load (object sender, EventArgs e)
+ {
+ Assert.IsNotNull (((Customadaptercontrol) sender).ResolveAdapter (), "ResolveAdapter Failed#2");
+ Assert.AreEqual ("MonoTests.System.Web.UI.Customadapter", ((Customadaptercontrol) sender).ResolveAdapter ().ToString (),
+ "ResolveAdapter Failed#2");
+ }
+ }
+
+ public class CustomHtmlTextWriter : HtmlTextWriter
+ {
+ public CustomHtmlTextWriter (TextWriter tw)
+ : base (tw)
+ {
+ }
+
+ public override void WriteBeginTag(string s)
+ {
+ AddAttribute("renderedby", "CustomHtmlTextWriter");
+ base.WriteBeginTag(s);
+ }
+ }
+
+ class DerivedCustomadaptercontrol : Customadaptercontrol
+ {
+ internal DerivedCustomadaptercontrol () : base ()
+ {
+ }
+ }
+
+
+}
+#endif
+2008-03-09 Dean Brettle <dean@brettle.com>
+
+ * AppBrowsersTest.cs: added. Includes tests for Control.Adapter,
+ Control.ResolveAdapter, Control.TagWriter, and
+ Control.CreateHtmlTextWriter, when using App_Browsers/*.browser files.
+ AppBrowsersTest is currently tagged [Ignore], pending a fix for
+ bug #351878.
+
+ * HttpRuntimeTest.cs: added. Includes test for
+ HttpRuntime.UnloadAppDomain(). Marked [Ignore], pending a fix for
+ bug #351878.
+
2008-01-16 Juraj Skripsky <js@hotfeet.ch>
* HttpRequestTest.cs (TestReferer): added test for invalid referer url.
--- /dev/null
+//
+// System.Web.HttpRuntimeTest.cs - Unit tests for System.Web.HttpRuntime
+//
+// Author:
+// Dean Brettle <dean@brettle.com>
+//
+// Copyright (C) 2007 Dean Brettle
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Web;
+using NUnit.Framework;
+using MonoTests.SystemWeb.Framework;
+using System.Web.UI;
+using System.Threading;
+
+namespace MonoTests.System.Web
+{
+ [TestFixture]
+ public class HttpRuntimeTest
+ {
+
+ [Test]
+ [Category ("NunitWeb")]
+ [Ignore ("Pending fix for bug 351878")]
+ public void UnloadAppDomain ()
+ {
+ WebTest t = new WebTest (PageInvoker.CreateOnLoad (UnloadAppDomain_OnLoad));
+ t.Run ();
+ }
+
+ public static void UnloadAppDomain_OnLoad (Page p)
+ {
+ HttpRuntime.UnloadAppDomain();
+ }
+
+ [Test]
+ [Category ("NunitWeb")]
+ [Ignore ("Pending fix for bug 351878")]
+ [Explicit]
+ public void UnloadAppDomain100Times ()
+ {
+ for (int i = 0; i < 100; i++)
+ UnloadAppDomain();
+ }
+
+ }
+}
+2008-03-09 Dean Brettle <dean@brettle.com>
+
+ * add new resources:
+ PageWithAdapter.aspx for PageTest and PageAdapterTest.
+ TestCapability.browser for AppBrowsersTest.
+
+ * NunitWebResources/adapters.browser,
+ NunitWebResources/AppBrowsersTest.browser: modified to support
+ testing reference nodes with captures, and adapters.
+
+ * NunitWeb/NunitWeb/WebTest.cs: ensure that, during AppDomain
+ unload, no new requests are sent to the app host and any
+ pending requests are completed before the the unload occurs.
+ Also added WebTest.AppUnloaded event that tests can use to wait
+ for the app to unload (e.g. after touching Global.asax), and
+ WebTest.CleanApp() which can be called to restart the app with
+ the a skeleton directory structure. Tests which add files that
+ could effect other tests (e.g. App_Browsers/*.browser files) should
+ call WebTest.CleanApp() during TearDown to return the app to a
+ pristine environment.
+
2008-01-08 Dean Brettle <dean@brettle.com>
* NunitWeb/NunitWeb/WebTest.cs: copy .mdb or .pdb files with
+2008-01-07 Dean Brettle <dean@brettle.com>
+
+ * HtmlAgilityPack/AssemblyInfo.cs: made assembly delay signed so that
+ tests can access System.Web internals now that System.Web is
+ InternalsVisibleTo this assembly.
+
2007-03-06 Vladimir Krasniv <vladimirk@mainsoft.com>
* reference20: added reference test for PageDirectories tests
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
+#if !(TARGET_JVM || TARGET_DOTNET)
+[assembly: AssemblyDelaySign (true)]
+[assembly: AssemblyKeyFile ("../winfx.pub")]
+#endif
using System;
using System.Reflection;
using System.IO;
+using System.Web;
using System.Web.Hosting;
+using System.Web.UI;
+using System.Threading;
namespace MonoTests.SystemWeb.Framework
{
{
if (Request.Url == null)
Request.Url = Invoker.GetDefaultUrl ();
- WebTest newTestInstance = Host.Run (this);
- CopyFrom (newTestInstance);
+ _unloadHandler.StartingRequest();
+ try {
+ WebTest newTestInstance = Host.Run (this);
+ CopyFrom (newTestInstance);
+ } finally {
+ _unloadHandler.FinishedRequest();
+ }
return _response.Body;
}
-
+
private void CopyFrom (WebTest newTestInstance)
{
this._invoker = newTestInstance._invoker;
/// <summary>
/// Unload the web appdomain and delete the temporary application root
/// directory.
- /// Is never called.
/// </summary>
- static void RealUnload ()
+ public static void CleanApp ()
{
#if !TARGET_JVM
if (host != null) {
- AppDomain oldDomain = host.AppDomain;
- if (oldDomain == AppDomain.CurrentDomain)
- {
- Console.Error.WriteLine ("Some nasty runtime bug happened");
- throw new Exception ("Some nasty runtime bug happened");
- }
- host = null;
- AppDomain.CurrentDomain.SetData (HOST_INSTANCE_NAME, null);
- AppDomain.Unload (oldDomain);
+ lock (_appUnloadedSync) {
+ EventHandler handler = new EventHandler(PulseAppUnloadedSync);
+ WebTest.AppUnloaded += handler;
+ WebTest t = new WebTest (PageInvoker.CreateOnLoad (UnloadAppDomain_OnLoad));
+ t.Run ();
+ Monitor.Wait(_appUnloadedSync);
+ WebTest.AppUnloaded -= handler;
+ }
}
if (baseDir != null) {
Directory.Delete (baseDir, true);
}
#endif
}
+
+ private static object _appUnloadedSync = new object();
+
+ private static void PulseAppUnloadedSync(object source, EventArgs args)
+ {
+ lock (_appUnloadedSync)
+ Monitor.PulseAll(_appUnloadedSync);
+ }
+
+ public static void UnloadAppDomain_OnLoad (Page p)
+ {
+ HttpRuntime.UnloadAppDomain();
+ }
public static void Unload () {}
#endif
}
- private static void EnsureHosting ()
+ public static void EnsureHosting ()
{
if (host != null)
return;
host = (MyHost) ApplicationHost.CreateApplicationHost (typeof (MyHost), VIRTUAL_BASE_DIR, baseDir);
AppDomain.CurrentDomain.SetData (HOST_INSTANCE_NAME, host);
host.AppDomain.SetData (HOST_INSTANCE_NAME, host);
+ host.AppDomain.DomainUnload += new EventHandler (_unloadHandler.OnUnload);
#endif
}
+ private static UnloadHandler _unloadHandler = new UnloadHandler();
+
+ public class UnloadHandler : MarshalByRefObject
+ {
+ AutoResetEvent _unloaded = new AutoResetEvent(false);
+
+ int _numRequestsPending = 0;
+ object _syncUnloading = new object();
+ object _syncNumRequestsPending = new object();
+
+ internal void StartingRequest()
+ {
+ // If the app domain is about to unload, wait
+ lock (_syncUnloading)
+ lock (_syncNumRequestsPending)
+ _numRequestsPending++;
+ }
+
+ internal void FinishedRequest()
+ {
+ // Let any unloading continue once there are not requests pending
+ lock (_syncNumRequestsPending) {
+ _numRequestsPending--;
+ if (_numRequestsPending == 0)
+ Monitor.PulseAll(_syncNumRequestsPending);
+ }
+ }
+
+ public void OnUnload (object o, EventArgs args)
+ {
+ // Block new requests from starting
+ lock (_syncUnloading) {
+ // Wait for pending requests to finish
+ lock (_syncNumRequestsPending) {
+ while (_numRequestsPending > 0)
+ Monitor.Wait(_syncNumRequestsPending);
+ }
+ // Clear the host so that it will be created again on the next request
+ AppDomain.CurrentDomain.SetData (HOST_INSTANCE_NAME, null);
+ WebTest.host = null;
+
+ EventHandler handler = WebTest.AppUnloaded;
+ if (handler != null)
+ handler(this, null);
+ }
+ }
+ }
+
+ public static event EventHandler AppUnloaded;
+
#if !TARGET_JVM
const string VIRTUAL_BASE_DIR = "/NunitWeb";
private static string baseDir;
--- /dev/null
+<%@ Page Language="C#" AutoEventWireup="true" inherits="MonoTests.System.Web.UI.TestPageWithAdapter" %>
+<%@ OutputCache duration="1" VaryByHeader="header-from-aspx" VaryByParam="*;param-from-aspx" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" >
+<head runat="server">
+ <title>Untitled Page</title>
+ <script runat="server">
+ </script>
+</head>
+<body>
+ <form id="form1" runat="server">
+ <div>
+
+ </div>
+ </form>
+</body>
+</html>
--- /dev/null
+<browsers>
+ <defaultBrowser id="Default">
+ <capture>
+ </capture>
+ <capabilities>
+ </capabilities>
+ <controlAdapters />
+ </defaultBrowser>
+ <browser id="Default">
+ <identification>
+ <userAgent match="^(?'capturename'.*)$" />
+ </identification>
+ <capture>
+ </capture>
+ <capabilities>
+ <capability name="notChanged" value="default" />
+ <capability name="changedInRefNode" value="unchanged" />
+ <capability name="capturedInDefaultNode" value="ua:${capturename}" />
+ </capabilities>
+ <controlAdapters />
+ </browser>
+</browsers>
-<!--\r
- You can find existing browser definitions at\r
- <windir>\Microsoft.NET\Framework\<ver>\CONFIG\Browsers\r
--->\r
-<browsers>\r
- <!--browser refID="Default">\r
- <controlAdapters>\r
- <adapter \r
- controlType="MonoTests.System.Web.UI.Customadaptercontrol, MonoTests.System.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"\r
- adapterType="MonoTests.System.Web.UI.Customadapter, MonoTests.System.Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" \r
- />\r
- </controlAdapters>\r
- </browser-->\r
-</browsers>
\ No newline at end of file
+<!--
+ You can find existing browser definitions at
+ <windir>\Microsoft.NET\Framework\<ver>\CONFIG\Browsers
+-->
+<browsers>
+ <browser refID="Default">
+ <capture>
+ <userAgent match="^(?'refuacapturename'.*)$" />
+ </capture>
+ <controlAdapters markupTextWriterType="MonoTests.System.Web.CustomHtmlTextWriter, System.Web_test_net_2_0">
+ <adapter
+ controlType="MonoTests.System.Web.UI.Customadaptercontrol, System.Web_test_net_2_0"
+ adapterType="MonoTests.System.Web.UI.Customadapter, System.Web_test_net_2_0"
+ />
+ </controlAdapters>
+ <capabilities>
+ <capability name="addedInRefNode" value="added" />
+ <capability name="changedInRefNode" value="changed" />
+ <capability name="capturedInOrigNode" value="uaInOrig:${capturename}" />
+ <capability name="capturedInRefNode" value="uaInRef:${refuacapturename}" />
+ </capabilities>
+ </browser>
+</browsers>