﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-beyondjay</title><link>http://www.cnblogs.com/beyondjay/</link><description /><language>zh-cn</language><lastBuildDate>Wed, 19 Nov 2008 06:53:50 GMT</lastBuildDate><pubDate>Wed, 19 Nov 2008 06:53:50 GMT</pubDate><ttl>60</ttl><item><title>Permissions for the Event log and registry</title><link>http://www.cnblogs.com/beyondjay/archive/2008/09/11/1289205.html</link><dc:creator>Tony Zhou</dc:creator><author>Tony Zhou</author><pubDate>Thu, 11 Sep 2008 07:24:00 GMT</pubDate><guid>http://www.cnblogs.com/beyondjay/archive/2008/09/11/1289205.html</guid><wfw:comment>http://www.cnblogs.com/beyondjay/comments/1289205.html</wfw:comment><comments>http://www.cnblogs.com/beyondjay/archive/2008/09/11/1289205.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/beyondjay/comments/commentRss/1289205.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/beyondjay/services/trackbacks/1289205.html</trackback:ping><description><![CDATA[Permissions for the Event log are driven through the registry. Each event log has an entry in the registry under the following key:<br />
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog<br />
<br />
To allow the ASP.NET account access to create an event source, you need to have read permission on this and all sub keys, and write permission on the event to which you want to create the event source. Part of your error message says "<span class="txt4" id="_ctl0_MainContent__ctl0_PostForm_ReplyBody"> Inaccessible logs: Security.". Note that "Virtual Server" seems to be another common inaccessible log. This means that for the Security log, the ASP.NET account (MachineName\ASPNET) does not have read access to that key.<br />
<br />
For reasons that I can't explain, the </span><span class="txt4" id="_ctl0_MainContent__ctl0_PostForm_ReplyBody"><font face="Courier New, Courier, Monospace">EventLog.CreateEventSource() </font></span><span class="txt4" id="_ctl0_MainContent__ctl0_PostForm_ReplyBody">method attempts to search Event Sources under all event logs, not just the event log for which you want to create the source. There are two solutions to this. The first, easiest, and most insecure, is just to give read/write access to all event logs for the ASP.NET account. To do this, follow these steps:<br />
</span>
<ol>
    <li><span class="txt4" id="_ctl0_MainContent__ctl0_PostForm_ReplyBody">Start -&gt; Run -&gt; regedit.exe</span></li>
    <li><span class="txt4" id="_ctl0_MainContent__ctl0_PostForm_ReplyBody">Navigate to My Computer &gt; </span>HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog</li>
    <li>Right click this key, select Permissions, and grant the ASPNET account read/write permissions as described above. Note that for the "inaccessible" logs (ie. Security, Virtual Server), you'll also need to grant read access, as permissions have been set to not inherity from the parent key.</li>
    <li>Restart IIS (start -&gt; Run&nbsp; -&gt; iisreset)</li>
    <li>Cause the code line that creates the event source to be executed (<span class="txt4" id="_ctl0_MainContent__ctl0_PostForm_ReplyBody"><font face="Courier New, Courier, Monospace">EventLog.CreateEventSource()</font></span>)<br />
    </li>
</ol>
I don't like this solution because it means that every time a new program that installs its own log (an hence premissions) is installed, the same problem will be encountered.<br />
<br />
The second solution is to bypass the use of the <span class="txt4" id="_ctl0_MainContent__ctl0_PostForm_ReplyBody"><font face="Courier New, Courier, Monospace">EventLog.CreateEventSource()</font></span> code, and write your own Event Source addition code, by directly editing adding it to the registry (using code, not regedit!).<br />
<br />
Each event source appears as a key below the event log name. So an event source named "MediaManager" under the event log "Hoksoft" would appear as HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\Hoksoft\MediaManager.<br />
<br />
An "Event Message File" contains resource strings which format your message content based on parameters. The default .NET message file, EventLogMessages.dll, simply has one parameter "%1", which means that your text is inserted as the message content in its entirity. For further reading on this topic, read <a title="http://www.codeproject.com/dotnet/evtvwr.asp" href="http://www.codeproject.com/dotnet/evtvwr.asp">http://www.codeproject.com/dotnet/evtvwr.asp</a>. Anyway, to avoid message text similar to the following being displayed...<br />
<br />
<font style="color: rgb(0,0,255)" size="2">The description for Event ID ( 0 ) in Source ( MediaManager ) cannot be found. The local computer may not have the necessary registry information or message DLL files to display messages from a remote computer. You may be able to use the /AUXSOURCE= flag to retrieve this description; see Help and Support for details. The following information is part of the event:</font><br />
<br />
..., it's necessary to set the EventMessageFile parameter (registry string value) under the subkey for the Event Source. The default location of this file is in the following directory:&nbsp; c:\WINNT\Microsoft.NET\Framework\v2.0.50727\, where v2.0.50727 is the version of the framework you are using (starting with v1.1.x).<br />
<br />
The following partial snippet of code should contain enough detail to dynamically create the event log source, without requiring access to other event logs. To use this code snippet, ensure that the following permissions are set:<br />
<ol>
    <li>Read access to ASPNET on the EventLog key: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog</li>
    <li>Read + Write (Full Control OK) on the custom Event Log for your application, eg., for event Log "Hoksoft", on key: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog\Hoksoft</li>
    <li>Ensure that the permissions are set to apply to "this key and subkeys".<br />
    </li>
