<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.bartdesmet.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>B# .NET Blog : ASP.NET</title><link>http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET/default.aspx</link><description>Tags: ASP.NET</description><dc:language>en</dc:language><generator>CommunityServer 2007 (Build: 20423.869)</generator><item><title>Blog on the move adventures - Simple URL rewriting</title><link>http://blogs.bartdesmet.net/blogs/bart/archive/2006/11/04/Blog-on-the-move-adventures-_2D00_-Simple-URL-rewriting.aspx</link><pubDate>Sat, 04 Nov 2006 11:56:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:11910</guid><dc:creator>bart</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=11910</wfw:commentRss><comments>http://blogs.bartdesmet.net/blogs/bart/archive/2006/11/04/Blog-on-the-move-adventures-_2D00_-Simple-URL-rewriting.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://community.bartdesmet.net/blogs/bart/archive/2006/11/03/About-a-new-blog-hosting-space-and-CAPTCHA-validation.aspx"&gt;Yesterday&lt;/a&gt;&amp;nbsp;I reported having moved my blog to another host, which went just fine. So, today I took a look at the stats that come with the hosting package to find out about the number of requests per day. I was pretty amazed to see about 14,000 hits per day. However, when diving a little deeper I saw that about 10% of the requests ended up as a error-notfound.aspx. Pretty strange.&lt;/p&gt;&lt;p&gt;So what was going on? In the past, before moving to Community Server, my blog was on &lt;a href="http://blogs.bartrdesmet.net/bart"&gt;http://blogs.bartrdesmet.net/bart&lt;/a&gt;. Later, when I moved to CS, I added a dummy website to IIS, redirecting all traffic for &lt;a href="http://blogs.bartdesmet.net/"&gt;http://blogs.bartdesmet.net&lt;/a&gt;&amp;nbsp;to &lt;a href="http://community.bartdesmet.net/blogs"&gt;http://community.bartdesmet.net/blogs&lt;/a&gt; which worked fine. Today however, everything is hosted in one flat IIS space, meaning that &lt;a href="http://community.bartdesmet.net/"&gt;http://community.bartdesmet.net&lt;/a&gt; and &lt;a href="http://blogs.bartdesmet.net/"&gt;http://blogs.bartdesmet.net&lt;/a&gt; point to the same physical file location. So, requests like &lt;a href="http://blogs.bartdesmet.net/bart/archive/2005/10/28/3736.aspx"&gt;http://blogs.bartdesmet.net/bart/archive/2005/10/28/3736.aspx&lt;/a&gt;&amp;nbsp;result in a not found error.&lt;/p&gt;&lt;p&gt;The solution? I wrote&amp;nbsp;a very simple URL rewriting tool that looks for requests starting with /bart and redirect those to the appropriate location, e.g. &lt;a href="http://community.bartdesmet.net/blogs/bart/archive/2005/10/28/3736.aspx"&gt;http://community.bartdesmet.net/blogs/bart/archive/2005/10/28/3736.aspx&lt;/a&gt;. Here&amp;#39;s the code:&lt;/p&gt;&lt;p&gt;&lt;em&gt;using System;&lt;br /&gt;using System.Web;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;public class UrlRewriter : IHttpModule&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp; public virtual void Init(HttpApplication app)&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; app.BeginRequest += new&amp;nbsp;EventHandler(this.UrlRewriter_BeginRequest);&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp; public void UrlRewriter_BeginRequest(object sender, EventArgs e)&lt;br /&gt;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpApplication app = (HttpApplication) sender;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (app.Request.Path.ToLower().StartsWith(&amp;quot;/bart&amp;quot;))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; app.Response.Redirect(&amp;quot;&lt;/em&gt;&lt;a href="http://community.bartdesmet.net/blogs"&gt;&lt;em&gt;http://community.bartdesmet.net/blogs&lt;/em&gt;&lt;/a&gt;&lt;em&gt;&amp;quot; + app.Request.Path);&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; public void Dispose() {}&lt;br /&gt;}&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Tomorrow I&amp;#39;m leaving for TechEd. There will be a last technical post from home that appears online tomorrow afternoon. Stay tuned for TechEd adventure reports the next two weeks.&lt;/p&gt;&lt;img src="http://blogs.bartdesmet.net/aggbug.aspx?PostID=11910" width="1" height="1"&gt;</description><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/Personal/default.aspx">Personal</category></item><item><title>IIS worldwide server share increasing</title><link>http://blogs.bartdesmet.net/blogs/bart/archive/2006/04/07/3875.aspx</link><pubDate>Fri, 07 Apr 2006 22:50:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:3875</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=3875</wfw:commentRss><comments>http://blogs.bartdesmet.net/blogs/bart/archive/2006/04/07/3875.aspx#comments</comments><description>According to &lt;a href="http://news.netcraft.com/archives/2006/04/06/april_2006_web_server_survey.html" target="_blank"&gt;Netcraft&lt;/a&gt;, Microsoft gained about 4.71 percent web server market share. I'm happy to see this evolution: IIS and ASP.NET are really great pieces of technology and a lot has been proven on the field of security and reliability in the last couple of years (Code Red was a big security turn-over in IIS' history). On to a big IIS7 release...&lt;br&gt;&lt;br&gt;
&lt;img src="http://news.netcraft.com/archives/2006/04/overallc.gif"&gt;&lt;br&gt;&lt;i&gt;Source: Netcraft&lt;/i&gt;&lt;img src="http://blogs.bartdesmet.net/aggbug.aspx?PostID=3875" width="1" height="1"&gt;</description><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET+v2.0/default.aspx">ASP.NET v2.0</category></item><item><title>Arrived at the PDC - LA</title><link>http://blogs.bartdesmet.net/blogs/bart/archive/2005/09/13/3539.aspx</link><pubDate>Wed, 14 Sep 2005 04:55:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:3539</guid><dc:creator>bart</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=3539</wfw:commentRss><comments>http://blogs.bartdesmet.net/blogs/bart/archive/2005/09/13/3539.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;Okay, pretty late notice due to internet connectivity problems at the hotel, but I arrived at the PDC in LA a couple of days ago after a 11:40 hours flight from Amsterdam to LAX airport. Luckily, I'm not suffering from a jetlag, but I guess that has to do with my lack of biorithm :d.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;On Sunday I took the &lt;A href="mailto:EMEA@PDC"&gt;EMEA@PDC&lt;/A&gt; odd city tour, yesterday I went to the beach (Venice Beach) with &lt;A href="mailto:EMEA@PDC"&gt;EMEA@PDC&lt;/A&gt; to read some stuff, including documents on the C# 3.0, LINQ, DLINQ and XLINQ stuff that was announced in today's &lt;A href="http://www.microsoft.com/events/executives/billgates.mspx"&gt;keynote by Bill Gates and Jim Allchin&lt;/A&gt; which was pretty cool, covering Windows Vista pre-beta 2, Office 12 (it's sooo exciting, believe me ;-)), *&lt;A href="http://msdn.microsoft.com/netframework/future/linq/"&gt;LINQ&lt;/A&gt;, &lt;A href="http://beta.asp.net/default.aspx?tabindex=7&amp;tabid=47"&gt;Atlas&lt;/A&gt; and a lot of fun demos by Anders Heijlsberg, Don Box, Chris Anderson and Scott Gut&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;hrie. Also check out &lt;A href="http://www.microsoft.com/max/"&gt;Microsoft Max&lt;/A&gt;, a sample app running on WCF and WPF.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Going to find some food now (12:51 PM).&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.bartdesmet.net/aggbug.aspx?PostID=3539" width="1" height="1"&gt;</description><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/Avalon_2C00_+Indigo_2C00_+WinFX_2C00_+XAML/default.aspx">Avalon, Indigo, WinFX, XAML</category><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/PDC+2005/default.aspx">PDC 2005</category><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/C_2300_+3.0/default.aspx">C# 3.0</category></item><item><title>A simple request logger in ASP.NET</title><link>http://blogs.bartdesmet.net/blogs/bart/archive/2005/08/07/3430.aspx</link><pubDate>Sun, 07 Aug 2005 09:40:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:3430</guid><dc:creator>bart</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=3430</wfw:commentRss><comments>http://blogs.bartdesmet.net/blogs/bart/archive/2005/08/07/3430.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;&lt;FONT color=#000080&gt;Introduction&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;I just deployed a self-written request logger HTTP Module to my blogs website to have a better picture about the activity on my blog over here. Through this post, I'd like to share information with you on how to create such a logger HTTP Module.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=2&gt;&lt;STRONG&gt;What's an HTTP Module?&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;ASP.NET processes requests through a so-called HTTP request pipeline. A common example of such a request is browsing to an .aspx page. First of all, the request reaches the IIS machine on a some website (based on the IP and possibly a host header). In there, an ISAPI called aspnet_isapi.dll is configured for the .aspx extension, therefore sending the request to that ISAPI dll for further processing. In here, the HTTP pipeline of ASP.NET comes into play. Based on the configuration of the web server and the web application, the request is sent further to the right party for further processing. In the case of an .aspx page, the System.Web.UI.PageHandlerFactory class takes over the request for further processing.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;This "further processing" is based on two principles:&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;HTTP Modules&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;HTTP Handlers&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;An HTTP Module can be seen as a filter (and is somewhat equivalent to an ISAPI filter). All requests pass through the configured modules before further processing is done. Samples of modules include caching, authentication, authorization modules and also a logging module as I'll show you later on.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;HTTP Handlers are the equivalent of an ISAPI extension and are responsible to handle certain requests. Examples include the processing logic for .aspx, .asmx, .cs, ... files. By writing a custom HTTP Handler you can extend the ASP.NET runtime with your own logic to process certain requests. An simple example is a handler for .jpg images that supports image resizing as I explained earlier in an article of mine (&lt;A href="http://www.microsoft.com/belux/nl/msdn/community/columns/desmet/httphandler.mspx"&gt;http://www.microsoft.com/belux/nl/msdn/community/columns/desmet/httphandler.mspx&lt;/A&gt;).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In the machine.config file (%windir%\Microsoft.NET\Framework\v1.1.4322\CONFIG\machine.config) you'll find a section &lt;HTTPHANDLERS&gt;and &lt;HTTPMODULES&gt;that contains preconfigured HTTP Handlers and HTTP Modules, as shown below:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;httpHandlers&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.vjsproj" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.java" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.jsl" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="trace.axd" type="System.Web.Handlers.TraceHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.aspx" type="System.Web.UI.PageHandlerFactory" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.ashx" type="System.Web.UI.SimpleHandlerFactory" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.asmx" type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" validate="false" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.rem" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="false" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.soap" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" validate="false" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.asax" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.ascx" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="GET,HEAD" path="*.dll.config" type="System.Web.StaticFileHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="GET,HEAD" path="*.exe.config" type="System.Web.StaticFileHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.config" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.cs" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.csproj" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.vb" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.vbproj" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.webinfo" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.asp" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.licx" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.resx" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*.resources" type="System.Web.HttpForbiddenHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="GET,HEAD" path="*" type="System.Web.StaticFileHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add verb="*" path="*" type="System.Web.HttpMethodNotAllowedHandler" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/httpHandlers&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;httpModules&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="OutputCache" type="System.Web.Caching.OutputCacheModule" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="Session" type="System.Web.SessionState.SessionStateModule" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/httpModules&amp;gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Take a close look at these and try to understand what the role of each handler/module is. On a non-production box, feel free to play with these defaults.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=2&gt;&lt;STRONG&gt;Developing a custom HTTP Module&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Let's take a look at the development of our logging module, step by step:&lt;/FONT&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Start Visual Studio .NET 2003 and create a new Class Library project in C# and give it the name WebLogger.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Right click the References node in the Solution Explorer and choose Add Reference. Go to the .NET tab and select System.Web.dll (version 1.0.5000.0) and click OK.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Now go to Class1.cs and change the code as follows:&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;FONT face="Courier New" size=2&gt;using System;&lt;BR&gt;using System.Configuration;&lt;BR&gt;using System.Data;&lt;BR&gt;using System.Data.SqlClient;&lt;BR&gt;using System.Web;&lt;BR&gt;&lt;BR&gt;namespace BdsSoft&lt;BR&gt;{&lt;BR&gt;&lt;STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;public class WebLogger : IHttpModule&lt;/STRONG&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Holds the connection string to the logging database&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private string dsn;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// &lt;SUMMARY&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// Default constructor. Initializes the logger with configuration read from web.config.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// &lt;/SUMMARY&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public WebLogger()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Grab the connection string from &lt;APPSETTINGS /&gt;in web.config&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dsn = ConfigurationSettings.AppSettings["dsn"];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#region IHttpModule Members&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// &lt;SUMMARY&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// Initialization routine for the module.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// &lt;/SUMMARY&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// &lt;PARAM name="context"&gt;Context object for the current web application&lt;/PARAM&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void Init(HttpApplication context)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//We're only interested in incoming requests for logging purposes&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;context.BeginRequest += new EventHandler(context_BeginRequest);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;/STRONG&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// &lt;SUMMARY&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// Implementation of IDisposable.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// &lt;/SUMMARY&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void Dispose()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#endregion&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// &lt;SUMMARY&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// Event handler for the beginning of a web request.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// &lt;/SUMMARY&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// &lt;PARAM name="sender"&gt;HttpApplication object&lt;/PARAM&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;/// &lt;PARAM name="e"&gt;Event arguments&lt;/PARAM&gt;&lt;BR&gt;&lt;STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private void context_BeginRequest(object sender, EventArgs e)&lt;BR&gt;&lt;/STRONG&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Get access to the request context&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HttpApplication context = sender as HttpApplication;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Connect to the database&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;using (SqlConnection conn = new SqlConnection(dsn))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Stored procedure to insert an entry in our web log&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SqlCommand cmd = new SqlCommand("InsertLogEntry", conn);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.CommandType = CommandType.StoredProcedure;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Parameterization of the SqlCommand&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.Parameters.Add("@agent", SqlDbType.NVarChar, 100);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.Parameters.Add("@rawUrl", SqlDbType.NVarChar, 1000);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.Parameters.Add("@userHostAddress", SqlDbType.NVarChar, 15);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT size=2&gt;cmd.Parameters.Add("@userHostName", SqlDbType.NVarChar, 1000);&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.Parameters.Add("@httpMethod", SqlDbType.NVarChar, 10);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Query the stuff we need and set the parameters&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.Parameters["@agent"].Value = context.Request.UserAgent;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.Parameters["@rawUrl"].Value = context.Request.RawUrl;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.Parameters["@userHostAddress"].Value = context.Request.UserHostAddress;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT size=2&gt;cmd.Parameters["@userHostName"].Value = Dns.Resolve(context.Request.UserHostAddress).HostName; &lt;FONT color=#ff0000&gt;//this can cause a significant slowdown because of DNS reverse lookup queries!!!&lt;/FONT&gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.Parameters["@httpMethod"].Value = context.Request.HttpMethod;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//Open connection and execute the stored procedure&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;conn.Open();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cmd.ExecuteNonQuery();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;}&lt;/FONT&gt;&lt;BR&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;As you can see, the HTTP Module is nothing more than an implementation of the System.Web.IHttpModule interface. In the Init method, we register an event handler for the BeginRequest event of the HttpApplication which is passed to use by the ASP.NET runtime through the context parameter. The rest of the code is pretty straightforward and just plain vanilla ADO.NET magic. Build the project by hitting CTRL-SHIFT-B.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Now, for the database:&lt;/FONT&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Open SQL Server 2000 Query Analyzer.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Connect to the database where you want to put the logs; make sure you have administrative privileges over that database in order to add a table and a stored procedure.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Execute the following script:&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;create table RequestLog&lt;BR&gt;(&lt;BR&gt;[ID] INT IDENTITY(1,1) PRIMARY KEY,&lt;BR&gt;[agent] nvarchar(100) NOT NULL,&lt;BR&gt;[rawUrl] nvarchar(1000) NOT NULL,&lt;BR&gt;[userHostAddress] nvarchar(15) NOT NULL,&lt;BR&gt;[userHostName] nvarchar(1000) NOT NULL,&lt;BR&gt;[httpMethod] nvarchar(10) NOT NULL,&lt;BR&gt;[dateTime] datetime DEFAULT GetDate()&lt;BR&gt;)&lt;BR&gt;go&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;create proc InsertLogEntry&lt;BR&gt;@agent nvarchar(100),&lt;BR&gt;@rawUrl nvarchar(1000),&lt;BR&gt;@userHostAddress nvarchar(15),&lt;BR&gt;@userHostName nvarchar(1000),&lt;BR&gt;@httpMethod nvarchar(10)&lt;BR&gt;as&lt;BR&gt;insert into RequestLog (agent, rawUrl, userHostAddress, userHostName, httpMethod) values (@agent, @rawUrl, @userHostAddress, @userHostName, @httpMethod)&lt;BR&gt;go&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;FONT face="Courier New"&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Very straightforward, isn't it?&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000080 size=2&gt;&lt;STRONG&gt;Deployment&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Time to deploy. Connect to the webserver by means of FrontPage Server Extensions or FTP or file share or ... and open up the folder that contains the web application. Do the following:&lt;/FONT&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Copy the WebLogger.dll file from the bin\Debug folder of your project (that's the location where the module was&amp;nbsp;compiled to) to the bin folder on the server.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Edit the web.config file in the root folder of the web application as follows:&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;lt;configuration&amp;gt;&lt;BR&gt;&amp;nbsp; &lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;lt;appSettings&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;!--Web logger --&amp;gt;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add key="dsn" value = "server=localhost;uid=Blogs_BartDeSmet;pwd=8BhWx9CB73;database=Blogs_BartDeSmet" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/appSettings&amp;gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp; &amp;lt;system.web&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;lt;httpModules&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="RequestLogger" type= "BdsSoft.WebLogger, WebLogger" /&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/httpModules&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp; &amp;lt;/system.web&amp;gt;&lt;BR&gt;&amp;lt;/configuration&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Of course, maintain all the other stuff needed in your web.config file. The code displayed above just indicates the changes needed, including the registration of the HTTP Module and the configuration of it through the dsn-setting under &lt;APPSETTINGS&gt;, which needs to be adapted to reflect your configuration (user name, password and database name). Once you have saved the web.config file, the logging should start. While writing this post (took me about 10 minutes or so), I got already 239 rows in my event log table. Analysis can start! In particular I'm interested to see which kind of user agents are visiting my blog. Currently I have:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Abilon &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Bloglines/2.0 (http://www.bloglines.com; 29 subscribers) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;BlogPulse (ISSpider-3.0) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;FeedDemon/1.5 (http://www.bradsoft.com/; Microsoft Windows XP) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Feed-Directory/0.1 (+http://www.feed-directory.com/bot.html) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;http://www.feedtagger.com/rss-fetcher.php &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;JetBrains Omea Pro 2.0 Release Candidate 2 (http://www.jetbrains.com/omea/) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;JetBrains Omea Pro 2.0 Release Candidate 4 (http://www.jetbrains.com/omea/) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;JetBrains Omea Reader 1.0.4 (http://www.jetbrains.com/omea_reader/) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) Fetch API Request &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.3705) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/4.0 (compatible; MSIE 6.0; Windows 98; .NET CLR 1.1.4322) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50215) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50215; .NET CLR 1.1.4322) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50215) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; (R1 1.3); .NET CLR 1.1.4322) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.40607) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1; Maxthon; .NET CLR 1.1.4322) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.10) Gecko/20050716 Thunderbird/1.0.6 &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.7.10) Gecko/20050716 Firefox/1.0.6 &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;NewsGator/2.0 (http://www.newsgator.com; Microsoft Windows NT 5.1.2600.0; .NET CLR 1.1.4322.2032) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;NewsGatorOnline/2.0 (http://www.newsgator.com; 1 subscribers) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;NewsGatorOnline/2.0 (http://www.newsgator.com; 24 subscribers) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;RssBandit/1.3.0.26 (.NET CLR 1.1.4322.2032; WinNT 5.1.2600.0; http://www.rssbandit.org) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;RssBandit/1.3.0.29 (.NET CLR 1.1.4322.2032; WinNT 5.1.2600.0; http://www.rssbandit.org) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;RssReader/1.0.88.0 (http://www.rssreader.com) Microsoft Windows NT 5.2.3790.0 &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;SharpReader/0.9.5.1 (.NET CLR 1.1.4322.2032; WinNT 5.1.2600.0) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;SharpReader/0.9.5.1 (.NET CLR 1.1.4322.2300; WinNT 5.2.3790.0) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Waggr_Fetcher) &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;YahooSeeker-Testing/v3.9 (compatible; Mozilla 4.0; MSIE 5.5; http://search.yahoo.com/)&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Pretty cool. Hope you enjoy it too!&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.bartdesmet.net/aggbug.aspx?PostID=3430" width="1" height="1"&gt;</description><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/Personal/default.aspx">Personal</category></item><item><title>PHP ... powered by .NET</title><link>http://blogs.bartdesmet.net/blogs/bart/archive/2005/03/18/700.aspx</link><pubDate>Sat, 19 Mar 2005 01:51:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:700</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=700</wfw:commentRss><comments>http://blogs.bartdesmet.net/blogs/bart/archive/2005/03/18/700.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;Came across this nice project (nice because it has to do with .NET of course): a PHP compiler written in .NET. No, I'm not a PHP fan. Yes, I'm a .NET fan :-) More info on &lt;A href="http://www.php-compiler.net/"&gt;http://www.php-compiler.net/&lt;/A&gt;. Especially the benchmarks are interesting: the fastest PHP runtime is running on IIS, thanks to the underlying framework of course. And another nice effort, develop PHP inside Visual Studio .NET with full debugging support.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Anyway, counting down for ASP.NET v2.0 to come :-))))&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.bartdesmet.net/aggbug.aspx?PostID=700" width="1" height="1"&gt;</description><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Q&amp;A: Self-displaying ASP.NET pages</title><link>http://blogs.bartdesmet.net/blogs/bart/archive/2005/03/18/699.aspx</link><pubDate>Fri, 18 Mar 2005 09:54:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:699</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=699</wfw:commentRss><comments>http://blogs.bartdesmet.net/blogs/bart/archive/2005/03/18/699.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Question:&lt;/STRONG&gt; How to make a page that can show itself (that is, the source code) when creating samples?&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Answer:&lt;/STRONG&gt; Take a look at &lt;A href="http://www.bartdesmet.net/download/hash.aspx"&gt;http://www.bartdesmet.net/download/hash.aspx&lt;/A&gt;. Basically the code is just as simple as this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;string f = Server.MapPath(Request.Path);&lt;BR&gt;using(StreamReader r = new StreamReader(f))&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; code.Text = Server.HtmlEncode(r.ReadToEnd());&lt;BR&gt;}&lt;/FONT&gt;&lt;BR&gt;&lt;BR&gt;&lt;FONT face=Arial size=2&gt;Which you can put in an .ascx too, in order to display the .aspx that contains it (cf. Request.Path). So, it becomes as easy as doing a &amp;lt;%@ Register Tagprefix="src" Tagname="view" Src="showcode.ascx" %&amp;gt; together with &amp;lt;src:view runat="server" /&amp;gt;.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.bartdesmet.net/aggbug.aspx?PostID=699" width="1" height="1"&gt;</description><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Problem with System.Web.Mail?</title><link>http://blogs.bartdesmet.net/blogs/bart/archive/2005/02/22/634.aspx</link><pubDate>Tue, 22 Feb 2005 09:40:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:634</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=634</wfw:commentRss><comments>http://blogs.bartdesmet.net/blogs/bart/archive/2005/02/22/634.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;As I received a question today via MSN about the use of System.Web.Mail in .NET FX v1.x to send e-mails, I'm adding a pointer over here on my blog to the one (and only?) website for this kind of issues: &lt;A href="http://www.systemwebmail.com/"&gt;http://www.systemwebmail.com/&lt;/A&gt;. An entire domain for one namespace in the .NET Base Class Library :-).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Fortunately, these problems will be solved in .NET v2.0 where the SMTP classes won't rely on CDO anymore but will do the work on their own using TCP sockets directly.&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.bartdesmet.net/aggbug.aspx?PostID=634" width="1" height="1"&gt;</description><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Important information about ASP.NET Path Validation Vulnerability</title><link>http://blogs.bartdesmet.net/blogs/bart/archive/2005/02/09/620.aspx</link><pubDate>Wed, 09 Feb 2005 09:05:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:620</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=620</wfw:commentRss><comments>http://blogs.bartdesmet.net/blogs/bart/archive/2005/02/09/620.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;Read more on &lt;A href="http://support.microsoft.com/kb/886903"&gt;http://support.microsoft.com/kb/886903&lt;/A&gt;&amp;nbsp;and &lt;A href="http://www.microsoft.com/technet/security/Bulletin/ms05-004.mspx"&gt;http://www.microsoft.com/technet/security/Bulletin/ms05-004.mspx&lt;/A&gt;. It's currently under review at &lt;A href="http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0847"&gt;http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0847&lt;/A&gt;.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;EM&gt;The Microsoft .NET forms authentication capability allows remote attackers to bypass authentication for .aspx files in restricted directories via a request containing a (1) "\" (backslash) or (2) "%5C" (encoded backslash).&lt;/EM&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.bartdesmet.net/aggbug.aspx?PostID=620" width="1" height="1"&gt;</description><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/Security/default.aspx">Security</category></item><item><title>How to boost your managed code performance? Some tips...</title><link>http://blogs.bartdesmet.net/blogs/bart/archive/2004/12/18/502.aspx</link><pubDate>Sat, 18 Dec 2004 10:25:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:502</guid><dc:creator>bart</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=502</wfw:commentRss><comments>http://blogs.bartdesmet.net/blogs/bart/archive/2004/12/18/502.aspx#comments</comments><description>&lt;P&gt;&lt;FONT face=Arial size=2&gt;Last days, I've been evaluating some medium-sized project on the field performance, more specifically on the level of CLR managed code. Let's give a collection of tips in this post to make your app more performing.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=3&gt;&lt;STRONG&gt;1. Let garbage collection do its work&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Garbage collection is a great thing for various reasons (of which automatic memory management is the most important one of course). For the realtime software people, I know the GC is not a blessing for that kind of software, but it was never meant to be used for this class of scenarios. I won't cover the GC here in full detail but what you should know is that objects are grouped according to their lifetime and volatitly in what we call generations. Currently, there are three generations (Gen 0 - 2) and objects are promoted to higher generations when they live longer (0 --&amp;gt; 1 --&amp;gt; 2). The frequency of garbage collection is lower when the generation is growing. Garbage collection and finalization go hand in hand. Finalization is the process that is executed on an object before the managed memory of the object is reclaimed and has - in C# - the same syntax as a destructor in C++ (although the semantics are completely different).&amp;nbsp;More info on finalization, object disposal and GC can be found on the MSDN website. The GC is smart enough to decide when to work, so &lt;U&gt;there is not need to force the GC to start collecting objects&lt;/U&gt; using &lt;EM&gt;GC.Collect()&lt;/EM&gt;. Consequently, the &lt;EM&gt;GC.WaitForPendingFinalizers()&lt;/EM&gt; method should not be called as well (unless you have a really really serious reason - I can't think of one right now - to do this). There are two GCs on the system, one for workstations and one for servers with multiple processors (needed to split the heap over the various CPUs and to perform GC according to this model).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;&lt;EM&gt;To Finalize or not to Finalize&lt;/EM&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Don't implement the Finalize method always because the GC needs to promote an object that supports finalization to older generations in order to be able to execute finalization. This behavior has the undesired side-effect that objects become long-lived, something you don't want if your object's lifetime is short. When adding a "destructor", use the IDisposable interface always (see sample further). Only implement finalization when needed (maybe disposal is sufficient) and keep the code simple and short! If combined with threading on your object, take especially care of the synchronization of the threads (cleanup code should be threadsafe if the type is).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;&lt;EM&gt;Dispose correctly&lt;/EM&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;If you've used the &lt;EM&gt;using&lt;/EM&gt; syntax in C#, you probably know that this works only with IDisposable classes. I don't mean the "using" to import a namespace, rather I mean this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;using (SqlConnection conn = new SqlConnection(dsn)) {&lt;BR&gt;&amp;nbsp;&amp;nbsp; //use conn&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;}&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Disposing objects are used when external resources are called that need to be freed explicitly by the caller (in the case of "using", the disposing is done automagically and implicitly). You'll see this disposing pattern being applied on various places, such as database connections. Why don't we use finalization rather than disposing on this kind of objects? Well, the reason is that finalization is a GC-initiated process that is executed asynchronously, whileas the disposable pattern gives you the control needed to release resources in a timely fashion. One thing to keep in mind is that the GC can request finalization on an object, so this should be suppressed during the execution of the Dispose method call. In order to do so, don't ever forget to call &lt;EM&gt;GC.SuppressFinalization &lt;/EM&gt;in the Dispose method. As a side-remark, database connection et al support a Close method as well, which is in most cases just a context-specific synonym for disposing&amp;nbsp;an object (therefore more self-explaining to the developer). Another tip is to keep track of whether the Dispose object has been called already on an object. If that's the case, a second call should not be permitted which can be solved by throwing an &lt;EM&gt;ObjectDisposedException&lt;/EM&gt;. Typically, the creation of an IDisposable object is more complex than just writing the Dispose method. A typical skeleton is this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;class MyDisposableClass : IDisposable //you can seal the class if you want&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private bool _hasDisposed = false;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Dispose() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!_hasDisposed) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dispose(true);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GC.SuppressFinalize(this);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Special method for&amp;nbsp;object disposal; param indicates the call source&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected virtual void Dispose(bool disp) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (disp) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //dispose only when Dispose was called; used for managed resources&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//always do finalization; e.g. closing handles to unmanaged resources&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_hasDisposed = true;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;~MyDisposableClass() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dispose(false);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;&lt;EM&gt;Weak references&lt;/EM&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Weak referenes (class &lt;EM&gt;WeakReference&lt;/EM&gt;) allows to releasenon-critical objects from memory when there is memory pressure and the GC comes into play. What I mean but non-critical can be illustrated using the sample of a cache. Objects in a cache are pretty useful for the caller to improve the performance, but strictly speaking these objects are not needed since these can be resurrected all the time. So, under memory pressure, these objects can be resurrected safely without affecting the functionality of the system. Weak references are typically used on non-trivial objects (objects that contain quite some data). Basically, the WeakReference class is a wrapper that is recognized during garbage collection and can be used to release the memory when needed. The usage is pretty easy:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;//Some object is created&lt;BR&gt;MyWeakReferencedObject obj = new MyWeakReferencedObject();&lt;BR&gt;&lt;BR&gt;//Wrap the object&lt;BR&gt;WeakReference ref&amp;nbsp;= new WeakReference(obj);&lt;BR&gt;&lt;BR&gt;//Store the reference somewhere, e.g. in a collection&lt;BR&gt;//...&lt;BR&gt;//Retrieve the reference somewhere, e.g. get it from a collection&lt;BR&gt;&lt;BR&gt;//Unwrap the object&lt;BR&gt;MyWeakReferencedObject o = null;&lt;BR&gt;if (ref.IsAlive)&lt;BR&gt;&amp;nbsp;&amp;nbsp; o = (MyWeakReferencedObject) ref.Target;&lt;BR&gt;if (o == null)&lt;BR&gt;&amp;nbsp;&amp;nbsp; //GC has occurred, retrieve the object again (resurrection) from the source&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;//Normal operation continues&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;STRONG&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=3&gt;&lt;STRONG&gt;2. Use threading with care&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Use multithreading with care&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Multithreading makes your applications more responsive (in the presentation layer) and can be used to execute tasks that can't interfere with each other in a parallel way. This sounds great, and indeed it is. However, threads are the basic units of work on a processor and the OS is responsible to schedule threads for execution, which is done by context switching (therefore it can have a negative impact on the overall performance of the application when you have a bunch of threads). This is the reason why SQL 7 and higher are actually avoiding scheduling on the level of the kernel by means of the UMS (User Mode Scheduler) in order to reduce the number of context switches.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Threads are cute, ThreadPools are cuter&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;ThreadPools are a queuing mechanism that is using a set of pre-instantiated threads that are living in a pool. When work needs to be done, no new threads need to be initialized (which actually takes time to allocate the thread structure), a thread only needs to be grabbed from the pool when available. The way to use this mechanism is amazingly simple:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;WaitCallback cb = new WaitCallback(myObject.MyTargetMethod);&lt;BR&gt;ThreadPool.QueueUserWorkItem(cb); //will call the myObject.MyTargetMethod as soon as a thread becomed available in the pool&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;.NET v2.0 BackgroundWorkers&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In .NET Framework v2.0 there is support for a BackgroundWorker that offloads you from the complexity of performing background work and communicating back to the calling thread for progress indication (typically used in a WinForms app). Use this technology if you can instead of your own implementations of this mechanism.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Timers versus threads&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;When tasks need to be performed on a regular basis, use the various Timer components to do the trick. It's threading, but offloads you as a developer from the plumbing of timer logic and wait loops. You'll find timers typically in WinForms apps (Controls --&amp;gt; Timer), Windows Services (Components --&amp;gt; Timer), etc. If you don't use components to use some kind of timer, use the &lt;EM&gt;System.Threading.Timer&lt;/EM&gt; class (straightforward usage).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Let threads shut down gentry, don't use Thread.Abort&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Threads should commit suicide in order to stop. This allows resources to be cleaned up in the right way, to release locks, etc. &lt;EM&gt;Thread.Abort &lt;/EM&gt;should not be used, instead use some boolean value that is checked periodically inside the thread to detect whether it has to stop its work (i.e. to commit suicide). When you need to stop the thread, set the boolean stop indication value to true.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;Avoid deadlocks, avoid Thread.Resume and Thread.Suspend&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Synchronization of the work across threads should never be obtained using &lt;EM&gt;Suspend/Resume &lt;/EM&gt;calls, rather you should use &lt;EM&gt;lock&lt;/EM&gt; in C# or various objects in the Threading namespace such as Mutex, Monitor, etc to do this kind of work. Personally, the &lt;EM&gt;lock&lt;/EM&gt; keyword is my reliable partner in threading development.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=3&gt;&lt;STRONG&gt;3. Don't wait if you don't have to - Asynchronous invocation&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Why wait for a call to return if we can do other operations in the meantime. Or why wait for a call to return, therefore blocking the active thread. There are a series of classes in the BCL that support &lt;EM&gt;BeginInvoke&lt;/EM&gt; and &lt;EM&gt;EndInvoke&lt;/EM&gt; to make an asynchronous call. That means that when calling the BeginInvoke method, the method will return immediately. You supply the parameters to the method as well as a callback (delegate). When the work is done, the specified delegate's method will be called. In there, you can call the EndInvoke method on the object to retrieve the returned value (or any exceptions). The EndInvoke method will give your access to an AsyncState object that can be used to get more details about the original request and status. A typical example is an asynchonous web service call.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=3&gt;&lt;STRONG&gt;4. Why generics are great&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Collections in .NET v1.x are based on the mother of all types, the type "Object". Thus, when working with a colleciton, you can add objects of any type to that collection. However, when you retrieve the object from the collection, you end up with an object of the type "Object", so you need to upcast the returned object to the right type. This operation is expensive. .NET v2.0 will support generics that help you to solve this problem (by specifying the type you want to use in the collection):&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;//v1.x&lt;BR&gt;ArrayList lst = new ArrayList();&lt;BR&gt;lst.Add(1); //store an int&lt;BR&gt;int val = (int) lst[0]; //retrieve the int needs casting&lt;BR&gt;&lt;BR&gt;//v2.0&lt;BR&gt;ArrayList&lt;INT&gt; lst = new ArrayList&lt;INT&gt;();&lt;BR&gt;lst.Add(1);&lt;BR&gt;int val = lst[0];&lt;/FONT&gt;&lt;BR&gt;&lt;BR&gt;Note that generics work at development time, and the IDE will recognize the targeted type(s) of the collection.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=+0&gt;&lt;STRONG&gt;5. Be aware of remote objects or objects in other appdoms&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT size=+0&gt;When using .NET Remoting, be aware that using a remote object can cause a bunch of calls to be sent to another appdomain or even another machine. Think of this:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=+0&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;MyRemoteObject o = new MyRemoteObject();&lt;BR&gt;o.Property1 = "Hello";&lt;BR&gt;string msg = o.Property1;&lt;BR&gt;object&amp;nbsp;zzz = o.DoSomething("World");&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT size=+0&gt;This piece of code - when invoked on a transparent proxy object that represents a remote object living somewhere else - causes a lot of message to be passed over the wire: create the object, call the property setter, retrieve a value from the getter, call a method and return the value.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT size=+0&gt;Therefore, if you can, think of using a stateless approach, e.g. using web services or be at least aware of the negative impact remote objects can have. Thus, transparancy comes at the cost of performance.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT size=+0&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=+0&gt;&lt;STRONG&gt;6. Exceptions - only when needed&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT size=+0&gt;Exceptions should not be the default way to return from a method. It are &lt;U&gt;exceptions&lt;/U&gt;, what's in a word? Make sure you're using exceptions the right way.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT size=+0&gt;&lt;STRONG&gt;&lt;EM&gt;Finally finally&lt;/EM&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT size=+0&gt;Everyone knows and uses try ... catch, but please don't forget the finally block. All too often, this block is omitted. Think of this classic sample:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=+0&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;try &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=+0&gt;&lt;FONT size=2&gt;&lt;FONT face="Courier New"&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlConnection conn = new SqlConnection(dsn);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //use conn&lt;BR&gt;}&lt;BR&gt;catch {}&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;What's wrong here? A lot! First of all, a catch-all block is something to avoid whenever you can. Secondly, the connection should be closed when it has been used:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=+0&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;try &lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlConnection conn = new SqlConnection(dsn);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //use conn&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.Close();&lt;BR&gt;}&lt;BR&gt;catch (SqlException ex) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //catch it&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Better isn't it? Yes, but not good enough yet. Although we have replaced the catch block to catch only the exceptions we can and should&amp;nbsp;catch, we don't close the connection when an error occurs. Instead, use this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;SqlConnection conn = new SqlConnection(dsn);&lt;BR&gt;try &lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //use conn&lt;BR&gt;}&lt;BR&gt;catch (SqlException ex) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //catch it; don't attempt to close over here&lt;BR&gt;}&lt;BR&gt;finally {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.Close(); //or better, check connection state first using conn.State&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Finally always executes, even when you perform a return statement inside the try block. That's why it's just great. If you only have try ... finally (without catch), it's possible that you can replace the code with the C# &lt;EM&gt;using&lt;/EM&gt; syntax, as explained earlier in the IDisposable coverage.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;EM&gt;Don't rethrow but wrap&lt;/EM&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Rethrowing an exception is simply, just use &lt;EM&gt;throw&lt;/EM&gt; inside the &lt;EM&gt;catch&lt;/EM&gt; block. However, this call is very expensive (stack unwinding etc), so avoid it. Maybe it's better not to catch the exception (e.g. in&amp;nbsp;a helper method) and to catch it higher up the stack. Or - to help abstraction, at the cost of performance - wrap the exception in another exception-type (self-written) and throw that one. An example is to catch a SqlException and to throw it as a DALException (derived from &lt;EM&gt;ApplicationException&lt;/EM&gt;) to the higher layer. Use an InnerException if you want the original exception to be passed to the higher level.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;7. Strings are immutable&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Strings are immutable. Once allocated, their size can't be increased or decreased. So, what happens over here?&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;string s = "Bart";&lt;BR&gt;s += " De Smet";&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Indeed, a temporary string needs to be created and the original string "Bart" needs to be GCed. A better example:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;string str = "This string is becoming ";&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;for (int i = 0; i &amp;lt; 1000000; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp; str = str + "longer and "&lt;BR&gt;str = str + "longer."&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;In such a case you don't want to play the heap of the CLR (strings are reference types) and the GC will get tired to clean the 1M phantom objects. Even worse, the loop will become slower and slower at each pass, since a lot of char copying needs to be performed to concat a long string with another string.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;&lt;FONT size=2&gt;String operator overload '+' - use with care&lt;/FONT&gt;&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Use the concatenation operator + if you know that the number of concats is limited. In fact, I like to use String.Format instead in quite some cases to split the layout from the content. E.g. (both okay):&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;//Solution 1:&lt;BR&gt;string&amp;nbsp;envelope = "Name: " + name + "\nAddress: " + address + "\nZIP: " + zip + "\tCity: " + city&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;//Solution 2:&lt;BR&gt;string envelope = String.Format("Name: {0}\nAddress: {1}\nZIP: {2}\tCity: {3}", name, address, zip, city);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;&lt;EM&gt;Use StringBuilder inside loops etc&lt;/EM&gt;&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;StringBuilders use an internal buffer of characters (char array) to store the string and grow when the array is running out of space (by doubling the size of the array). An example:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;System.Text.StringBuilder sb = new System.Text.StringBuilder();&lt;BR&gt;sb.Append("This string is becoming ");&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;for (int i = 0; i &amp;lt; 1000000; i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp; sb.Append("longer and ");&lt;BR&gt;sb.Append("longer.");&lt;BR&gt;string str = sb.ToString();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;8. Reflection is slooooooooow&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;Relfection can be great if you use it with care. Late binding looks as it is a holy grail for software extensibility (and yes it is, as I explained in a post on my blog earlier). If you use late binding (e.g. when loading "providers" from a configuration file using reflection), make sure you can cache the retrieve object instance to avoid a second binding performance hit (caused by Activator.CreateInstance for example).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;9. Ngen.exe&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;NGen.exe is a tool that comes with the .NET Framework SDK that allows you to precompile an assembly (containing MSIL code) to native code, targeting the current hardware platform and processor instruction set (of the machine on which you run ngen). This increases performance but comes at the price of cross-platform portability of assemblies. In v1.x you can't use it however with ASP.NET assemblies in the web folder's bin directory, but this will change with precompilation in .NET v2.0 for ASP.NET pages.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;10. ASP.NET tips (sneak peak)&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;If I find some time later on, I'll cover ASP.NET specific performance tips. Let's give a fairly huge list of tips you can use:&lt;/FONT&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;FONT size=2&gt;Cache, cache, cache whenever possible. A 1 second cache is better than no cache in a lot of cases.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Limit the number of HttpModules.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Reduce round trips to the client (use client-side script and validation).&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Don't call long-running tasks when handling events server-side (use async calls, message queues, fire-and-forget, etc&amp;nbsp;if possible).&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Disable viewstate if not needed.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;In-process state is faster than using the ASP.NET state server or a SQL Server db; use these options only in web farms.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Use output buffering and Response.Flush to reduce roundtrips (chunky versus chatty).&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Server.Transfer avoids a roundtrip to the server compared to the use of Response.Redirect. However, Server.Transfer remains on the server all the time and can therefore bypass the HttpModules on the system; and you have to keep in the scope of the same app.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;In ASP.NET v2.0 use database cache invalidation with SQL Server 7/2000/2005.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Tweak the machine.config performance settings on the field of connections and worker/io threads and the threading pools.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Avoid aggressive use of IIS 6 app pool recycling.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Perfmon should be your guide to improve performance.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Never ever forget to call Dispose on database connections etc since these are typically used very very much inside web apps.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Avoid to open up a bunch of connections to a db, e.g. inside a OnItemDatabound event handler for a DataList, DataGrid, Repeater control. Chatty is bad, chunky is good.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Don't bypass SQL Server connection pooling; use the same connection string all the time to enable pooling to do its job.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Gzip/deflate compression can increase network speed, but can put additional pressure on the processor on both the client and the server; use it with care.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Page.IsPostBack should be used to avoid data rebinding on postbacks etc&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Impersonation is slow; avoid to do this on a per-request basis; use a trusted subsystem for the database when you can.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Use user controls to apply different caching on various webcontrols individually.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;In production, debugging and tracing should be disabled (e.g. trace.axd should not be reachable); use customErrors.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Use one dev language per folder; multiple languages (C#, VB.NET) cause different assemblies to be created in the bin folder.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Databind on the level of controls, not on the page level (e.g. grid.DataBind() instead of this.DataBind()).&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Avoid &lt;% .. %&gt;regions as well as &lt;%# ... %&gt;regions containing embedded script and DataBinder.Eval calls. This makes separation of code and content vague (remember plain old ASP-spaghetti code?). Use the OnItemDataBound event of the controls instead.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Windows Server 2003 kernel&amp;nbsp;caching (http.sys) should be used whenever possible (&lt;HTTPRUNTIME enableKernelModeCache="true" /&gt;).&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;@OutputCache is more than "Duration" and "VaryByParam". Take a look at the &lt;EM&gt;Location&lt;/EM&gt; attribute as well (Client &amp;lt;-&amp;gt; Server &amp;lt;-&amp;gt; ClientAndServer) for use with proxy servers etc.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Avoid Application[] and Session[] collections when you can; e.g. instead of using Application[] you can use static properties on the application object level as well.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;State is using serialization to store objects; use basic types to make serialization simpler. This is only applicable when using StateServer or SQL as state containers.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Session state, avoid if not needed and make it read-only on pages where you don't need write-access (&lt;%@ Page EnableSessionState="ReadOnly" %&gt;).&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;When creating server controls, don't use string concat the generate HTML, but use HtmlTextWriter instead.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Use Server.GetLastError() as catch-it-all inside the global.asax's Application_Error event handler.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;ASP.NET uses MTA (multithreaded apartment) for its threading; STA COM objects are discouraged if not needed (cf. AspCompat flag).&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Limit what you render to the client; use paging on DataGrids, turn off viewstate if not needed, make repeating regions lightweight.&lt;/FONT&gt; 
&lt;LI&gt;&lt;FONT size=2&gt;Remote middletiers offer a great benefit on the field of encapsulation and abstraction, but come at the cost of performance.&lt;/FONT&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://blogs.bartdesmet.net/aggbug.aspx?PostID=502" width="1" height="1"&gt;</description><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/Microsoft/default.aspx">Microsoft</category></item><item><title>Nikhil's server up for &gt; 250 days</title><link>http://blogs.bartdesmet.net/blogs/bart/archive/2004/10/16/439.aspx</link><pubDate>Sat, 16 Oct 2004 08:39:00 GMT</pubDate><guid isPermaLink="false">863c5522-913f-4a64-ac0a-bd5f05abad0f:439</guid><dc:creator>bart</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.bartdesmet.net/blogs/bart/rsscomments.aspx?PostID=439</wfw:commentRss><comments>http://blogs.bartdesmet.net/blogs/bart/archive/2004/10/16/439.aspx#comments</comments><description>&lt;FONT face=Arial size=2&gt;According to Netcraft (&lt;A href="http://uptime.netcraft.com/up/graph?site=www.nikhilk.net"&gt;http://uptime.netcraft.com/up/graph?site=www.nikhilk.net&lt;/A&gt;), Nikhil Kothari's server at Microsoft is now running for 251 days which means he has outperformed me on the field of system uptime. My record on &lt;A href="http://www.bartdesmet.net"&gt;www.bartdesmet.net&lt;/A&gt; (running Windows 2000 back then) was 250 days :-). Maybe he just has forgotten to have a server out there since the activity on his blog is rather low last time but I guess&amp;nbsp;this is due to priorities @ work :-). Nikhil is a PM on the ASP.NET team and has written the bible (that's my private opinion) on "Developing ASP.NET Server Controls and Components". Interesting reading and if you're serious on ASP.NET development you should have it on your shelf.&lt;/FONT&gt;&lt;img src="http://blogs.bartdesmet.net/aggbug.aspx?PostID=439" width="1" height="1"&gt;</description><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.bartdesmet.net/blogs/bart/archive/tags/Microsoft/default.aspx">Microsoft</category></item></channel></rss>