</ol>
<div id="aa" style="background-color: rgb(221,221,221)"><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">string eventLogName = "Hoksoft";</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">string sourceName = "MediaManager";</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">EventLog hoksoftLog;</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">hoksoftLog = new EventLog();</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">hoksoftLog.Log = eventLogName;</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">// set default event source (to be same as event log name) if not passed in</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">if((sourceName == null) || (sourceName.Trim().Length == 0))</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">{</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; sourceName = eventLogName;</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">}</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">hoksoftLog.Source = sourceName;</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">// Extra Raw event data can be added (later) if needed</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">byte[] rawEventData = Encoding.ASCII.GetBytes("");</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">/// Check whether the Event Source exists. It is possible that this may</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">/// raise a security exception if the current process account doesn't</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">/// have permissions for all sub-keys under </span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">/// HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">// Check whether registry key for source exists</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">string keyName = @"SYSTEM\CurrentControlSet\Services\EventLog\" + eventLogName;</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">RegistryKey rkEventSource = Registry.LocalMachine.OpenSubKey(keyName + @"\" + sourceName);</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">// Check whether key exists</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">if(rkEventSource == null)</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">{</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; /// Key does not exist. Create key which represents source</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; Registry.LocalMachine.CreateSubKey(keyName + @"\" + sourceName);</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">}</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">/// Now validate that the .NET Event Message File, EventMessageFile.dll (which correctly</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">/// formats the content in a Log Message) is set for the event source</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">object eventMessageFile = rkEventSource.GetValue("EventMessageFile");</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">/// If the event Source Message File is not set, then set the Event Source message file.</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">if(eventMessageFile == null)</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">{</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; /// Source Event File Doesn't exist - determine .NET framework location,</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; /// for Event Messages file.</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; RegistryKey dotNetFrameworkSettings = Registry.LocalMachine.OpenSubKey(</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; @"SOFTWARE\Microsoft\.NetFramework\");</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; if(dotNetFrameworkSettings != null)</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; {</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; object dotNetInstallRoot = dotNetFrameworkSettings.GetValue(</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "InstallRoot",</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; null,</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; RegistryValueOptions.None);</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(dotNetInstallRoot != null)</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; string eventMessageFileLocation = </span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">dotNetInstallRoot.ToString() + </span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">"v" + </span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">System.Environment.Version.Major.ToString() + "." + </span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">System.Environment.Version.Minor.ToString()&nbsp; + "." + </span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">System.Environment.Version.Build.ToString() + </span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">@"\EventLogMessages.dll";</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /// Validate File exists</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(System.IO.File.Exists(</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">eventMessageFileLocation))</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">/// The Event Message File exists in the anticipated location on the</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">/// machine. Set this value for the new Event Source</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">// Re-open the key as writable</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">rkEventSource = Registry.LocalMachine.OpenSubKey(</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; keyName + @"\" + sourceName,</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; true);</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">// Set the "EventMessageFile" property</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">rkEventSource.SetValue(</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; "EventMessageFile",</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; eventMessageFileLocation,</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; RegistryValueKind.String);</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; }</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; dotNetFrameworkSettings.Close();</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">}</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">rkEventSource.Close();</span><br style="font-family: Courier New,Courier,Monospace" />
<br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">/// Log the message</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">hoksoftLog.WriteEntry(</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; logMessage,</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; type,</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; eventId,</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; 0,</span><br style="font-family: Courier New,Courier,Monospace" />
<span style="font-family: Courier New,Courier,Monospace">&nbsp;&nbsp;&nbsp; rawEventData);</span><br style="font-family: Courier New,Courier,Monospace" />
</div>
<img src ="http://www.cnblogs.com/beyondjay/aggbug/1289205.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/43607/" target="_blank">[新闻]后“开放”平台时代</a><br/><a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻频道</a>&nbsp;<a href="http://space.cnblogs.com/group.htm" target="_blank">小组</a>&nbsp;<a href="http://space.cnblogs.com/q" target="_blank">博问</a>&nbsp;<a href="http://wz.cnblogs.com/" target="_blank">网摘</a>&nbsp;<a href="http://space.cnblogs.com/ing" target="_blank">闪存</a>]]></description></item><item><title>Operating system error 5(error not found)</title><link>http://www.cnblogs.com/beyondjay/archive/2008/09/11/1289021.html</link><dc:creator>Tony Zhou</dc:creator><author>Tony Zhou</author><pubDate>Thu, 11 Sep 2008 04:41:00 GMT</pubDate><guid>http://www.cnblogs.com/beyondjay/archive/2008/09/11/1289021.html</guid><wfw:comment>http://www.cnblogs.com/beyondjay/comments/1289021.html</wfw:comment><comments>http://www.cnblogs.com/beyondjay/archive/2008/09/11/1289021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/beyondjay/comments/commentRss/1289021.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/beyondjay/services/trackbacks/1289021.html</trackback:ping><description><![CDATA[<p>The error I am getting is:<br />
Cannot Open Backup Device 'path_to_file'. Operating system error 5(error not found).</p>
<p>The problem was the service account (Network Service) doesn't have permissions to the specified drive and folder. <br />
After I run the service using my local account, it does work.</p>
<img src ="http://www.cnblogs.com/beyondjay/aggbug/1289021.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/43607/" target="_blank">[新闻]后“开放”平台时代</a><br/><a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻频道</a>&nbsp;<a href="http://space.cnblogs.com/group.htm" target="_blank">小组</a>&nbsp;<a href="http://space.cnblogs.com/q" target="_blank">博问</a>&nbsp;<a href="http://wz.cnblogs.com/" target="_blank">网摘</a>&nbsp;<a href="http://space.cnblogs.com/ing" target="_blank">闪存</a>]]></description></item><item><title>C#集合类(HashTable, Dictionary, ArrayList)与HashTable线程安全 (ZT)</title><link>http://www.cnblogs.com/beyondjay/archive/2008/08/26/1276616.html</link><dc:creator>Tony Zhou</dc:creator><author>Tony Zhou</author><pubDate>Tue, 26 Aug 2008 05:32:00 GMT</pubDate><guid>http://www.cnblogs.com/beyondjay/archive/2008/08/26/1276616.html</guid><wfw:comment>http://www.cnblogs.com/beyondjay/comments/1276616.html</wfw:comment><comments>http://www.cnblogs.com/beyondjay/archive/2008/08/26/1276616.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/beyondjay/comments/commentRss/1276616.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/beyondjay/services/trackbacks/1276616.html</trackback:ping><description><![CDATA[<h2><font face="Verdana">http://www.cnblogs.com/Mainz/archive/2008/04/06/1139117.html</font></h2>
<h2>&nbsp;</h2>
<h2><a id="AjaxHolder_ctl01_TitleUrl" href="http://www.cnblogs.com/Mainz/archive/2008/04/06/1139117.html">C#集合类(HashTable, Dictionary, ArrayList)与HashTable线程安全</a> </h2>
<div>
<p><strong>HashTable</strong><span style="font-family: 宋体">中的</span>key/value<span style="font-family: 宋体">均为</span>object<span style="font-family: 宋体">类型，由包含集合元素的存储桶组成。存储桶是</span> HashTable<span style="font-family: 宋体">中各元素的虚拟子组，与大多数集合中进行的搜索和检索相比，存储桶可令搜索和检索更为便捷。每一存储桶都与一个哈希代码关联，该哈希代码是使用哈希函数生成的并基于该元素的键。</span>HashTable<span style="font-family: 宋体">的优点就在于其索引的方式，速度非常快。如果以任意类型键值访问其中元素会快于其他集合，特别是当数据量特别大的时候，效率差别尤其大。</span></p>
<p>HashTable<span style="font-family: 宋体">的应用场合有：做对象缓存，树递归算法的替代，和各种需提升效率的场合。</span></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">Hashtable sample</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; System.Collections.Hashtable ht </span><span style="color: #000000">=</span>&nbsp;<span style="color: #0000ff">new</span><span style="color: #000000"> System.Collections.Hashtable();<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">--Be careful: Keys can't be duplicated, and can't be null----</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; ht.Add(</span><span style="color: #800080">1</span><span style="color: #000000">, </span><span style="color: #800000">"</span><span style="color: #800000">apple</span><span style="color: #800000">"</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; ht.Add(</span><span style="color: #800080">2</span><span style="color: #000000">, </span><span style="color: #800000">"</span><span style="color: #800000">banana</span><span style="color: #800000">"</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; ht.Add(</span><span style="color: #800080">3</span><span style="color: #000000">, </span><span style="color: #800000">"</span><span style="color: #800000">orange</span><span style="color: #800000">"</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; <br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">Modify item value:</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">if</span><span style="color: #000000">(ht.ContainsKey(</span><span style="color: #800080">1</span><span style="color: #000000">))<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ht[</span><span style="color: #800080">1</span><span style="color: #000000">] </span><span style="color: #000000">=</span>&nbsp;<span style="color: #800000">"</span><span style="color: #800000">appleBad</span><span style="color: #800000">"</span><span style="color: #000000">;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">The following code will return null oValue, no exception</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">object</span><span style="color: #000000"> oValue </span><span style="color: #000000">=</span><span style="color: #000000"> ht[</span><span style="color: #800080">5</span><span style="color: #000000">];&nbsp; <br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; <br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">traversal 1:</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">foreach</span><span style="color: #000000"> (DictionaryEntry de </span><span style="color: #0000ff">in</span><span style="color: #000000"> ht)<br />
<img id="Codehighlighter1_484_563_Open_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_484_563_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_484_563_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_484_563_Closed_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_484_563_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_484_563_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_484_563_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_484_563_Open_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_484_563_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(de.Key);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(de.Value);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">traversal 2:</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; System.Collections.IDictionaryEnumerator d </span><span style="color: #000000">=</span><span style="color: #000000"> ht.GetEnumerator();<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">while</span><span style="color: #000000"> (d.MoveNext())<br />
<img id="Codehighlighter1_682_765_Open_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_682_765_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_682_765_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_682_765_Closed_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_682_765_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_682_765_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_682_765_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_682_765_Open_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_682_765_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">key：{0} value：{1}</span><span style="color: #800000">"</span><span style="color: #000000">, d.Entry.Key, d.Entry.Value);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">Clear items</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; ht.Clear();</span></div>
<p><br />
<strong>Dictionary</strong><span style="font-family: 宋体">和</span>HashTable<span style="font-family: 宋体">内部实现差不多，但前者无需装箱拆箱操作，效率略高一点。<br />
</span></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">Dictionary sample</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; System.Collections.Generic.Dictionary</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">, </span><span style="color: #0000ff">string</span><span style="color: #000000">&gt;</span><span style="color: #000000"> fruits </span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">new</span><span style="color: #000000"> System.Collections.Generic.Dictionary</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">, </span><span style="color: #0000ff">string</span><span style="color: #000000">&gt;</span><span style="color: #000000">();<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; fruits.Add(</span><span style="color: #800080">1</span><span style="color: #000000">, </span><span style="color: #800000">"</span><span style="color: #800000">apple</span><span style="color: #800000">"</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; fruits.Add(</span><span style="color: #800080">2</span><span style="color: #000000">, </span><span style="color: #800000">"</span><span style="color: #800000">banana</span><span style="color: #800000">"</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; fruits.Add(</span><span style="color: #800080">3</span><span style="color: #000000">, </span><span style="color: #800000">"</span><span style="color: #800000">orange</span><span style="color: #800000">"</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">foreach</span><span style="color: #000000"> (</span><span style="color: #0000ff">int</span><span style="color: #000000"> i </span><span style="color: #0000ff">in</span><span style="color: #000000"> fruits.Keys)<br />
<img id="Codehighlighter1_282_348_Open_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_282_348_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_282_348_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_282_348_Closed_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_282_348_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_282_348_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_282_348_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_282_348_Open_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_282_348_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">key：{0} value：{1}</span><span style="color: #800000">"</span><span style="color: #000000">, i, fruits);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp; }</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">if</span><span style="color: #000000"> (fruits.ContainsKey(</span><span style="color: #800080">1</span><span style="color: #000000">))<br />
<img id="Codehighlighter1_385_440_Open_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_385_440_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_385_440_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_385_440_Closed_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_385_440_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_385_440_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_385_440_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_385_440_Open_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_385_440_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(</span><span style="color: #800000">"</span><span style="color: #800000">contain this key.</span><span style="color: #800000">"</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp; }</span></span></div>
<p>&nbsp;</p>
<p><strong>ArrayList</strong><span style="font-family: 宋体">是一维变长数组，内部值为</span>object<span style="font-family: 宋体">类型，效率一般：<br />
</span></p>
<p>&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">ArrayList</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; System.Collections.ArrayList list </span><span style="color: #000000">=</span>&nbsp;<span style="color: #0000ff">new</span><span style="color: #000000"> System.Collections.ArrayList();<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; list.Add(</span><span style="color: #800080">1</span><span style="color: #000000">);</span><span style="color: #008000">//</span><span style="color: #008000">object type</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; list.Add(</span><span style="color: #800080">2</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">for</span><span style="color: #000000"> (</span><span style="color: #0000ff">int</span><span style="color: #000000"> i </span><span style="color: #000000">=</span>&nbsp;<span style="color: #800080">0</span><span style="color: #000000">; i </span><span style="color: #000000">&lt;</span><span style="color: #000000"> list.Count; i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />
<img id="Codehighlighter1_184_227_Open_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_184_227_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_184_227_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_184_227_Closed_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_184_227_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_184_227_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_184_227_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_184_227_Open_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_184_227_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(list[i]);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp; }</span></span></div>
<p><br />
<br />
HashTable<span style="font-family: 宋体">是经过优化的，访问下标的对象先散列过，所以内部是无序散列的，保证了高效率，也就是说，其输出不是按照开始加入的顺序，而</span>Dictionary<span style="font-family: 宋体">遍历输出的顺序，就是加入的顺序，这点与</span>Hashtable<span style="font-family: 宋体">不同。如果一定要排序</span>HashTable<span style="font-family: 宋体">输出，只能自己实现：<br />
<br />
</span></p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">Hashtable sorting</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; System.Collections.ArrayList akeys </span><span style="color: #000000">=</span>&nbsp;<span style="color: #0000ff">new</span><span style="color: #000000"> System.Collections.ArrayList(ht.Keys); </span><span style="color: #008000">//</span><span style="color: #008000">from Hashtable</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; akeys.Sort(); </span><span style="color: #008000">//</span><span style="color: #008000">Sort by leading letter</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #0000ff">foreach</span><span style="color: #000000"> (</span><span style="color: #0000ff">string</span><span style="color: #000000"> skey </span><span style="color: #0000ff">in</span><span style="color: #000000"> akeys)<br />
<img id="Codehighlighter1_207_286_Open_Image" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_207_286_Open_Text').style.display='none'; document.getElementById('Codehighlighter1_207_286_Closed_Image').style.display='inline'; document.getElementById('Codehighlighter1_207_286_Closed_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"><img id="Codehighlighter1_207_286_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('Codehighlighter1_207_286_Closed_Text').style.display='none'; document.getElementById('Codehighlighter1_207_286_Open_Image').style.display='inline'; document.getElementById('Codehighlighter1_207_286_Open_Text').style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top">&nbsp;&nbsp;&nbsp; </span><span id="Codehighlighter1_207_286_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.Write(skey </span><span style="color: #000000">+</span>&nbsp;<span style="color: #800000">"</span><span style="color: #800000">:</span><span style="color: #800000">"</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(ht[skey]);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp; }</span></span></div>
<p>&nbsp; </p>
<p><strong>HashTable</strong><strong><span style="font-family: 宋体">与线程安全</span></strong><span style="font-family: 宋体">：</span></p>
<p><span style="font-family: 宋体">为了保证在多线程的情况下的线程同步访问安全，微软提供了自动线程同步的</span>HashTable: </p>
<p>&nbsp;</p>
<p><span style="font-family: 宋体">如果</span> <span id="highlight_tag">HashTable<span style="font-family: 宋体">要允许并发读但只能一个线程写</span>, <span style="font-family: 宋体">要这么创建</span> <span id="highlight_tag">HashTable<span style="font-family: 宋体">实例</span>:</span></span></p>
<p>&nbsp;</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">&nbsp;&nbsp;&nbsp; </span><span style="color: #008000">//</span><span style="color: #008000">Thread safe HashTable</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp; System.Collections.Hashtable htSyn </span><span style="color: #000000">=</span><span style="color: #000000"> System.Collections.Hashtable.Synchronized(</span><span style="color: #0000ff">new</span><span style="color: #000000"> System.Collections.Hashtable());</span></div>
<p><span style="font-family: 宋体">这样</span>, <span style="font-family: 宋体">如果有多个线程并发的企图写</span>HashTable<span style="font-family: 宋体">里面的</span> item, <span style="font-family: 宋体">则同一时刻只能有一个线程写</span>, <span style="font-family: 宋体">其余阻塞</span>; <span style="font-family: 宋体">对读的线程则不受影响。</span></p>
<p>&nbsp; </p>
<p><span style="font-family: 宋体">另外一种方法就是使用</span>lock<span style="font-family: 宋体">语句，但要</span>lock<span style="font-family: 宋体">的不是</span>HashTable<span style="font-family: 宋体">，而是其</span>SyncRoot<span style="font-family: 宋体">；虽然不推荐这种方法，但效果一样的，因为源代码就是这样实现的</span>:</p>
<div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas,'Courier New',courier,monospace; background-color: #f4f4f4; max-height: 200px">
<div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"><span style="color: #008000">//Thread safe</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> System.Collections.Hashtable htCache = <span style="color: #0000ff">new</span> System.Collections.Hashtable ();</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">&nbsp;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> AccessCache ()</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">{</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    <span style="color: #0000ff">lock</span> ( htCache.SyncRoot )</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    {</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">        htCache.Add ( <span style="color: #006080">"key"</span>, <span style="color: #006080">"value"</span> );</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">&nbsp;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">        <span style="color: #008000">//Be careful: don't use foreach to operation on the whole collection</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">        <span style="color: #008000">//Otherwise the collection won't be locked correctly even though indicated locked</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">        <span style="color: #008000">//--by MSDN</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">}</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">&nbsp;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">&nbsp;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"><span style="color: #008000">//Is equivalent to 等同于 (lock is equivalent to Monitor.Enter and Exit()</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"><span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> AccessCache ()</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">{</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    System.Threading.Monitor.Enter ( htCache.SyncRoot );</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">&nbsp;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    <span style="color: #0000ff">try</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    {</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">        <span style="color: #008000">/* critical section */</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">        htCache.Add ( <span style="color: #006080">"key"</span>, <span style="color: #006080">"value"</span> );</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">&nbsp;</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">        <span style="color: #008000">//Be careful: don't use foreach to operation on the whole collection</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">        <span style="color: #008000">//Otherwise the collection won't be locked correctly even though indicated locked</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">        <span style="color: #008000">//--by MSDN</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">    <span style="color: #0000ff">finally</span></pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    {</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">        System.Threading.Monitor.Exit ( htCache.SyncRoot );</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none">    }</pre>
<pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas,'Courier New',courier,monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none">}</pre>
</div>
</div>
<div id="MySignature">
<p align="right"><span style="color: #999999">(</span><span style="color: #999999; font-family: 宋体">欢迎拍砖，交流，探讨</span><span style="color: #999999">)</span></p>
</div>
</div>
<img src ="http://www.cnblogs.com/beyondjay/aggbug/1276616.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/43606/" target="_blank">[新闻]李彦宏首次表态竞价排名问题:有错能改善莫大焉</a><br/><a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻频道</a>&nbsp;<a href="http://space.cnblogs.com/group.htm" target="_blank">小组</a>&nbsp;<a href="http://space.cnblogs.com/q" target="_blank">博问</a>&nbsp;<a href="http://wz.cnblogs.com/" target="_blank">网摘</a>&nbsp;<a href="http://space.cnblogs.com/ing" target="_blank">闪存</a>]]></description></item><item><title>What is difference between HttpModule and HttpHandler（ZT)</title><link>http://www.cnblogs.com/beyondjay/archive/2008/08/26/1276473.html</link><dc:creator>Tony Zhou</dc:creator><author>Tony Zhou</author><pubDate>Tue, 26 Aug 2008 02:58:00 GMT</pubDate><guid>http://www.cnblogs.com/beyondjay/archive/2008/08/26/1276473.html</guid><wfw:comment>http://www.cnblogs.com/beyondjay/comments/1276473.html</wfw:comment><comments>http://www.cnblogs.com/beyondjay/archive/2008/08/26/1276473.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/beyondjay/comments/commentRss/1276473.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/beyondjay/services/trackbacks/1276473.html</trackback:ping><description><![CDATA[<p><em><font face="Times New Roman" size="3">HTTP handlers are the end point objects in ASP.NET pipeline and an HTTP Handler essentially processes the request and produces the response. For example an ASP.NET Page is an HTTP Handler. <br />
<br />
HTTP Modules are objects which also participate the pipeline but they work before and after the HTTP Handler does its job, and produce additional services within the pipeline (for example associating session within a request before HTTP handler executes, and saving the session state after HTTP handler has done its job, is basically done by an HTTP module, SessionStateModule)<br />
<br />
<br />
HTTP handlers <br />
<br />
HTTP handlers are the .NET components that implement the System.Web.IHttpHandler interface. Any class that implements the IHttpHandler interface can act as a target for the incoming HTTP requests. HTTP handlers are somewhat similar to ISAPI extensions. One difference between HTTP handlers and ISAPI extensions is that HTTP handlers can be called directly by using their file name in the URL, similar to ISAPI extensions. <br />
<br />
<br />
HTTP Modules<br />
<br />
<br />
HTTP modules are .NET components that implement the System.Web.IHttpModule interface. These components plug themselves into the ASP.NET request processing pipeline by registering themselves for certain events. Whenever those events occur, ASP.NET invokes the interested HTTP modules so that the modules can play with the request. </font></em></p>
<p><em><font face="Times New Roman" size="3"></font></em>&nbsp;</p>
<p><em><font face="Times New Roman" size="3"><font face="Verdana">http://www.dotnetspider.com/forum/158666-What-difference-between-HttpModule-HttpHandler.aspx</font></p>
<p><br />
</p>
</font></em>
<img src ="http://www.cnblogs.com/beyondjay/aggbug/1276473.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/43606/" target="_blank">[新闻]李彦宏首次表态竞价排名问题:有错能改善莫大焉</a><br/><a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻频道</a>&nbsp;<a href="http://space.cnblogs.com/group.htm" target="_blank">小组</a>&nbsp;<a href="http://space.cnblogs.com/q" target="_blank">博问</a>&nbsp;<a href="http://wz.cnblogs.com/" target="_blank">网摘</a>&nbsp;<a href="http://space.cnblogs.com/ing" target="_blank">闪存</a>]]></description></item><item><title>HTTP Handlers and HTTP Modules in ASP.NET(ZT)</title><link>http://www.cnblogs.com/beyondjay/archive/2008/08/26/1276402.html</link><dc:creator>Tony Zhou</dc:creator><author>Tony Zhou</author><pubDate>Tue, 26 Aug 2008 01:44:00 GMT</pubDate><guid>http://www.cnblogs.com/beyondjay/archive/2008/08/26/1276402.html</guid><wfw:comment>http://www.cnblogs.com/beyondjay/comments/1276402.html</wfw:comment><comments>http://www.cnblogs.com/beyondjay/archive/2008/08/26/1276402.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/beyondjay/comments/commentRss/1276402.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/beyondjay/services/trackbacks/1276402.html</trackback:ping><description><![CDATA[<p><font face="Verdana"><a href="http://www.15seconds.com/issue/020417.htm">http://www.15seconds.com/issue/020417.htm</a></font></p>
<p>&nbsp;</p>
<p class="MsoNormal" style="margin-bottom: 0pt; line-height: normal"><strong><span style="font-size: 12pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">Introduction</span></strong><span style="font-size: 12pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'"> <o:p></o:p></span></p>
<p>&nbsp;</p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">In the Internet world, Web servers serve resources that have been put on the Internet and provide other services like security, logging, etc. <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">At the beginning of the Internet era, clients' needs were very limited; .htm files were often satisfactory. As time passed, however, clients' requirements extended beyond the functionality contained in .htm files or static files. <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">Developers needed a way to extend or complement the functionality of Web servers. Web server vendors devised different solutions, but they all followed a common theme: "Plug some component into the Web server". All Web server complement technologies allowed developers to create and plug in components for enhancing Web server functionality. Microsoft came up with ISAPI (Internet Server API); Netscape came up with NSAPI (Netscape Server API), etc. <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">ISAPI is an important technology that allows us to enhance the capabilities of an ISAPI-compliant Web server (IIS is an ISAPI-compliant Web server). The following components serve this purpose: <o:p></o:p></span></p>
<ul type="disc">
    <li class="MsoNormal" style="color: black; line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt"><span style="font-size: 10pt; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">ISAPI Extensions <o:p></o:p></span></li>
    <li class="MsoNormal" style="color: black; line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-list: l1 level1 lfo1; tab-stops: list 36.0pt"><span style="font-size: 10pt; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">ISAPI Filters <o:p></o:p></span></li>
</ul>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">ISAPI extensions are implemented by using Win32 DLLs. You can think of an ISAPI extension as a normal application. ISAPI extensions are the target of http requests. That means you must call them to activate them. For example, the following URL calls the store.dll ISAPI extension and passes two values to it: <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">http://www.myownwebsite.com/Store.dll?sitename=15seconds&amp;location=USA <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">Think of an ISAPI filter as just that: a filter. It sits between your Web server and the client. Every time a client makes a request to the server, it passes through the filter. <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">Clients do not specifically target the filter in their requests, rather, clients simply send requests to the Web server, and then the Web server passes that request to the interested filters. <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">Filters can then modify the request, perform some logging operations, etc. <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">It was very difficult to implement these components because of the complexities involved. One had to use C/C++ to develop these components, and for many, development in C/C++ is a pain. <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">So what does ASP.NET offer to harness this functionality? ASP.NET offers HttpHandlers and HttpModules. <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">Before going into the details of these components, it is worth looking at the flow of http requests as it passes through the HTTP modules and HTTP handlers. <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><strong><span style="font-size: 12pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-bidi-font-size: 11.0pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">Setting up the Sample Applications</span></strong><span style="font-size: 12pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'"> <o:p></o:p></span></p>
<p class="MsoNormal" style="line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto"><span style="font-size: 10pt; color: black; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">I have created the following C# projects, which demonstrate different components of the application. <o:p></o:p></span></p>
<ul type="disc">
    <li class="MsoNormal" style="color: black; line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt"><span style="font-size: 10pt; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">NewHandler (HTTP handler) <o:p></o:p></span></li>
    <li class="MsoNormal" style="color: black; line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt"><span style="font-size: 10pt; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">Webapp (Demonstrates HTTP handler) <o:p></o:p></span></li>
    <li class="MsoNormal" style="color: black; line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt"><span style="font-size: 10pt; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">SecurityModules (HTTP module) <o:p></o:p></span></li>
    <li class="MsoNormal" style="color: black; line-height: normal; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto; mso-list: l0 level1 lfo2; tab-stops: list 36.0pt"><span style="font-size: 10pt; font-family: 'Arial, Helvetica,MS Sans Serif','serif'; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">Webapp2 (Demonstrated HTTP module) <o:p></o:p></span></li>
</ul>
<p class="MsoNormal"><o:p>&nbsp;</p>
<p>To install the applications:
<p>
<ul>
    <li>Extract all the code from the <a href="http://www.15seconds.com/files/020417.zip">attached zip file</a>.</li>
    <li>Create two virtual directories named webapp and webapp2; point these directories to the actual physical folders for the Webapp and Webapp2 web applications.</li>
    <li>Copy the Newhandler.dll file from the NewHandler project into the bin directory of webapp web application.</li>
    <li>Copy the SecurityModules.dll file from the SecurityModules project into the bin directory of webapp2 web application. </li>
</ul>
<p>
<p><span class="clsTitle">ASP.NET Request Processing</span>
<p><span class="clsBlurb">
<p>ASP.NET request processing is based on a pipeline model in which ASP.NET passes http requests to all the modules in the pipeline. Each module receives the http request and has full control over it. The module can play with the request in any way it sees fit. Once the request passes through all of the HTTP modules, it is eventually served by an HTTP handler. The HTTP handler performs some processing on it, and the result again passes through the HTTP modules in the pipeline.
<p>The following figure describes this flow.
<p><img src="http://www.15seconds.com/graphics/issue/020417_01.jpg"  alt="" />
<p>Notice that during the processing of an http request, only one HTTP handler will be called, whereas more than one HTTP modules can be called.
<p></span>
<p><span class="clsTitle">Http Handlers</span>
<p><span class="clsBlurb">
<p>HTTP handlers are the .NET components that implement the System.Web.IHttpHandler interface. Any class that implements the IHttpHandler interface can act as a target for the incoming HTTP requests. HTTP handlers are somewhat similar to ISAPI extensions. One difference between HTTP handlers and ISAPI extensions is that HTTP handlers can be called directly by using their file name in the URL, similar to ISAPI extensions.
<p>HTTP handlers implement the following methods.
<p>
<table border="1">
    <tr>
            <td><strong>Method Name</strong></td>
            <td><strong>Description</strong></td>
        </tr>
        <tr>
            <td>ProcessRequest</td>
            <td>This method is actually the heart of all http handlers. This method is called to process http requests. </td>
        </tr>
        <tr>
            <td>IsReusable</td>
            <td>This property is called to determine whether this instance of http handler can be reused for fulfilling another requests of the same type. HTTP handlers can return either true or false in order to specify whether they can be reused.</td>
        </tr>
    </table>
<p>These classes can be mapped to http requests by using the web.config or machine.config file. Once that is done, ASP.NET will instantiate http handler whenever the corresponding request comes in. We will see how to specify all of these details in web.config and/or machine.config files.
<p>ASP.NET also supports the creation of http handlers by means of the IHttpHandlerFactory interface. ASP.NET provides the capability of routing http requests to an object of the class that implements the IHttpHandlerFactory interface. Here, ASP.NET utilizes the Factory design pattern. This pattern provides an interface for creating families of related objects without specifying their concrete classes. In simple terms, you can consider such a class as a factory that creates http handler objects depending on the parameters passed to it. We don't have to specify a particular http handler class to instantiate; http handler factory takes care of it. The benefit of this is if in the future the implementation of the object that implements the IHttpHandler interface changes, the consuming client is not affected as long as the interface remains the same.
<p>These are following methods in IHttpHandlerFactory interface:
<p>
<table border="1">
    <tr>
            <td><strong>Method Name</strong></td>
            <td><strong>Description</strong></td>
        </tr>
        <tr>
            <td>GetHandler</td>
            <td>This method is responsible for creating the appropriate handler and returns the reference out to the calling code (the ASP.NET runtime). Handler object returned by this method should implement the IHttpHandler interface.</td>
        </tr>
        <tr>
            <td>ReleaseHandler</td>
            <td>This method is responsible for releasing the http handler once request processing is complete. The implementation of the factory decides what it should do. Factory implementation can either actually destroy the instance or return it to a pool for future requests.</td>
        </tr>
    </table>
<p></span>
<p><span class="clsTitle">Registering HTTP Handlers and HTTP Handler Factories in Configuration Files</span>
<p><span class="clsBlurb">
<p>ASP.NET maintains its configuration information in the following configuration files:
<p>
<ul>
    <li>machine.config</li>
    <li>web.config </li>
</ul>
<p>machine.config file contains the configuration settings that apply to all the Web applications installed on that box.
<p>web.config file is specific to each Web application. Each Web application can have its own web.config file. Any sub directory of a Web application may have its own web.config file; this allows them to override the settings imposed by the parent directories.
<p>We can use &lt;httpHandlers&gt; and &lt;add&gt; nodes for adding HTTP handlers to our Web applications. In fact the handlers are listed with &lt;add&gt; nodes in between &lt;httpHandlers&gt; and &lt;/httpHandlers&gt; nodes. Here is a generic example of adding an HTTP handler:
<pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
&lt;httpHandlers&gt;
&lt;add verb="supported http verbs" path="path" type="namespace.classname, assemblyname" /&gt;
&lt;httpHandlers&gt;
</font>
</pre>
<p class="MsoNormal">In the above XML, </p>
<p>
<ul>
    <li>The verb attribute specifies the HTTP verbs supported by the handler. If the handler supports all of the HTTP verbs, simply use "*", otherwise list the supported verbs in a comma separated list. So if your handler supports only HTTP GET and POST, then verb attribute will be "GET, POST".</li>
    <li>The path attribute specifies the path or wildcard specification of the files for which this handler will be invoked. For example, if you want your handler to be called only when test.xyz file is requested, then the path attribute will contain "test.xyz"; similarly if you want your handler called for any file having .xyz extension, the path attribute will contain "*.xyz".</li>
    <li>The <em>type</em> attribute specifies the actual type of the handler or handler factory in the form of a combination of namespace, class name and assembly name. ASP.NET runtime first searches the assembly DLL in the application's bin directory and then searches in the Global Assembly Cache (GAC). </li>
</ul>
<p></span>
<p><span class="clsTitle">Use of HTTP Handlers by the ASP.NET Runtime</span>
<p><span class="clsBlurb">
<p>Believe it or not, ASP.NET uses HTTP handlers for implementing a lot of its own functionality. ASP.NET uses handlers for processing .aspx, .asmx, .soap and other ASP.NET files.
<p>The following is the snippet from the machine.config file:
<pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
&lt;httpHandlers&gt;
&lt;add verb="*" path="trace.axd" type="System.Web.Handlers.TraceHandler"/&gt;
&lt;add verb="*" path="*.aspx" type="System.Web.UI.PageHandlerFactory"/&gt;
&lt;add verb="*" path="*.ashx" type="System.Web.UI.SimpleHandlerFactory"/&gt;
&lt;add verb="*" path="*.config" type="System.Web.HttpForbiddenHandler"/&gt;
&lt;add verb="GET,HEAD" path="*" type="System.Web.StaticFileHandler"/&gt;
. . . . . .
. . . . . .
&lt;/httpHandlers&gt;
</font>
</pre>
<p class="MsoNormal">You can see in the above configuration that all the requests for .aspx files are processed by the System.Web.UI.PageHandlerFactory class. Similarly all the requests for .config and other files, which should not be directly accessible to the clients, are handled by the System.Web.HttpForbiddenHandler class. As you might have already guessed, this class simply returns an error to the client stating that these kinds of files are not served. </p>
<p></span>
<p><span class="clsTitle">Implementing HTTP Handlers</span>
<p><span class="clsBlurb">
<p>Now we will see how to implement an HTTP handler. So what should our new handler do? Well, as I stated above, handlers are mostly used for adding new functionalities to Web servers; therefore, we will create a handler that handles new types of files, files that have a .15seconds extension. Once we implement this handler and register it in the web.config file of our Web application, all requests for .15seconds files will be handled by this new handler.
<p>You might be thinking about the use of such a handler. Well, what if you want to introduce a new kind of server scripting language or dynamic server file such as asp, aspx? You can write your own handler for this. Similarly, what will you do if you want to run Java servlets, JSPs and other server side Java components on IIS? One way of doing this is to install some ISAPI extension like Allaire or Macromedia Jrun. Or you can write your own HTTP handler. Although it is a difficult task for third-party vendors like Allaire and Macromedia, it is a very attractive option because their HTTP handlers will have access to all the new functionalities exposed by the ASP.NET runtime.
<p>Steps involved in implementing our HTTP handler are as follows:
<ol>
    <li>Write a class which implements IHttpHandler interface</li>
    <li>Register this handler in web.config or machine.config file.</li>
    <li>Map the file extension (.15seconds) to ASP.NET ISAPI extension DLL (aspnet_isapi.dll) in Internet Services Manager. </li>
</ol>
<p class="MsoNormal"><strong>Step1</strong><br />
Create a new C# Class Library project in Visual Studio.NET and name it "MyHandler". Visual Studio.NET will automatically add a class named "Class1.cs" into the project. Rename it "NewHandler"; open this class in the code window and change the class name and constructor name to "NewHandler". </p>
<p>The following is the code for the NewHandler class.
<pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
using System;
using System.Web;
namespace MyHandler
{
/// &lt;summary&gt;
/// Summary description for NewHandler.
/// &lt;/summary&gt;
public class NewHandler : IHttpHandler
{
public NewHandler()
{
//
// TODO: Add constructor logic here
//
}
#region Implementation of IHttpHandler
public void ProcessRequest(System.Web.HttpContext context)
{
HttpResponse objResponse = context.Response ;
objResponse.Write("&lt;html&gt;&lt;body&gt;&lt;h1&gt;Hello 15Seconds   Reader ") ;
objResponse.Write("&lt;/body&gt;&lt;/html&gt;") ;
}
public bool IsReusable
{
get
{
return true;
}
}
#endregion
}
}
</font>
</pre>
<p class="MsoNormal">As you can see in the ProcessRequest method, the HTTP handler has access to all ASP.NET intrinsic objects passed to it in its parameter through the System.Web.HttpContext object. Implementing the ProcessRequest method is simply extracting the HttpResponse object from the context object and then sending some HTML out to the client. Similarly, IsReusable returns true to designate that this handler can be reused for processing the other HTTP requests. </p>
<p>Let's compile it and place it in the bin directory of the webapp virtual directory.
<p><strong>Step 2</strong><br />
Register this handler by adding the following text in the web.config file:
<pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
&lt;httpHandlers&gt;
&lt;add verb="*" path="*.15seconds" type="MyHandler.NewHandler,MyHandler"/&gt;
&lt;/httpHandlers&gt;
</pre>
<p class="MsoNormal"></font><strong>Step 3</strong><br />
Since we are creating a handler for handling files of a new extension, we also need to tell IIS about this extension and map it to ASP.NET. If we don't perform this step and try to access the <strong>Hello.15seconds</strong> file, IIS will simply return the file rather than pass it to ASP.NET runtime. As a consequence, the HTTP handler will not be called. </p>
<p>Launch the <strong>Internet Services Manager</strong> tool, right click on <strong>Default Web Site</strong>, select <strong>Properties</strong>, go to <strong>Home Directory</strong> tab and press <strong>Configuration</strong> button. This will popup <strong>Application Configuration</strong> dialog. Click <strong>Add</strong> button and fill the <strong>Executable</strong> field with the path to the aspnet_isapi.dll file and fill .15seconds in the <strong>Extension</strong> field. Leave the other fields as is; the dialog box should look as follows:
<p><img src="http://www.15seconds.com/graphics/issue/020417_02.jpg"  alt="" />
<p>Close the <strong>Application Configuration</strong> and <strong>Default Web Site Properties</strong> dialog boxes by pressing the <strong>OK</strong> button.
<p>Now we are good to go. Launch Internet Explorer and go to the following url:
<p>http://localhost/webapp/hello.15seconds
<p>You should see the following page:
<p><img src="http://www.15seconds.com/graphics/issue/020417_03.jpg"  alt="" />
<p></span>
<p><span class="clsTitle">Session State in HTTP Handlers</span>
<p><span class="clsBlurb">
<p>Maintaining session state is one of the most common tasks that Web applications perform. HTTP handlers also need to have access to the session state. But session state is not enabled by default for HTTP handlers. In order to read and/or write session data, HTTP handlers are required to implement one of the following interfaces:
<ul>
    <li>IRequiresSessionState</li>
    <li>IReadOnlySessionState. </li>
</ul>
<p>An HTTP handler should implement the IRequiresSessionState interface when it requires read-write access to the session data. If a handler only needs read access to session data, then it should only implement the IReadOnlySessionState interface.
<p>Both of these interfaces are just marker interfaces and do not contain any methods. So if we want to enable session state for our NewHandler handler, then declare the NewHandler class as followed:
<pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
public class NewHandler : IHttpHandler, IRequiresSessionState
</font>
</pre>
<p class="MsoNormal"></span></p>
<p><span class="clsTitle">HTTP Modules</span>
<p><span class="clsBlurb">
<p>HTTP modules are .NET components that implement the System.Web.IHttpModule interface. These components plug themselves into the ASP.NET request processing pipeline by registering themselves for certain events. Whenever those events occur, ASP.NET invokes the interested HTTP modules so that the modules can play with the request.
<p>An HTTP module is supposed to implement the following methods of the IHttpModule interface:
<p>
<table border="1">
    <tr>
            <td><strong>Method Name</strong></td>
            <td><strong>Description</strong></td>
        </tr>
        <tr>
            <td>Init</td>
            <td>This method allows an HTTP module to register its event handlers to the events in the HttpApplication object.</td>
        </tr>
        <tr>
            <td>Dispose</td>
            <td>This method gives HTTP module an opportunity to perform any clean up before the object gets garbage collected.</td>
        </tr>
    </table>
<p>An HTTP module can register for the following events exposed by the System.Web.HttpApplication object.
<p>
<table border="1">
    <tr>
            <td><strong>Event Name</strong></td>
            <td><strong>Description</strong></td>
        </tr>
        <tr>
            <td>AcquireRequestState</td>
            <td>This event is raised when ASP.NET runtime is ready to acquire the Session state of the current HTTP request. </td>
        </tr>
        <tr>
            <td>AuthenticateRequest</td>
            <td>This event is raised when ASP.NET runtime is ready to authenticate the identity of the user. </td>
        </tr>
        <tr>
            <td>AuthorizeRequest</td>
            <td>This event is raised when ASP.NET runtime is ready to authorize the user for the resources user is trying to access. </td>
        </tr>
        <tr>
            <td>BeginRequest</td>
            <td>This event is raised when ASP.NET runtime receives a new HTTP request. </td>
        </tr>
        <tr>
            <td>Disposed</td>
            <td>This event is raised when ASP.NET completes the processing of HTTP request. </td>
        </tr>
        <tr>
            <td>EndRequest</td>
            <td>This event is raised just before sending the response content to the client. </td>
        </tr>
        <tr>
            <td>Error</td>
            <td>This event is raised when an unhandled exception occurs during the processing of HTTP request. </td>
        </tr>
        <tr>
            <td>PostRequestHandlerExecute</td>
            <td>This event is raised just after HTTP handler finishes execution. </td>
        </tr>
        <tr>
            <td>PreRequestHandlerExecute</td>
            <td>This event is raised just before ASP.NET begins executing a handler for the HTTP request. After this event, ASP.NET will forward the request to the appropriate HTTP handler. </td>
        </tr>
        <tr>
            <td>PreSendRequestContent</td>
            <td>This event is raised just before ASP.NET sends the response contents to the client. This event allows us to change the contents before it gets delivered to the client. We can use this event to add the contents, which are common in all pages, to the page output. For example, a common menu, header or footer. </td>
        </tr>
        <tr>
            <td>PreSendRequestHeaders</td>
            <td>This event is raised just before ASP.NET sends the HTTP response headers to the client. This event allows us to change the headers before they get delivered to the client. We can use this event to add cookies and custom data into headers. </td>
        </tr>
        <tr>
            <td>ReleaseRequestState</td>
            <td>This event is raised after ASP.NET finishes executing all request handlers.
            <tr>
                <td>ResolveRequestCache</td>
                <td>This event is raised to determine whether the request can be fulfilled by returning the contents from the Output Cache. This depends on how the Output Caching has been setup for your web application. </td>
            </tr>
            <tr>
                <td>UpdateRequestCache</td>
                <td>This event is raised when ASP.NET has completed processing the current HTTP request and the output contents are ready to be added to the Output Cache. This depends on how the Output Caching has been setup for your Web application. </td>
            </tr>
        </table>
    <p>Apart from these events, there are four more events that we can use. We can hook up to these events by implementing the methods in the global.asax file of our Web application.
    <p>These events are as follows:
    <p>
    <ul>
        <li>Application_OnStart<br />
        This event is raised when the very first request arrives to the Web application.</li>
        <li>Application_OnEnd<br />
        This event is raised just before the application is going to terminate.</li>
        <li>Session_OnStart<br />
        This event is raised for the very first request of the user's session.</li>
        <li>Session_OnEnd<br />
        This event is raised when the session is abandoned or expired. </li>
    </ul>
    <p></span>
    <p><span class="clsTitle">Registering HTTP Modules in Configuration Files</span>
    <p><span class="clsBlurb">
    <p>Once an HTTP module is built and copied into the bin directory of our Web application or copied into the Global Assembly Cache, then we will register it in either the web.config or machine.config file.
    <p>We can use &lt;httpModules&gt; and &lt;add&gt; nodes for adding HTTP modules to our Web applications. In fact the modules are listed by using &lt;add&gt; nodes in between &lt;httpModules&gt; and &lt;/httpModules&gt; nodes.
    <p>Since configuration settings are inheritable, the child directories inherit configuration settings of the parent directory. As a consequence, child directories might inherit some unwanted HTTP modules as part of the parent configuration; therefore, we need a way to remove those unwanted modules. We can use the &lt;remove&gt; node for this.
    <p>If we want to remove all of the inherited HTTP modules from our application, we can use the &lt;clear&gt; node.
    <p>The following is a generic example of adding an HTTP module:
    <pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
    &lt;httpModules&gt;
    &lt;add type="classname, assemblyname" name="modulename"  /&gt;
    &lt;httpModules&gt;
    </font>
    </pre>
    <p class="MsoNormal">The following is a generic example of removing an HTTP module from your application. </p>
    <pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
    &lt;httpModules&gt;
    &lt;remove name="modulename"  /&gt;
    &lt;httpModules&gt;
    </font>
    </pre>
    <p class="MsoNormal">In the above XML, </p>
    <p>
    <ul>
        <li>The type attribute specifies the actual type of the HTTP module in the form of class and assembly name.</li>
        <li>The name attribute specifies the friendly name for the module. This is the name that will be used by other applications for identifying the HTTP module. </li>
    </ul>
    <p></span>
    <p><span class="clsTitle">Use of HTTP Modules by the ASP.NET Runtime</span>
    <p><span class="clsBlurb">
    <p>ASP.NET runtime uses HTTP modules for implementing some special features. The following snippet from the machine.config file shows the HTTP modules installed by the ASP.NET runtime.
    <pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
    &lt;httpModules&gt;
    &lt;add name="OutputCache" type="System.Web.Caching.OutputCacheModule"/&gt;
    &lt;add name="Session" type="System.Web.SessionState.SessionStateModule"/&gt;
    &lt;add name="WindowsAuthentication"
    type="System.Web.Security.WindowsAuthenticationModule"/&gt;
    &lt;add name="FormsAuthentication"
    type="System.Web.Security.FormsAuthenticationModule"/&gt;
    &lt;add name="PassportAuthentication"
    type="System.Web.Security.PassportAuthenticationModule"/&gt;
    &lt;add name="UrlAuthorization"
    type="System.Web.Security.UrlAuthorizationModule"/&gt;
    &lt;add name="FileAuthorization"
    type="System.Web.Security.FileAuthorizationModule"/&gt;
    &lt;/httpModules&gt;
    </font>
    </pre>
    <p class="MsoNormal">All of the above HTTP modules are used by ASP.NET to provide services like authentication and authorization, session management and output caching. Since these modules have been registered in machine.config file, these modules are automatically available to all of the Web applications. </p>
    <p></span>
    <p><span class="clsTitle">Implementing an HTTP Module for Providing Security Services</span>
    <p><span class="clsBlurb">
    <p>Now we will implement an HTTP module that provides security services for our Web application. Our HTTP module will basically provide a custom authentication service. It will receive authentication credentials in HTTP request and will determine whether those credentials are valid. If yes, what roles are the user associated with? Through the User.Identity object, it will associate those roles that are accessible to our Web application pages to the user's identity.
    <p>Following is the code of our HTTP module.
    <pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
    using System;
    using System.Web;
    using System.Security.Principal;
    namespace SecurityModules
    {
    /// &lt;summary&gt;
    /// Summary description for Class1.
    /// &lt;/summary&gt;
    public class CustomAuthenticationModule : IHttpModule
    {
    public CustomAuthenticationModule()
    {
    }
    public void Init(HttpApplication r_objApplication)
    {
    // Register our event handler with Application object.
    r_objApplication.AuthenticateRequest +=
    new EventHandler(this.AuthenticateRequest) ;
    }
    public void Dispose()
    {
    // Left blank because we dont have to do anything.
    }
    private void AuthenticateRequest(object r_objSender,
    EventArgs r_objEventArgs)
    {
    // Authenticate user credentials, and find out user roles.
    1. HttpApplication objApp = (HttpApplication) r_objSender ;
    2. HttpContext objContext = (HttpContext) objApp.Context ;
    3. if ( (objApp.Request["userid"] == null) ||
    4.                     (objApp.Request["password"] == null) )
    5. {
    6.  objContext.Response.Write("&lt;H1&gt;Credentials not provided&lt;/H1&gt;") ;
    7.  objContext.Response.End() ;
    8. }
    9. string userid = "" ;
    10. userid = objApp.Request["userid"].ToString() ;
    11. string password = "" ;
    12. password = objApp.Request["password"].ToString() ;
    13. string[] strRoles ;
    14. strRoles = AuthenticateAndGetRoles(userid, password) ;
    15. if ((strRoles == null) || (strRoles.GetLength(0) == 0))
    16. {
    17. objContext.Response.Write("&lt;H1&gt;We are sorry but we could not
    find this user id and password in our database&lt;/H1&gt;") ;
    18. objApp.CompleteRequest() ;
    19. }
    20. GenericIdentity objIdentity = new GenericIdentity(userid,
    "CustomAuthentication") ;
    21. objContext.User = new GenericPrincipal(objIdentity, strRoles) ;
    }
    private string[] AuthenticateAndGetRoles(string r_strUserID,
    string r_strPassword)
    {
    string[] strRoles = null ;
    if ((r_strUserID.Equals("Steve")) &amp;&amp;
    (r_strPassword.Equals("15seconds")))
    {
    strRoles = new String[1] ;
    strRoles[0] = "Administrator" ;
    }
    else if ((r_strUserID.Equals("Mansoor")) &amp;&amp;
    (r_strPassword.Equals("mas")))
    {
    strRoles = new string[1] ;
    strRoles[0] = "User" ;
    }
    return strRoles ;
    }
    }
    }
    </pre>
    <p class="MsoNormal"></font>Let's explore the code. </p>
    <p>We start with the Init function. This function plugs in our handler for the AuthenticateRequest event into the Application object's event handlers list. This will cause the Application object to call this method whenever the AuthenticationRequest event is raised.
    <p>Once our HTTP module is initialized, its AuthenticateRequest method will be called for authenticating client requests. AuthenticateRequest method is the heart of the security/authentication mechanism. In that function:
    <p>Line 1 and Line 2 extract the HttpApplication and HttpContext objects. Line 3 through Line 7 checks whether any of the userid or password is not provided to us. If this is the case, error is displayed and the request processing is terminated.
    <p>Line 9 through Line 12 extract the user id and password from the HttpRequest object.
    <p>Line 14 calls a helper function, named AuthenticateAndGetRoles. This function basically performs the authentication and determines the user role. This has been hard-coded and only two users are allowed, but we can generalize this method and add code for interacting with some user database to retrieve user roles.
    <p>Line 16 through Line 19 checks whether the user has any role assigned to it. If this is not the case that means the credentials passed to us could not be verified; therefore, these credentials are not valid. So, an error message is sent to the client and the request is completed.
    <p>Line 20 and Line 21 are very important because these lines actually inform the ASP.NET HTTP runtime about the identity of the logged-in user. Once these lines are successfully executed, our aspx pages will be able to access this information by using the User object.
    <p>Now let's see this authentication mechanism in action. Currently we are only allowing the following users to log in to our system:
    <p>
    <ul>
        <li>User id = Steve, Password = 15seconds, Role = Administrator</li>
        <li>User id = Mansoor, Password = mas, Role = User </li>
    </ul>
    <p>Note that user id and password are case-sensitive.
    <p>First try logging-in without providing credentials. Go to http://localhost/webapp2/index.aspx and you should see the following message.
    <p><img src="http://www.15seconds.com/graphics/issue/020417_04.jpg"  alt="" />
    <p>Now try logging-in with the user id "Steve" and password "15seconds". Go to http://localhost/webapp2/index.aspx?userid=Steve&amp;password=15seconds and you should see the following welcome message.
    <p><img src="http://www.15seconds.com/graphics/issue/020417_05.jpg"  alt="" />
    <p>Now try to log-in with the user id "Mansoor" and password "15seconds". Go to http://localhost/webapp2/index.aspx?userid=Mansoor&amp;password=mas and you should see the following welcome page.
    <p><img src="http://www.15seconds.com/graphics/issue/020417_06.jpg"  alt="" />
    <p>Now try to log-in with the wrong combination of user id and password. Go to http://localhost/webapp2/index.aspx?userid=Mansoor&amp;password=xyz and you should see the following error message.
    <p><img src="http://www.15seconds.com/graphics/issue/020417_07.jpg"  alt="" />
    <p>This shows our security module in action. You can generalize this security module by using database-access code in the AuthenticateAndGetRoles method.
    <p>For all of this to work, we have to perform some changes in our web.config file. First of all, since we are using our own custom authentication, we don't need any other authentication mechanism. To specify this, change the &lt;authentication&gt; node in web.config file of webapp2 to look like this:
    <pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
    &lt;authentication mode="None"/&gt;
    </pre>
    <p class="MsoNormal"></font>Similarly, don't allow anonymous users to our Web site. Add the following to web.config file: </p>
    <pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
    &lt;authorization&gt;
    &lt;deny users="?"/&gt;
    &lt;/authorization&gt;
    </font>
    </pre>
    <p class="MsoNormal">Users should at least have anonymous access to the file that they will use for providing credentials. Use the following configuration setting in the web.config file for specifying index.aspx as the only anonymously accessible file: </p>
    <pre><font face="ARIAL,HELVETICA" color="#0000ff" size="2">
    &lt;location path="index.aspx"&gt;
    &lt;system.web&gt;
    &lt;authorization&gt;
    &lt;allow users="*"/&gt;
    &lt;/authorization&gt;
    &lt;/system.web&gt;
    &lt;/location&gt;
    </font>
    </pre>
    <p class="MsoNormal"></span></p>
    <p><span class="clsTitle">Conclusion</span>
    <p><span class="clsBlurb">
    <p>As you might have realized with HTTP handlers and modules, ASP.NET has put a lot of power in the hands of developers. Plug your own components into the ASP.NET request processing pipeline and enjoy the benefits.
    <p>This article should at least get you started with these components. As an exercise, you might want to go and make this sample authentication module more flexible and tune it according to your needs.
    <p></span>
    <p><span class="clsTitle">About the Author</span>
    <p><span class="clsBlurb">
    <p>Mansoor Ahmed Siddiqui is a software consultant and technical writer working in the United States. He has a masters degree in computer science and been involved in software development since 1997. His areas of expertise include designing and developing Web-based applications, client-server applications, and n-tier applications, with a special focus on middle-tier and Win32 programming.
    <p>He has expertise in Microsoft. NET Framework, ASP.NET, C#, Visual Studio .NET, Web Services, ADO.NET, ASP, JavaScript, eXtensible Markup Language (XML), Simple Object Access Protocol (SOAP), Visual C++, Microsoft Foundation Class Library (MFC), Active Template Library (ATL), Visual Basic 6.0, ActiveX Data Objects (ADO), COM/DCOM/COM+, Microsoft Transaction Server (MTS), Microsoft Message Queue (MSMQ), SQL Server 7.0/2000, OMG's Unified Modeling Language (UML), Rational Software Corp.'s Rational Rose, Java, Java Server Page (JSP), servlets, Enterprise JavaBeans (EJBs), Java 2 Platform Enterprise Edition (J2EE). Currently, he is working with Visual Studio 7.0 and the Microsoft .NET platform. He is an MCSD and is Brainbench certified in different languages.
    <p>Apart from technical writing, other interests include listening to music, swimming, playing cricket and pool, and hanging out with friends. He can be reached at mansoorasiddiqui@hotmail.com and ICQ 151707288. </p>
    </span></o:p>
<img src ="http://www.cnblogs.com/beyondjay/aggbug/1276402.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/43606/" target="_blank">[新闻]李彦宏首次表态竞价排名问题:有错能改善莫大焉</a><br/><a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻频道</a>&nbsp;<a href="http://space.cnblogs.com/group.htm" target="_blank">小组</a>&nbsp;<a href="http://space.cnblogs.com/q" target="_blank">博问</a>&nbsp;<a href="http://wz.cnblogs.com/" target="_blank">网摘</a>&nbsp;<a href="http://space.cnblogs.com/ing" target="_blank">闪存</a>]]></description></item><item><title>Rendering n-column tables using the Repeater control（转载）</title><link>http://www.cnblogs.com/beyondjay/archive/2008/08/12/1266023.html</link><dc:creator>Tony Zhou</dc:creator><author>Tony Zhou</author><pubDate>Tue, 12 Aug 2008 07:31:00 GMT</pubDate><guid>http://www.cnblogs.com/beyondjay/archive/2008/08/12/1266023.html</guid><wfw:comment>http://www.cnblogs.com/beyondjay/comments/1266023.html</wfw:comment><comments>http://www.cnblogs.com/beyondjay/archive/2008/08/12/1266023.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/beyondjay/comments/commentRss/1266023.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/beyondjay/services/trackbacks/1266023.html</trackback:ping><description><![CDATA[<p><font face="Verdana">ref:<a href="http://blogs.msdn.com/aribeiro/articles/351439.aspx">http://blogs.msdn.com/aribeiro/articles/351439.aspx</a></font></p>
<h2>Rendering n-column tables using the Repeater control</h2>
<div class="postcontent">
<p><font face="Arial" size="2">The ASP.NET <strong>Repeater </strong>control provides a template-based mechanism for rendering data using Data Binding. A basic usage sample can be found <font face="Arial" size="2"><a href="http://samples.gotdotnet.com/quickstart/aspplus/doc/webdatalist.aspx">here</a> </font>. </font></p>
<p><font face="Arial" size="2">The control uses the &lt;ItemTemplate&gt; tag&nbsp;for declaring HTML that should be rendered for each data item and a &lt;SeparatorTemplate&gt; tag to put some HTML between items. It also supports an &lt;AlternatingItemTemplate&gt; that can useful to render a fancy mixed two-color list or, more seriously, a two-column table. An example:</font></p>
<p><strong><font face="Arial" size="2">Page1.aspx</font></strong></p>
<p class="cs"><font face="Courier New" size="2">&nbsp;&nbsp;&nbsp; &lt;table border="1"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;asp:Repeater id="Repeater1" runat="server"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ItemTemplate&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;%# DataBinder.Eval(Container.DataItem, "ProductName") %&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/ItemTemplate&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;AlternatingItemTemplate&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;%# DataBinder.Eval(Container.DataItem, "ProductName") %&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/td&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/AlternatingItemTemplate&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/asp:Repeater&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/table&gt;</font></p>
<p><strong><font face="Arial" size="2">Page1.cs</font></strong></p>
<p class="cs"><font face="Courier New" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected System.Web.UI.WebControls.Repeater Repeater1;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void Page_Load(object sender, System.EventArgs e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SqlConnection connection = new SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI;");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SqlCommand command = new SqlCommand("SELECT TOP 15 ProductId, ProductName FROM Products", connection); </font></p>
<p class="cs"><font face="Courier New" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connection.Open(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Repeater1.DataSource = command.ExecuteReader(CommandBehavior.CloseConnection);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Repeater1.DataBind();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p class="text"><strong><font face="Arial" size="2">Resulting HTML</font></strong></p>
<table id="table2" border="1">
    <tr>
            <td>
            <p class="text"><font face="Arial" size="2">Alice Mutton </font></p>
            </td>
            <td>
            <p class="text"><font face="Arial" size="2">Aniseed Syrup </font></p>
            </td>
        </tr>
        <tr>
            <td>
            <p class="text"><font face="Arial" size="2">Boston Crab Meat </font></p>
            </td>
            <td>
            <p class="text"><font face="Arial" size="2">Camembert Pierrot </font></p>
            </td>
        </tr>
        <tr>
            <td>
            <p class="text"><font face="Arial" size="2">Carnarvon Tigers </font></p>
            </td>
            <td>
            <p class="text"><font face="Arial" size="2">Chai </font></p>
            </td>
        </tr>
        <tr>
            <td>
            <p class="text"><font face="Arial" size="2">Chang </font></p>
            </td>
            <td>
            <p class="text"><font face="Arial" size="2">Chartreuse verte </font></p>
            </td>
        </tr>
        <tr>
            <td>
            <p class="text"><font face="Arial" size="2">Chef Anton's Cajun Seasoning </font></p>
            </td>
            <td>
            <p class="text"><font face="Arial" size="2">Chef Anton's Gumbo Mix </font></p>
            </td>
        </tr>
        <tr>
            <td>
            <p class="text"><font face="Arial" size="2">Chocolade </font></p>
            </td>
            <td>
            <p class="text"><font face="Arial" size="2">C&#244;te de Blaye </font></p>
            </td>
        </tr>
        <tr>
            <td>
            <p class="text"><font face="Arial" size="2">Escargots de Bourgogne </font></p>
            </td>
            <td>
            <p class="text"><font face="Arial" size="2">Filo Mix </font></p>
            </td>
        </tr>
        <tr>
            <td>
            <p class="text"><font face="Arial" size="2">Flotemysost </font></p>
            </td>
        </tr>
    </table>
<p class="text"><font face="Arial" size="2">But what if need to render, lets say, a 3-column table? </font></p>
<table id="table3" border="1">
    <tr>
            <td><font face="Arial" size="2">Alice Mutton</font></td>
            <td><font face="Arial" size="2">Aniseed Syrup</font></td>
            <td><font face="Arial" size="2">Boston Crab Meat</font></td>
        </tr>
        <tr>
            <td><font face="Arial" size="2">Camembert Pierrot</font></td>
            <td><font face="Arial" size="2">Carnarvon Tigers</font></td>
            <td><font face="Arial" size="2">Chai</font></td>
        </tr>
        <tr>
            <td><font face="Arial" size="2">Chang</font></td>
            <td><font face="Arial" size="2">Chartreuse verte</font></td>
            <td><font face="Arial" size="2">Chef Anton's Cajun Seasoning</font></td>
        </tr>
        <tr>
            <td><font face="Arial" size="2">Chef Anton's Gumbo Mix</font></td>
            <td><font face="Arial" size="2">Chocolade</font></td>
            <td><font face="Arial" size="2">C&#244;te de Blaye</font></td>
        </tr>
        <tr>
            <td><font face="Arial" size="2">Escargots de Bourgogne</font></td>
            <td><font face="Arial" size="2">Filo Mix</font></td>
            <td><font face="Arial" size="2">Flotemysost</font></td>
        </tr>
    </table>
<p class="text"><font face="Arial" size="2">And generically, a n-column table?</font></p>
<p class="text"><font face="Arial" size="2">There's no &lt;n-AlternatingItemTemplate&gt; tag for this purpose. Yes, you could just programatically render the required HTML, loosing the design-time support. But you can also achieve this using a <strong>template-based </strong>approach maintaining design time support, using <strong>Data Binding events</strong>. Here's how.</font></p>
<p class="text"><font face="Arial" size="2"></font>&nbsp;</p>
<p class="text"><font face="Arial">A 3-column table using a template-based Repeater</font></p>
<p class="text"><font face="Arial" size="2">To produce a 3-column table, all you need is render a &lt;TD&gt;...&lt;/TD&gt; for each data item, and render a &lt;/TR&gt;&lt;TR&gt; every 3 items. Besides, you should place a &lt;TR&gt; befere the first item and a &lt;/TR&gt; after the last item.</font></p>
<p class="text"><font face="Arial" size="2">The difficult part on this is the <em>"render a &lt;/TR&gt;&lt;TR&gt; every 3 items" </em>thing. How can this be achieved using Data Binding? The answer is the ItemDataBound event.</font></p>
<p class="text"><font face="Arial" size="2">When you invoke DataBind() method on a Data Binding enabled control, you can subscribe an event that is fired when each item is rendered. With some coding on this event, you can programmatically change the presentation of a specific data item. With this in mind, you can just count the items being rendered, and show or hide a separator &lt;/TR&gt;&lt;TR&gt; every three items.</font></p>
<p class="text"><font face="Arial" size="2">A full example:</font></p>
<p><font face="Arial" size="2"></font>
<p><font face="Arial" size="2"></font></p>
<p><strong><font face="Arial" size="2">Page1.aspx</font></strong></p>
<p class="cs"><font face="Courier New" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;table border="1"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;asp:Repeater id="Repeater1" runat="server"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ItemTemplate&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;td&gt;&lt;%# DataBinder.Eval(Container.DataItem, "ProductName") %&gt;&lt;/td&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/ItemTemplate&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;SeparatorTemplate&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;tr&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/SeparatorTemplate&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/asp:Repeater&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/tr&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/table&gt;<br />
</font><br />
<strong><font face="Arial" size="2">Page1.cs</font></strong></p>
<p class="cs"><font face="Courier New" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected System.Web.UI.WebControls.Repeater Repeater1;<br />
</font><font face="Courier New" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected int counter = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected int columnCount = 3;</font><font face="Courier New"><br />
<br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void Page_Load(object sender, System.EventArgs e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SqlConnection connection = new SqlConnection("Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI;");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SqlCommand command = new SqlCommand("SELECT TOP 15 ProductId, ProductName FROM Products", connection); </font></font></p>
<p class="cs"><font face="Courier New" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connection.Open();&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;Repeater1.DataSource = command.ExecuteReader(CommandBehavior.CloseConnection);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Repeater1.ItemDataBound +=new RepeaterItemEventHandler(Repeater1_ItemDataBound);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Repeater1.DataBind();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p class="cs"><font face="Courier New" size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (e.Item.ItemType == ListItemType.Separator)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if((++counter % columnCount) != 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.Item.Visible = false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></p>
<p class="text"><font face="Arial" size="2">Cool?<font face="Verdana">To get the full source co