<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/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>Omar AL Zabir blog on ASP.NET Ajax and .NET 3.5 : asp.net, .net</title><link>http://msmvps.com/blogs/omar/archive/tags/asp.net/.net/default.aspx</link><description>Tags: asp.net, .net</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Web 2.0 AJAX Portal using jQuery, ASP.NET 3.5, Silverlight, Linq to SQL, WF and Unity</title><link>http://msmvps.com/blogs/omar/archive/2009/04/08/web-2-0-ajax-portal-using-jquery-asp-net-3-5-silverlight-linq-to-sql-wf-and-unity.aspx</link><pubDate>Wed, 08 Apr 2009 18:16:22 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1685991</guid><dc:creator>omar</dc:creator><slash:comments>11</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1685991</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2009/04/08/web-2-0-ajax-portal-using-jquery-asp-net-3-5-silverlight-linq-to-sql-wf-and-unity.aspx#comments</comments><description>&lt;p&gt;&lt;a title="Dropthings Web 2.0 style AJAX portal" href="http://dropthings.omaralzabir.com" target="_blank"&gt;Dropthings&lt;/a&gt; – my &lt;a title="Dropthings - Open Source AJAX Portal" href="http://www.codeplex.com/dropthings" target="_blank"&gt;open source&lt;/a&gt; Web 2.0 Ajax Portal has gone through a technology overhauling. Previously it was built using ASP.NET AJAX, a little bit of Workflow Foundation and Linq to SQL. Now Dropthings boasts full &lt;strong&gt;jQuery&lt;/strong&gt; front-end combined with ASP.NET AJAX &lt;code&gt;UpdatePanel&lt;/code&gt;, &lt;strong&gt;Silverlight widget&lt;/strong&gt;, full &lt;strong&gt;Workflow Foundation&lt;/strong&gt; implementation on the business layer, 100% &lt;strong&gt;Linq to SQL Compiled Queries&lt;/strong&gt; on the data access layer, Dependency Injection and Inversion of Control (IoC) using &lt;strong&gt;Microsoft Enterprise Library 4.1&lt;/strong&gt; and &lt;strong&gt;Unity&lt;/strong&gt;. It also has a ASP.NET AJAX Web Test framework that makes it real easy to write Web Tests that simulates real user actions on AJAX web pages. This article will walk you through the challenges in getting these new technologies to work in an ASP.NET website and how performance, scalability, extensibility and maintainability has significantly improved by the new technologies. Dropthings has been licensed for commercial use by prominent companies including BT Business, Intel, Microsoft IS, Denmark Government portal for Citizens; Startups like Limead and many more. So, this is serious stuff! There’s a very cool open source implementation of Dropthings framework available at &lt;a title="AJAX Portal at National University of Singapore" href="http://nexus.nus.edu.sg/apicta" target="_blank"&gt;National University of Singapore&lt;/a&gt; portal.&lt;/p&gt;  &lt;p&gt;Visit: &lt;a href="http://dropthings.omaralzabir.com"&gt;http://dropthings.omaralzabir.com&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_57907290.png"&gt;&lt;img title="Dropthings AJAX Portal" style="border-top-width:0px;display:inline;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="529" alt="Dropthings AJAX Portal" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_37551A39.png" width="600" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I have published a new article on this on CodeProject:&lt;/p&gt;  &lt;p&gt;&lt;a title="Web 2.0 AJAX Portal using jQuery, ASP.NET 3.5, Silverlight, Linq to SQL, WF and Unity" href="http://www.codeproject.com/KB/ajax/Web20Portal.aspx"&gt;http://www.codeproject.com/KB/ajax/Web20Portal.aspx&lt;/a&gt;&lt;/p&gt;  &lt;h2&gt;Get the source code&lt;/h2&gt;  &lt;p&gt;Latest source code is hosted at Google code:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://code.google.com/p/dropthings"&gt;http://code.google.com/p/dropthings&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;There’s a CodePlex site for documentation and issue tracking:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.codeplex.com/dropthings"&gt;http://www.codeplex.com/dropthings&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;You will need Visual Studio 2008 Team Suite with Service Pack 1 and Silverlight 2 SDK in order to run all the projects. If you have only Visual Studio 2008 Professional, then you will have to remove the Dropthings.Test project.&lt;/p&gt;  &lt;h2&gt;New features introduced&lt;/h2&gt;  &lt;p&gt;Dropthings new release has the following features:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Template users – you can define a user who’s pages and widgets are used as a template for new users. Whatever you put in that template user’s pages, it will be copied for every new user. Thus this is an easier way to define the default pages and widgets for new users. Similarly you can do the same for a registered user. The template users can be defined in the &lt;code&gt;web.config&lt;/code&gt;. &lt;/li&gt;    &lt;li&gt;Widget-to-Widget communication – Widgets can send message to each other. Widgets can subscribe to an Event Broker and exchange messages using a Pub-Sub pattern. &lt;/li&gt;    &lt;li&gt;WidgetZone – you can create any number of zones in any shape on the page. You can have widgets laid in horizontal layout, you can have zones on different places on the page and so on. With this zone model, you are no longer limited to the Page-Column model where you could only have N vertical columns. &lt;/li&gt;    &lt;li&gt;Role based widgets – now widgets are mapped to roles so that you can allow different users to see different widget list using &lt;code&gt;ManageWidgetPersmission.aspx.&lt;/code&gt; &lt;/li&gt;    &lt;li&gt;Role based page setup – you can define page setup for different roles. For ex, Managers see different pages and widgets than Employees. &lt;/li&gt;    &lt;li&gt;Widget maximize – you can maximize a widget to take full screen. Handy for widgets with lots of content. &lt;/li&gt;    &lt;li&gt;Free form resize – you can freely resize widgets vertically. &lt;/li&gt;    &lt;li&gt;Silverlight Widgets – You can now make widgets in Silverlight! &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Why the technology overhauling&lt;/h2&gt;  &lt;p&gt;Performance, Scalability, Maintainability and Extensibility – four key reasons for the overhauling. Each new technology solved one of more of these problems. &lt;/p&gt;  &lt;p&gt;First, jQuery was used to replace my personal hand-coded large amount of Javascript code that offered the client side drag &amp;amp; drop and other UI effects. jQuery already has a rich set of library for Drag &amp;amp; Drop, Animations, Event handling, cross browser javascript framework and so on. So, using jQuery means opening the door to thousands of jQuery plugins to be offered on Dropthings. This made Dropthings highly extensible on the client side. Moreover, jQuery is very light. Unlike AJAX Control Toolkit jumbo sized framework and heavy control extenders, jQuery is very lean. So, total javascript size decreased significantly resulting in improved page load time. In total, the jQuery framework, AJAX basic framework, all my stuffs are total 395KB, sweet! Performance is key; it makes or breaks a product.&lt;/p&gt;  &lt;p&gt;Secondly, Linq to SQL queries are replaced with Compiled Queries. Dropthings did not survive a load test when regular lambda expressions were used to query database. I could only reach up to 12 Req/Sec using 20 concurrent users without burning up web server CPU on a Quad Core DELL server. &lt;/p&gt;  &lt;p&gt;Thirdly, Workflow Foundation is used to build operations that require multiple Data Access Classes to perform together in a single transaction. Instead of writing large functions with many if…else conditions, for…loops, it’s better to write them in a Workflow because you can visually see the flow of execution and you can reuse Activities among different Workflows. Best of all, architects can design workflows and developers can fill-in code inside Activities. So, I could design a complex operations in a workflow without writing the real code inside Activities and then ask someone else to implement each Activity. It is like handing over a design document to developers to implement each unit module, only that here everything is strongly typed and verified by compiler. If you strictly follow Single Responsibility Principle for your Activities, which is a smart way of saying one Activity does only one and very simple task, you end up with a highly reusable and maintainable business layer and a very clean code that’s easily extensible.&lt;/p&gt;  &lt;p&gt;Fourthly, &lt;a title="Unity Dependency Injection framework" href="http://www.codeplex.com/unity" target="_blank"&gt;Unity&lt;/a&gt; Dependency Injection (DI) framework is used to pave the path for unit testing and dependency injection. It offers Inversion of Control (IoC), which enables testing individual classes in isolation. Moreover, it has a handy feature to control lifetime of objects. Instead of creating instance of commonly used classes several times within the same request, you can make instances thread level, which means only one instance is created per thread and subsequent calls reuse the same instance. Are these going over your head? No worries, continue reading, I will explain later on.&lt;/p&gt;  &lt;p&gt;Fifthly, enabling API for Silverlight widgets allows more interactive widgets to be built using Silverlight. HTML and Javascripts still have limitations on smooth graphics and continuous transmission of data from web server. Silverlight solves all of these problems.&lt;/p&gt;  &lt;p&gt;Read the article for details on how all these improvements were done and how all these hot techs play together in a very useful open source project for enterprises.&lt;/p&gt;  &lt;p&gt;&lt;a title="Web 2.0 AJAX Portal using jQuery, ASP.NET 3.5, Silverlight, Linq to SQL, WF and Unity" href="http://www.codeproject.com/KB/ajax/Web20Portal.aspx"&gt;http://www.codeproject.com/KB/ajax/Web20Portal.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Don’t forget to vote for me if you like it.&lt;/p&gt;&lt;div class="wlWriterHeaderFooter" style="text-align:left;margin:0px;padding:4px 4px 4px 4px;"&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http://msmvps.com/blogs/omar/archive/2009/04/08/web-2-0-ajax-portal-using-jquery-asp-net-3-5-silverlight-linq-to-sql-wf-and-unity.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http://msmvps.com/blogs/omar/archive/2009/04/08/web-2-0-ajax-portal-using-jquery-asp-net-3-5-silverlight-linq-to-sql-wf-and-unity.aspx&amp;amp;bgcolor=0080C0&amp;amp;fgcolor=FFFFFF&amp;amp;border=000000&amp;amp;cbgcolor=808080&amp;amp;cfgcolor=000000" alt="DotNetKicks Image" border="0/" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1685991" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/linq/default.aspx">linq</category><category domain="http://msmvps.com/blogs/omar/archive/tags/workflow/default.aspx">workflow</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/silverlight/default.aspx">silverlight</category></item><item><title>Optimize ASP.NET Membership Stored Procedures for greater speed and scalability</title><link>http://msmvps.com/blogs/omar/archive/2009/03/13/optimize-asp-net-membership-stored-procedures-for-greater-speed-and-scalability.aspx</link><pubDate>Fri, 13 Mar 2009 13:23:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1678004</guid><dc:creator>omar</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1678004</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2009/03/13/optimize-asp-net-membership-stored-procedures-for-greater-speed-and-scalability.aspx#comments</comments><description>&lt;p&gt;Last year at &lt;a href="http://www.pageflakes.com" title="Pageflakes - Web 2.0 AJAX portal" target="_blank"&gt;Pageflakes&lt;/a&gt;, when we were getting millions of hits per day, we were having query timeout due to lock timeout and Transaction Deadlock errors. These locks were produced from &lt;code&gt;aspnet_Users&lt;/code&gt; and &lt;code&gt;aspnet_Membership&lt;/code&gt; tables. Since both of these tables are very high read (almost every request causes a read on these tables) and high write (every anonymous visit creates a row on &lt;code&gt;aspnet_Users&lt;/code&gt;), there were just way too many locks created on these tables per second. SQL Counters showed thousands of locks per second being created. Moreover, we had queries that would select thousands of rows from these tables frequently and thus produced more locks for longer period, forcing other queries to timeout and thus throw errors on the website.&lt;/p&gt;
&lt;p&gt;If you have &lt;a href="http://msmvps.com/blogs/omar/archive/2009/03/07/linq-to-sql-solve-transaction-deadlock-and-query-timeout-problem-using-uncommitted-reads.aspx" title="Solve Transaction Deadlock and Lock Contention in Linq to Sql" target="_blank"&gt;read my last blog post&lt;/a&gt;, you know why such locks happen. Basically every table when it grows up to hold millions of records and becomes popular goes through this trouble. It&amp;rsquo;s just a part of scalability problem that is common to database. But we rarely take prevention about it in our early design.&lt;/p&gt;
&lt;p&gt;The solution is simple, you should either have &lt;code&gt;WITH (NOLOCK)&lt;/code&gt; or &lt;code&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED&lt;/code&gt; before SELECT queries. Either of this will do. They tell SQL Server not to hold any lock on the table while it is reading the table. If some row is locked while the read is happening, it will just ignore that row. When you are reading a table thousand times per second, without these options, you are issuing lock on many places around the table thousand times per second. It not only makes read from table slower, but also so many lock prevents insert, update, delete from happening timely and thus queries timeout. If you have queries like &amp;ldquo;show the currently online users from last one hour based on &lt;code&gt;LastActivityDate&lt;/code&gt; field&amp;rdquo;, that is going to issue such a wide lock that even other harmless select queries will timeout. And did I tell you that there&amp;rsquo;s no index on &lt;code&gt;LastActivityDate&lt;/code&gt; on &lt;code&gt;aspnet_Users&lt;/code&gt; table?&lt;/p&gt;
&lt;p&gt;Now don&amp;rsquo;t blame yourself for not putting either of these options on your every stored proc and every dynamically generated SQL from the very first day. ASP.NET developers made the same mistake. You won&amp;rsquo;t see either of these used in any of the stored procs used by ASP.NET Membership. For example, the following stored proc gets called whenever you access &lt;code&gt;Profile&lt;/code&gt; object:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;ALTER PROCEDURE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;[dbo]&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;[aspnet_Profile_GetProperties]&lt;br /&gt;    @ApplicationName      &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;nvarchar&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;256&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;),&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserName             &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;nvarchar&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;256&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;),&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@CurrentTimeUtc       &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;datetime&lt;br /&gt;AS&lt;br /&gt;BEGIN&lt;br /&gt;&lt;br /&gt;    DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;uniqueidentifier&lt;br /&gt;    SELECT  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;NULL&lt;br /&gt;    SELECT  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;FROM &lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;      dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Applications &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE LOWER&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationName&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;) = &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LoweredApplicationName&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IS NULL&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;RETURN&lt;br /&gt;&lt;br /&gt;    DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;uniqueidentifier&lt;br /&gt;    DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@LastActivityDate &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;datetime&lt;br /&gt;    SELECT  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;NULL&lt;br /&gt;&lt;br /&gt;    SELECT &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@LastActivityDate &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LastActivityDate&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;FROM   &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Users &lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;AND &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LoweredUserName &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;LOWER&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserName&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IS NULL&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;RETURN&lt;br /&gt;    SELECT TOP &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;1 &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyNames&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyValuesString&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyValuesBinary&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;FROM         &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Profile&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@@ROWCOUNT &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;0&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;BEGIN&lt;br /&gt;        UPDATE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Users&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;SET    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LastActivityDate&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;=&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@CurrentTimeUtc&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;END&lt;br /&gt;END&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;There are two SELECT operations that hold lock on two very high read tables &amp;ndash; &lt;code&gt;aspnet_Users&lt;/code&gt; and &lt;code&gt;aspnet_Profile&lt;/code&gt;. Moreover, there&amp;rsquo;s a nasty UPDATE statement. It tries to update the &lt;code&gt;LastActivityDate&lt;/code&gt; of a user whenever you access &lt;code&gt;Profile&lt;/code&gt; object for the first time within a http request. &lt;/p&gt;
&lt;p&gt;This stored proc alone is enough to bring your site down. It did to us because we are using &lt;code&gt;Profile&lt;/code&gt; Provider everywhere. This stored proc was called around 300 times/sec. We were having nightmarish slow performance on the website and many lock timeouts and transaction deadlocks. So, we added the transaction isolation level and we also modified the UPDATE statement to only perform an update when the &lt;code&gt;LastActivityDate&lt;/code&gt; is over an hour. So, this means, the same user&amp;rsquo;s &lt;code&gt;LastActivityDate&lt;/code&gt; won&amp;rsquo;t be updated if the user hits the site within the same hour.&lt;/p&gt;
&lt;p&gt;So, after the modifications, the stored proc looked like this:&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;ALTER PROCEDURE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;[dbo]&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;[aspnet_Profile_GetProperties]&lt;br /&gt;    @ApplicationName      &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;nvarchar&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;256&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;),&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserName             &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;nvarchar&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;256&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;),&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@CurrentTimeUtc       &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;datetime&lt;br /&gt;AS&lt;br /&gt;BEGIN&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#7f9f7f;"&gt;-- 1. Please no more locks during reads&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;uniqueidentifier&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#7f9f7f;"&gt;--SELECT  @ApplicationId = NULL&lt;br /&gt;    --SELECT  @ApplicationId = ApplicationId FROM dbo.aspnet_Applications &lt;br /&gt;    WHERE LOWER(@ApplicationName) = LoweredApplicationName&lt;br /&gt;    --IF (@ApplicationId IS NULL)&lt;br /&gt;    --    RETURN&lt;br /&gt;    &lt;br /&gt;    -- 2. No more call to Application table. We have only one app dude!&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;SET &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;udfGetAppId&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;()&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;uniqueidentifier&lt;br /&gt;    DECLARE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@LastActivityDate &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;datetime&lt;br /&gt;    SELECT  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;NULL&lt;br /&gt;&lt;br /&gt;    SELECT &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@LastActivityDate &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LastActivityDate&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;FROM   &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Users &lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@ApplicationId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;AND &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LoweredUserName &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;LOWER&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserName&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IS NULL&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;RETURN&lt;br /&gt;    SELECT TOP &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;1 &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyNames&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyValuesString&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;PropertyValuesBinary&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;FROM         &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Profile&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId&lt;br /&gt;&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@@ROWCOUNT &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;&amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;0&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;BEGIN&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#7f9f7f;"&gt;-- 3. Do not update the same user within an hour&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;IF DateDiff&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;n&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@LastActivityDate&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@CurrentTimeUtc&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;) &amp;gt; &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#8acccf;"&gt;60&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;BEGIN&lt;br /&gt;            &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#7f9f7f;"&gt;-- 4. Use ROWLOCK to lock only a row since we know this query&lt;br /&gt;            -- is highly selective&lt;br /&gt;            &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;UPDATE &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;aspnet_Users &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WITH&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;ROWLOCK&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;            &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;SET    &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;LastActivityDate&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;=&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@CurrentTimeUtc&lt;br /&gt;            &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;WHERE  &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;UserId &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;= &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;@UserId&lt;br /&gt;        &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;END&lt;br /&gt;    END&lt;br /&gt;END&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;The changes I made are numbered and commented. No need for further explanation. The only tricky thing here is, I have eliminate call to Application table just to get the ApplicationID from ApplicationName. Since there&amp;rsquo;s only one application in a database (ever heard of multiple applications storing their user separately on the same database and the same table?), we don&amp;rsquo;t need to look up the ApplicationID on every call to every Membership stored proc. We can just get the ID and hard code it in a function.&lt;/p&gt;
&lt;pre class="code"&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;CREATE FUNCTION &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;dbo&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;.&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;udfGetAppId&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;()&lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;RETURNS uniqueidentifier&lt;br /&gt;WITH EXECUTE AS &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dfdfbf;"&gt;CALLER&lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;AS&lt;br /&gt;BEGIN&lt;br /&gt;    RETURN CONVERT&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;(&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;uniqueidentifier&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;, &lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#c89191;"&gt;&amp;#39;fd639154-299a-4a9d-b273-69dc28eb6388&amp;#39;&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#eaeaac;"&gt;END&lt;/span&gt;&lt;span style="background:#3f3f3f none repeat scroll 0% 0%;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:#dcdccc;"&gt;;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;This UDF returns the &lt;code&gt;ApplicationID&lt;/code&gt; that I have hardcoded copying from the Application table. Thus it eliminates the need for quering on the Application table. &lt;/p&gt;
&lt;p&gt;Similarly you should do the changes in all other stored procedures that belong to Membership Provider. All the stroc procs are missing proper locking, issues aggressive lock during update and too frequent updates than practical need. Most of them also try to resolve ApplicationID from ApplicationName, which is unnecessary when you have only one web application per database. Make these changes and enjoy lock contention free super performance from Membership Provider!&lt;/p&gt;
&lt;div class="wlWriterHeaderFooter" style="margin:0px;padding:4px;text-align:left;"&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;/script&gt;
&lt;script src="http://widgets.dzone.com/widgets/zoneit.js" language="javascript"&gt;&lt;/script&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f03%2f14%2foptimize-asp-net-membership-stored-procedures-for-greater-speed-and-scalability.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2009%2f03%2f14%2foptimize-asp-net-membership-stored-procedures-for-greater-speed-and-scalability.aspx" alt="kick it on DotNetKicks.com" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1678004" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>Deploy ASP.NET MVC on IIS 6, solve 404, compression and performance problems</title><link>http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx</link><pubDate>Mon, 30 Jun 2008 08:12:22 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1638845</guid><dc:creator>omar</dc:creator><slash:comments>22</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1638845</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx#comments</comments><description>&lt;p&gt;There are several problems with ASP.NET MVC application when deployed on IIS 6.0:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Extensionless URLs give 404 unless some URL Rewrite module is used or wildcard mapping is enabled  &lt;li&gt;IIS 6.0 built-in compression does not work for dynamic requests. As a result, ASP.NET pages are served uncompressed resulting in poor site load speed.  &lt;li&gt;Mapping wildcard extension to ASP.NET introduces the following problems:  &lt;ul&gt; &lt;li&gt;Slow performance as all static files get handled by ASP.NET and ASP.NET reads the file from file system on every call  &lt;li&gt;Expires headers doesn&amp;#39;t work for static content as IIS does not serve them anymore. Learn about benefits of expires header from &lt;a title="Making best use of cache" href="http://msmvps.com/blogs/omar/archive/2007/11/29/making-best-use-of-cache-for-high-performance-website.aspx"&gt;here&lt;/a&gt;. ASP.NET serves a fixed expires header that makes content expire in a day.  &lt;li&gt;Cache-Control header does not produce max-age properly and thus caching does not work as expected. Learn about caching best practices from &lt;a title="Making best use of Cache" href="http://msmvps.com/blogs/omar/archive/2007/11/29/making-best-use-of-cache-for-high-performance-website.aspx"&gt;here&lt;/a&gt;. &lt;/li&gt;&lt;/ul&gt; &lt;li&gt;After deploying on a domain as the root site, the homepage produces HTTP 404.&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Problem 1: Visiting your website&amp;#39;s homepage gives 404 when hosted on a domain&lt;/h3&gt; &lt;p&gt;You have done the wildcard mapping, mapped .mvc extention to ASP.NET ISAPI handler, written the route mapping for Default.aspx or default.aspx (lowercase), but still when you visit your homepage after deployment, you get:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_32.png"&gt;&lt;img style="border-right:0px;border-top:0px;border-left:0px;border-bottom:0px;" height="273" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_6.png" width="430" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;You will find people banging their heads on the wall here:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a title="http://forums.asp.net/t/1237051.aspx" href="http://forums.asp.net/t/1237051.aspx"&gt;http://forums.asp.net/t/1237051.aspx&lt;/a&gt;  &lt;li&gt;&lt;a title="http://forums.asp.net/t/1253599.aspx" href="http://forums.asp.net/t/1253599.aspx"&gt;http://forums.asp.net/t/1253599.aspx&lt;/a&gt;  &lt;li&gt;&lt;a title="http://forums.asp.net/p/1239943/2294813.aspx" href="http://forums.asp.net/p/1239943/2294813.aspx"&gt;http://forums.asp.net/p/1239943/2294813.aspx&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Solution is to capture hits going to &amp;quot;/&amp;quot; and then rewrite it to Default.aspx:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_4.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="61" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_1.png" width="600" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;You can apply this approach to any URL that ASP.NET MVC is not handling for you and it should handle. Just see the URL reported on the 404 error page and then rewrite it to a proper URL.&lt;/p&gt; &lt;h3&gt;Problem 2: IIS 6 compression is no longer working after wildcard mapping&lt;/h3&gt; &lt;p&gt;When you enable wildcard mapping, IIS 6 compression no longer works for extensionless URL because IIS 6 does not see any extension which is defined in IIS Metabase. You can learn about IIS 6 compression feature and how to configure it properly from &lt;a title="IIS 6 Compression - quickest and effective way to do it" href="http://msmvps.com/blogs/omar/archive/2006/08/10/iis-6-compression-quickest-and-effective-way-to-do-it-for-asp-net-compression.aspx"&gt;my earlier post&lt;/a&gt;. &lt;/p&gt; &lt;p&gt;Solution is to use an HttpModule to do the compression for dynamic requests.&lt;/p&gt; &lt;h3&gt;Problem 3: ASP.NET ISAPI does not cache Static Files &lt;/h3&gt; &lt;p&gt;When ASP.NET&amp;#39;s &lt;u&gt;DefaultHttpHandler&lt;/u&gt; serves static files, it does not cache the files in-memory or in ASP.NET cache. As a result, every hit to static file results in a File read. Below is the decompiled code in &lt;u&gt;DefaultHttpHandler&lt;/u&gt; when it handles a static file. As you see here, it makes a file read on every hit and it only set the expiration to one day in future. Moreover, it generates &lt;u&gt;ETag&lt;/u&gt; for each file based on file&amp;#39;s modified date. For best caching efficiency, we need to get rid of that &lt;u&gt;ETag&lt;/u&gt;, produce an expiry date on far future (like 30 days), and produce &lt;u&gt;Cache-Control&lt;/u&gt; header which offers better control over caching.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_12.png"&gt;&lt;img height="433" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_5.png" width="600" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;So, we need to write a custom static file handler that will cache small files like images, Javascripts, CSS, HTML and so on in ASP.NET cache and serve the files directly from cache instead of hitting the disk. Here are the steps:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Install an &lt;u&gt;HttpModule&lt;/u&gt; that installs a Compression Stream on &lt;u&gt;Response.Filter&lt;/u&gt; so that anything written on Response gets compressed. This serves dynamic requests.  &lt;li&gt;Replace ASP.NET&amp;#39;s &lt;u&gt;DefaultHttpHandler&lt;/u&gt; that listens on *.* for static files.  &lt;li&gt;Write our own Http Handler that will deliver compressed response for static resources like Javascript, CSS, and HTML. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_6.png"&gt;&lt;img height="59" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_2.png" width="600" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Here&amp;#39;s the mapping in ASP.NET&amp;#39;s web.config for the &lt;u&gt;DefaultHttpHandler&lt;/u&gt;. You will have to replace this with your own handler in order to serve static files compressed and cached. &lt;/p&gt; &lt;h3&gt;Solution 1: An Http Module to compress dynamic requests&lt;/h3&gt; &lt;p&gt;First, you need to serve compressed responses that are served by the &lt;u&gt;MvcHandler&lt;/u&gt; or ASP.NET&amp;#39;s default Page Handler. The following &lt;u&gt;HttpCompressionModule&lt;/u&gt; hooks on the &lt;u&gt;Response.Filter&lt;/u&gt; and installs a &lt;u&gt;GZipStream&lt;/u&gt; or &lt;u&gt;DeflateStream&lt;/u&gt; on it so that whatever is written on the Response stream, it gets compressed.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_8.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="393" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_3.png" width="596" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;These are formalities for a regular &lt;u&gt;HttpModule&lt;/u&gt;. The real hook is installed as below:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_10.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="436" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_4.png" width="593" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Here you see we ignore requests that are handled by ASP.NET&amp;#39;s &lt;u&gt;DefaultHttpHandler&lt;/u&gt; and our own &lt;u&gt;StaticFileHandler&lt;/u&gt; that you will see in next section. After that, it checks whether the request allows content to be compressed. &lt;u&gt;Accept-Encoding&lt;/u&gt; header contains &amp;quot;gzip&amp;quot; or &amp;quot;deflate&amp;quot; or both when browser supports compressed content. So, when browser supports compressed content, a Response Filter is installed to compress the output.&lt;/p&gt; &lt;h3&gt;Solution 2: An Http Module to compress and cache static file requests&lt;/h3&gt; &lt;p&gt;Here&amp;#39;s how the handler works:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Hooks on *.* so that all unhandled requests get served by the handler  &lt;li&gt;Handles some specific files like js, css, html, graphics files. Anything else, it lets ASP.NET transmit it  &lt;li&gt;The extensions it handles itself, it caches the file content so that subsequent requests are served from cache  &lt;li&gt;It allows compression of some specific extensions like js, css, html. It does not compress graphics files or any other extension.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Let&amp;#39;s start with the handler code:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_16.png"&gt;&lt;img height="230" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_7.png" width="600" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Here you will find the extensions the handler handles and the extensions it compresses. You should only put files that are text files in the COMPRESS_FILE_TYPES.&lt;/p&gt; &lt;p&gt;Now start handling each request from &lt;u&gt;BeginProcessRequest&lt;/u&gt;. &lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_18.png"&gt;&lt;img height="432" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_8.png" width="598" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Here you decide the compression mode based on &lt;u&gt;Accept-Encoding&lt;/u&gt; header. If browser does not support compression, do not perform any compression. Then check if the file being requested falls in one of the extensions that we support. If not, let ASP.NET handle it. You will see soon how.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_20.png"&gt;&lt;img height="537" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_9.png" width="599" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Calculate the cache key based on the compression mode and the physical path of the file. This ensures that no matter what the URL requested, we have one cache entry for one physical file. Physical file path won&amp;#39;t be different for the same file. Compression mode is used in the cache key because we need to store different copy of the file&amp;#39;s content in ASP.NET cache based on Compression Mode. So, there will be one uncompressed version, a gzip compressed version and a deflate compressed version.&lt;/p&gt; &lt;p&gt;Next check if the file exits. If not, throw HTTP 404. Then create a memory stream that will hold the bytes for the file or the compressed content. Then read the file and write in the memory stream either directly or via a GZip or Deflate stream. Then cache the bytes in the memory stream and deliver to response. You will see the &lt;u&gt;ReadFileData&lt;/u&gt; and &lt;u&gt;CacheAndDeliver&lt;/u&gt; functions soon.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_22.png"&gt;&lt;img height="385" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_10.png" width="600" border="0" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;This function delivers content directly from ASP.NET cache. The code is simple, read from cache and write to the response.&lt;/p&gt; &lt;p&gt;When the content is not available in cache, read the file bytes and store in a memory stream either as it is or compressed based on what compression mode you decided before:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_24.png"&gt;&lt;img height="426" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_11.png" width="598" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Here bytes are read in chunk in order to avoid large amount of memory allocation. You could read the whole file in one shot and store in a byte array same as the size of the file length. But I wanted to save memory allocation. Do a performance test to figure out if reading in 8K chunk is not the best approach for you.&lt;/p&gt; &lt;p&gt;Now you have the bytes to write to the response. Next step is to cache it and then deliver it.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_26.png"&gt;&lt;img height="284" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_12.png" width="600" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Now the two functions that you have seen several times and have been wondering what they do. Here they are:&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_28.png"&gt;&lt;img height="477" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_13.png" width="599" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;u&gt;WriteResponse&lt;/u&gt; has no tricks, but &lt;u&gt;ProduceResponseHeader&lt;/u&gt; has much wisdom in it. First it turns off response buffering so that ASP.NET does not store the written bytes in any internal buffer. This saves some memory allocation. Then it produces proper cache headers to cache the file in browser and proxy for 30 days, ensures proxy revalidate the file after the expiry date and also produces the &lt;u&gt;Last-Modified&lt;/u&gt; date from the file&amp;#39;s last write time in UTC.&lt;/p&gt; &lt;h3&gt;How to use it&lt;/h3&gt; &lt;p&gt;Get the &lt;u&gt;HttpCompressionModule&lt;/u&gt; and &lt;u&gt;StaticFileHandler&lt;/u&gt; from: &lt;/p&gt; &lt;p&gt;&lt;a title="http://code.msdn.microsoft.com/fastmvc" href="http://code.msdn.microsoft.com/fastmvc"&gt;http://code.msdn.microsoft.com/fastmvc&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Then install them in &lt;u&gt;web.config&lt;/u&gt;. First you install the &lt;u&gt;StaticFileHandler&lt;/u&gt; by removing the existing mapping for path=&amp;quot;*&amp;quot; and then you install the &lt;u&gt;HttpCompressionModule&lt;/u&gt;.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_30.png"&gt;&lt;img height="208" alt="image" src="http://msmvps.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/omar/image_5F00_thumb_5F00_14.png" width="602" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;That&amp;#39;s it! Enjoy a faster and more responsive ASP.NET MVC website deployed on IIS 6.0.&lt;/p&gt;&lt;span class="sbmLink"&gt;&lt;span class="sbmLink"&gt; &lt;table cellspacing="1" cellpadding="1"&gt;  &lt;tr&gt; &lt;td class="sbmText"&gt;Share this post : &lt;/td&gt; &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to del.icio.us" href="http://del.icio.us/post?url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/deliciou4.png" border="0" alt="" /&gt;del.icio.us&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to digg" href="http://digg.com/submit?phase=2&amp;amp;url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/digg14.png" border="0" alt="" /&gt;digg&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to dotnetkicks" href="http://www.dotnetkicks.com/kick/?url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/CropperCapture154.jpg" border="0" alt="" /&gt;dotnetkicks&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to furl" href="http://www.furl.net/store?s=f&amp;amp;to=0&amp;amp;u=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;ti=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/furl4.png" border="0" alt="" /&gt;furl&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to live" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;amp;mkt=en-us&amp;amp;url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/live4.png" border="0" alt="" /&gt;live&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to reddit!" href="http://reddit.com/submit?url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/reddit4.png" border="0" alt="" /&gt;reddit&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to spurl" href="http://www.spurl.net/spurl.php?v=3&amp;amp;url=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/spurl8.png" border="0" alt="" /&gt;spurl&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to technorati!" href="http://technorati.com/faves/?add=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;title=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/technora4.png" border="0" alt="" /&gt;technorati&lt;/a&gt;  &lt;td class="sbmDim"&gt;&lt;a class="sbmDim" title="Post it to yahoo!" href="http://myweb.yahoo.com/myresults/bookmarklet?u=http://msmvps.com/blogs/omar/archive/2008/06/30/deploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx&amp;amp;t=Deploy%20ASP.NET%20MVC%20on%20IIS%206,%20solve%20404,%20compression%20and%20performance%20problems" target="_blank"&gt;&lt;img src="http://blogs.msdn.com/blogfiles/rahulso/WindowsLiveWriter/IconsfordifferentSocialBookmarkingSites_B387/yahoo9.png" border="0" alt="" /&gt;yahoo&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f06%2f30%2fdeploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fomar%2farchive%2f2008%2f06%2f30%2fdeploy-asp-net-mvc-on-iis-6-solve-404-compression-and-performance-problems.aspx" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1638845" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/production/default.aspx">production</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net+MVC/default.aspx">asp.net MVC</category></item><item><title>Fast, Streaming AJAX proxy - continuously download from cross domain</title><link>http://msmvps.com/blogs/omar/archive/2008/04/14/fast-streaming-ajax-proxy-continuously-download-from-cross-domain.aspx</link><pubDate>Mon, 14 Apr 2008 07:29:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1586081</guid><dc:creator>omar</dc:creator><slash:comments>15</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1586081</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/04/14/fast-streaming-ajax-proxy-continuously-download-from-cross-domain.aspx#comments</comments><description>&lt;p&gt;&lt;span id="intelliTXT"&gt;Due to browser&amp;#39;s prohibition on cross domain
XMLHTTP call, all AJAX
websites must have server side proxy to fetch content from external
domain like Flickr or Digg. From client side javascript code, an
XMLHTTP call goes to the server side proxy hosted on the same domain
and then the proxy downloads the content from the external server and
sends back to the browser. In general, all AJAX websites on the
Internet that are showing content from external domains are following
this proxy approach except some rare ones who are using JSONP. Such a
proxy gets a very large number of hits when a lot of component on the
website are downloading content from external domains. So, it becomes a
scalability issue when the proxy starts getting millions of hits.
Moreover, web page&amp;#39;s overall load performance largely depends on the
performance of the proxy as it delivers content to the page. In this
article, we will take a look how we can take a conventional AJAX Proxy
and make it faster, asynchronous, continuously stream content and thus
make it more scalable.&lt;/span&gt; &lt;/p&gt; &lt;p&gt;You can see such a proxy in action when you go to &lt;a href="http://www.pageflakes.com/"&gt;Pageflakes.com&lt;/a&gt;. You will see flakes (widgets) loading many different content like weather feed, flickr photo, youtube videos, RSS from many different external domains. All these are done via a &lt;i&gt;Content Proxy&lt;/i&gt;. Content Proxy served about &lt;b&gt;42.3 million URLs&lt;/b&gt; last month which is quite an engineering challenge for us to make it both fast and scalable. Sometimes Content Proxy serves megabytes of data, which poses even greater engineering challenge. As such proxy gets large number of hits, if we can save on an average 100ms from each call, we can save &lt;b&gt;4.23 million seconds&lt;/b&gt; of download/upload/processing time every month. That&amp;#39;s about 1175 man hours wasted throughout the world by millions of people staring at browser waiting for content to download.&lt;/p&gt; &lt;p&gt;Such a content proxy takes an external server&amp;#39;s URL as a query parameter. It downloads the content from the URL and then writes the content as response back to browser. &lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image1.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image1_thumb.png" alt="image" border="0" height="107" width="532" /&gt;&lt;/a&gt;&lt;br /&gt;Figure: Content Proxy working as a middleman between browser and external domain &lt;/p&gt; &lt;p&gt;The above timeline shows how request goes to the server and then server makes a request to external server, downloads the response and then transmits back to the browser. The response arrow from proxy to browser is larger than the response arrow from external server to proxy because generally proxy server&amp;#39;s hosting environment has better download speed than the user&amp;#39;s Internet connectivity.&lt;/p&gt; &lt;p&gt;Such a content proxy is also available in my open source Ajax Web Portal &lt;a href="http://www.dropthings.com/"&gt;Dropthings.com&lt;/a&gt;. You can see from &lt;a href="http://www.codeplex.com/dropthings"&gt;its code&lt;/a&gt; how such a proxy is implemented.&lt;/p&gt; &lt;p&gt;The following is a very simple synchronous, non-streaming, blocking Proxy:&lt;/p&gt; &lt;div class="csharpcode-wrapper" style="width:94.38%;height:192px;"&gt;&lt;pre class="csharpcode" style="width:63.65%;height:176px;"&gt;[WebMethod]&lt;br /&gt;[ScriptMethod(UseHttpGet=&lt;span class="kwrd"&gt;true&lt;/span&gt;)]&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetString(&lt;span class="kwrd"&gt;string&lt;/span&gt; url)&lt;br /&gt;{&lt;br /&gt;        &lt;span class="kwrd"&gt;using&lt;/span&gt; (WebClient client = &lt;span class="kwrd"&gt;new&lt;/span&gt; WebClient())&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; response = client.DownloadString(url);&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; response;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Although it shows the general principle, but it&amp;#39;s no where close to a real proxy because:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&amp;#39;s a synchronous proxy and thus not scalable. Every call to this web method causes the ASP.NET thread to wait until the call to the external URL completes. 
&lt;/li&gt;&lt;li&gt;It&amp;#39;s &lt;b&gt;non streaming&lt;/b&gt;. It first downloads the entire content on the server, storing it in a string and then uploading that entire content to the browser. If you pass &lt;a href="http://msdn.microsoft.com/rss.xml"&gt;MSDN feed URL&lt;/a&gt;, it will download that gigantic 220 KB RSS XML on the server and store it on a 220 KB long string (actually double the size as .NET strings are all Unicode string) and then write 220 KB to&amp;nbsp; ASP.NET Response buffer, consuming another 220 KB UTF8 byte array in memory. Then that 220 KB will be passed to IIS in chunks so that it can transmit it to the browser. 
&lt;/li&gt;&lt;li&gt;It does not produce proper response header to cache the response on the server. Nor does it deliver important headers like &lt;i&gt;Content-Type&lt;/i&gt; from the source. 
&lt;/li&gt;&lt;li&gt;If external URL is providing gzipped content, it decompresses the content into a string representation and thus wastes server memory. 
&lt;/li&gt;&lt;li&gt;It does not cache the content on the server. So, repeated call to the same external URL within the same second or minute will download content from the external URL and thus waste bandwidth on your server. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;So, we need an asynchronous &lt;b&gt;streaming proxy&lt;/b&gt; that transmits the content to the browser while it downloads from the external domain server. So, it will download bytes from external URL in small chunks and immediately transmit that to the browser. As a result, browser will see a continuous transmission of bytes right after calling the web service. There will be no delay while the content is fully downloaded on the server.&lt;/p&gt;
&lt;p&gt;Before I show you the complex streaming proxy code, let&amp;#39;s take an evolutionary approach. Let&amp;#39;s build a better Content Proxy that the one shown above, which is synchronous, non-streaming but does not have the other problems mentioned above. We will build a HTTP Handler named &lt;u&gt;RegularProxy.ashx&lt;/u&gt; which will take &lt;u&gt;url&lt;/u&gt; as a query parameter. It will also take &lt;u&gt;cache&lt;/u&gt; as a query parameter which it will use to produce proper response headers in order to cache the content on the browser. Thus it will save browser from downloading the same content again and again.&lt;/p&gt;
&lt;div&gt;&lt;pre class="csharpcode"&gt;&amp;lt;%@ WebHandler Language=&lt;span class="str"&gt;&amp;quot;C#&amp;quot;&lt;/span&gt; Class=&lt;span class="str"&gt;&amp;quot;RegularProxy&amp;quot;&lt;/span&gt; %&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Web.Caching;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Net;&lt;br /&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; ProxyHelpers;&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; RegularProxy : IHttpHandler {&lt;br /&gt;        &lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ProcessRequest (HttpContext context) {&lt;br /&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; url = context.Request[&lt;span class="str"&gt;&amp;quot;url&amp;quot;&lt;/span&gt;];&lt;br /&gt;        &lt;span class="kwrd"&gt;int&lt;/span&gt; cacheDuration = Convert.ToInt32(context.Request[&lt;span class="str"&gt;&amp;quot;cache&amp;quot;&lt;/span&gt;]?? &lt;span class="str"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;);&lt;br /&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; contentType = context.Request[&lt;span class="str"&gt;&amp;quot;type&amp;quot;&lt;/span&gt;];&lt;br /&gt;&lt;br /&gt;        &lt;span class="rem"&gt;// We don&amp;#39;t want to buffer because we want to save memory&lt;/span&gt;&lt;br /&gt;        context.Response.Buffer = &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;            &lt;br /&gt;        &lt;span class="rem"&gt;// Serve from cache if available&lt;/span&gt;&lt;br /&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (context.Cache[url] != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br /&gt;        {&lt;br /&gt;            context.Response.BinaryWrite(context.Cache[url] &lt;span class="kwrd"&gt;as&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[]);&lt;br /&gt;            context.Response.Flush();&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;        &lt;span class="kwrd"&gt;using&lt;/span&gt; (WebClient client = &lt;span class="kwrd"&gt;new&lt;/span&gt; WebClient())&lt;br /&gt;        {&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(contentType))&lt;br /&gt;                client.Headers[&lt;span class="str"&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;] = contentType;&lt;br /&gt;            &lt;br /&gt;            client.Headers[&lt;span class="str"&gt;&amp;quot;Accept-Encoding&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;gzip&amp;quot;&lt;/span&gt;;&lt;br /&gt;            client.Headers[&lt;span class="str"&gt;&amp;quot;Accept&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;*/*&amp;quot;&lt;/span&gt;;&lt;br /&gt;            client.Headers[&lt;span class="str"&gt;&amp;quot;Accept-Language&amp;quot;&lt;/span&gt;] = &lt;span class="str"&gt;&amp;quot;en-US&amp;quot;&lt;/span&gt;;&lt;br /&gt;            client.Headers[&lt;span class="str"&gt;&amp;quot;User-Agent&amp;quot;&lt;/span&gt;] = &lt;br /&gt;&lt;span class="str"&gt;&amp;quot;Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6&amp;quot;&lt;/span&gt;;&lt;br /&gt;            &lt;br /&gt;            &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] data = client.DownloadData(url);&lt;br /&gt;&lt;br /&gt;            context.Cache.Insert(url, data, &lt;span class="kwrd"&gt;null&lt;/span&gt;,&lt;br /&gt;                        Cache.NoAbsoluteExpiration,&lt;br /&gt;                        TimeSpan.FromMinutes(cacheDuration),&lt;br /&gt;                        CacheItemPriority.Normal, &lt;span class="kwrd"&gt;null&lt;/span&gt;); &lt;br /&gt;            &lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!context.Response.IsClientConnected) &lt;span class="kwrd"&gt;return&lt;/span&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;br /&gt;            &lt;span class="rem"&gt;// Deliver content type, encoding and length as it is received from the external URL&lt;/span&gt;&lt;br /&gt;            context.Response.ContentType = client.ResponseHeaders[&lt;span class="str"&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;];&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; contentEncoding = client.ResponseHeaders[&lt;span class="str"&gt;&amp;quot;Content-Encoding&amp;quot;&lt;/span&gt;];&lt;br /&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; contentLength = client.ResponseHeaders[&lt;span class="str"&gt;&amp;quot;Content-Length&amp;quot;&lt;/span&gt;];&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(contentEncoding))&lt;br /&gt;                context.Response.AppendHeader(&lt;span class="str"&gt;&amp;quot;Content-Encoding&amp;quot;&lt;/span&gt;, contentEncoding);&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(contentLength))&lt;br /&gt;                context.Response.AppendHeader(&lt;span class="str"&gt;&amp;quot;Content-Length&amp;quot;&lt;/span&gt;, contentLength);&lt;br /&gt;&lt;br /&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (cacheDuration &amp;gt; 0)&lt;br /&gt;                HttpHelper.CacheResponse(context, cacheDuration);&lt;br /&gt;            &lt;br /&gt;            &lt;span class="rem"&gt;// Transmit the exact bytes downloaded&lt;/span&gt;&lt;br /&gt;            context.Response.BinaryWrite(data);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsReusable {&lt;br /&gt;        get {&lt;br /&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There are two enhancements in this proxy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It allows server side caching of content. Same URL requested by a different browser within a time period will not be downloaded on server again, instead it will be served from cache. 
&lt;/li&gt;&lt;li&gt;It generates proper response cache header so that the content can be cached on browser. 
&lt;/li&gt;&lt;li&gt;It does not decompress the downloaded content in memory. It keeps the original byte stream intact. This saves memory allocation. 
&lt;/li&gt;&lt;li&gt;It transmits the data in non-buffered fashion, which means ASP.NET Response object does not buffer the response and thus saves memory&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;However, this is a blocking proxy. We need to make a streaming asynchronous proxy for better performance. Here&amp;#39;s why:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_8.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_thumb_3.png" alt="image" border="0" height="128" width="497" /&gt;&lt;/a&gt;&amp;nbsp;&lt;br /&gt;Figure: Continuous streaming proxy&lt;/p&gt;
&lt;p&gt;As you see, when data is transmitted from server to browser while server downloads the content, the delay for server side download is eliminated. So, if server takes 300ms to download something from external source, and then 700ms to send it back to browser, you can save up to 300ms Network Latency between server and browser. The situation gets even better when the external server that serves the content is slow and takes quite some time to deliver the content. The slower external site is, the more saving you get in this continuous streaming approach. This is significantly faster than blocking approach when the external server is in Asia or Australia and your server is in USA. &lt;/p&gt;
&lt;p&gt;The approach for continuous proxy is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read bytes from external server in chunks of 8KB from a separate thread (Reader thread) so that it&amp;#39;s not blocked 
&lt;/li&gt;&lt;li&gt;Store the chunks in an in-memory Queue 
&lt;/li&gt;&lt;li&gt;Write the chunks to ASP.NET Response from that same queue 
&lt;/li&gt;&lt;li&gt;If the queue is finished, wait until more bytes are downloaded by the reader thread&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image15.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image15_thumb.png" alt="image" border="0" height="180" width="551" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;The Pipe Stream needs to be thread safe and it needs to support blocking Read. By blocking read it means, if a thread tries to read a chunk from it and the stream is empty, it will suspend that thread until another thread writes something on the stream. Once a write happens, it will resume the reader thread and allow it to read. I have taken the code of &lt;u&gt;PipeStream&lt;/u&gt; from &lt;a href="http://www.codeproject.com/KB/threads/PipeStream.aspx"&gt;CodeProject article by James Kolpack&lt;/a&gt; and extended it to make sure it&amp;#39;s high performance, supports chunks of bytes to be stored instead of single bytes, support timeout on waits and so on. &lt;/p&gt;
&lt;p&gt;A did some comparison between Regular proxy (blocking, synchronous, download all then deliver) and Streaming Proxy (continuous transmission from external server to browser). Both proxy downloads the MSDN feed and delivers it to the browser. The time taken here shows the total duration of browser making the request to the proxy and then getting the entire response.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_14.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_thumb_4.png" alt="image" border="0" height="230" width="381" /&gt;&lt;/a&gt; &lt;br /&gt;Figure: Time taken by Streaming Proxy vs Regular Proxy while downloading MSDN feed&lt;/p&gt;
&lt;p&gt;Not a very scientific graph and response time varies on the link speed between the browser and the proxy server and then from proxy server to the external server. But it shows that most of the time, Streaming Proxy outperformed Regular proxy.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_18.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_thumb_7.png" alt="image" border="0" height="373" width="457" /&gt;&lt;/a&gt; &lt;br /&gt;Figure: Test client to compare between Regular Proxy and Streaming Proxy&lt;/p&gt;
&lt;p&gt;You can also test both proxy&amp;#39;s response time by going to &lt;a href="http://labs.dropthings.com/AjaxStreamingProxy"&gt;http://labs.dropthings.com/AjaxStreamingProxy&lt;/a&gt;. Put your URL and hit Regular/Stream button and see the &amp;quot;Statistics&amp;quot; text box for the total duration. You can turn on &amp;quot;Cache response&amp;quot; and hit a URL from one browser. Then go to another browser and hit the URL to see the response coming from server cache directly. Also if you hit the URL again on the same browser, you will see response comes instantly without ever making call to the server. That&amp;#39;s browser cache at work.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Learn more about Http Response caching from my blog post:&lt;br /&gt;&lt;a href="http://feeds.feedburner.com/%7Er/OmarAlZabirBlog/%7E3/267239050/making-best-use-of-cache-for-high-performance-website.aspx"&gt;Making best use of cache for high performance website&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;p&gt;A Visual Studio Web Test run inside a Load Test shows a better picture:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_24.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_thumb_10.png" alt="image" border="0" height="200" width="512" /&gt;&lt;/a&gt;&amp;nbsp;&lt;br /&gt;Figure: Regular Proxy load test result shows &lt;b&gt;Average Requests/Sec 0.79&lt;/b&gt; and &lt;b&gt;Avg Response Time 2.5 sec&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_26.png"&gt;&lt;img src="http://msmvps.com/blogs/omar/WindowsLiveWriter/FastStreamingAJAXproxy_A628/image_thumb_11.png" alt="image" border="0" height="214" width="506" /&gt;&lt;/a&gt;&lt;br /&gt;Figure: Streaming Proxy load test result shows &lt;b&gt;Avg Req/Sec is 1.08&lt;/b&gt; and &lt;b&gt;Avg Response Time 1.8 sec&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;From the above load test results, Streaming Proxy is &lt;b&gt;26% better Request/Sec and Average Response Time is 29% better&lt;/b&gt;. The numbers may sound small, but at Pageflakes, 29% better response time means &lt;b&gt;1.29 million seconds&lt;/b&gt; saved per month for all the users on the website. So, we are effectively saving 353 man hours per month which was wasted staring at browser screen while it downloads content.&lt;/p&gt;
&lt;h3&gt;Building the Streaming Proxy&lt;/h3&gt;&lt;p&gt;The details how the Streaming Proxy is built is quite long and not suitable for a blog post. So, I have written a CodeProject article:&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.codeproject.com/KB/ajax/ajaxproxy.aspx"&gt;Fast, Scalable, Streaming AJAX Proxy - continuously deliver data from cross domain&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Please read the article and please vote for me if your find it useful. &amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1586081" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net+ajax/default.aspx">asp.net ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/pageflakes/default.aspx">pageflakes</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>10 ASP.NET Performance and Scalability Secrets</title><link>http://msmvps.com/blogs/omar/archive/2008/01/30/10-asp-net-performance-and-scalability-secrets.aspx</link><pubDate>Wed, 30 Jan 2008 15:47:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1486901</guid><dc:creator>omar</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1486901</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/01/30/10-asp-net-performance-and-scalability-secrets.aspx#comments</comments><description>&lt;p&gt;ASP.NET 2.0 has many secrets, when revealed, can give you big performance and
scalability boost. For instance, there are secret bottlenecks in Membership and Profile
provider which can be solved easily to make authentication and authorization faster.
Furthermore, ASP.NET Http pipeline can be tweaked to avoid executing unnecessary code
that gets hit on each and every request. Not only that, ASP.NET Worker Process can be
pushed to its limit to squeeze out every drop of performance out of it. Page fragment
output caching on the browser (not on the server) can save significant amount of download
time on repeated visits. On demand UI loading can give your site a fast and smooth
feeling. Finally, Content Delivery Networks (CDN) and proper use of HTTP Cache headers
can make your website screaming fast when implemented properly. In this article, you will
learn these techniques that can give your ASP.NET application a big performance and
scalability boost and prepare it to perform well under 10 times to 100 times more
traffic.&lt;/p&gt;
&lt;p&gt;
&lt;a title="http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx" href="http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx"&gt;http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;In this article I have shown the following techniques:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ASP.NET Pipeline optimization&lt;/li&gt;
&lt;li&gt;ASP.NET Process configuration optimization&lt;/li&gt;
&lt;li&gt;Things you must do for ASP.NET before going live&lt;/li&gt;
&lt;li&gt;Content Delivery Network&lt;/li&gt;
&lt;li&gt;Caching AJAX calls on browser&lt;/li&gt;
&lt;li&gt;Making best use of Browser Cache&lt;/li&gt;
&lt;li&gt;On demand progressive UI loading for fast smooth experience&lt;/li&gt;
&lt;li&gt;Optimize ASP.NET 2.0 Profile provider&lt;/li&gt;
&lt;li&gt;How to query ASP.NET 2.0 Membership tables without bringing down the site&lt;/li&gt;
&lt;li&gt;Prevent Denial of Service (DOS) attack&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above techniques can be implemented on any ASP.NET website especially those who
use ASP.NET 2.0&amp;#39;s Membership and Profile provider.&lt;/p&gt;
&lt;p&gt;You can learn a lot more about performance and scalability improvement of ASP.NET and
ASP.NET AJAX websites from my book - 
&lt;a href="http://www.oreilly.com/catalog/9780596510503/"&gt;Building a Web 2.0 portal using
ASP.NET 3.5&lt;/a&gt;.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1486901" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/performance/default.aspx">performance</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/production/default.aspx">production</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>My first book - Building a Web 2.0 Portal with ASP.NET 3.5</title><link>http://msmvps.com/blogs/omar/archive/2008/01/13/my-first-book-building-a-web-2-0-portal-with-asp-net-3-5.aspx</link><pubDate>Sun, 13 Jan 2008 20:23:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1461326</guid><dc:creator>omar</dc:creator><slash:comments>44</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1461326</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2008/01/13/my-first-book-building-a-web-2-0-portal-with-asp-net-3-5.aspx#comments</comments><description>&lt;p&gt;My first book &amp;quot;&lt;a href="http://www.oreilly.com/catalog/9780596510503/" target="_blank"&gt;Building a Web 2.0 Portal with ASP.NET 3.5&lt;/a&gt;&amp;quot; from O&amp;#39;Reilly is published and available in the stores. This book explains in detail the architecture design, development, test, deployment, performance and scalability challenges of my open source web portal &lt;a href="http://www.dropthings.com" target="_blank"&gt;Dropthings.com&lt;/a&gt;. Dropthings is a prototype of a web portal similar to &lt;a href="http://www.google.com/ig" target="_blank"&gt;iGoogle&lt;/a&gt; or &lt;a href="http://www.pageflakes.com" target="_blank"&gt;Pageflakes&lt;/a&gt;. But this portal is developed using recently released brand new technologies like ASP.NET 3.5, C# 3.0, Linq to Sql, Linq to XML, and Windows Workflow foundation. It makes heavy use of ASP.NET AJAX 1.0. Throughout my career I have built several state-of-the-art &lt;a href="http://omar.mvps.org" target="_blank"&gt;personal&lt;/a&gt;, educational, enterprise and &lt;a href="http://www.pageflakes.com" target="_blank"&gt;mass consumer web portals&lt;/a&gt;. This book collects my experience in building all of those portals.&lt;/p&gt;&lt;p&gt;O&amp;#39;Reilly Website:&lt;br /&gt;&lt;a href="http://www.oreilly.com/catalog/9780596510503/"&gt;http://www.oreilly.com/catalog/9780596510503/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Amazon:&lt;br /&gt;&lt;a href="http://www.amazon.com/Building-Web-2-0-Portal-ASP-NET/dp/0596510500"&gt;http://www.amazon.com/Building-Web-2-0-Portal-ASP-NET/dp/0596510500&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;Disclaimer: This book does not show you how to build Pageflakes. Dropthings is entirely different in terms of architecture, implementation and the technologies involved.&lt;/p&gt; &lt;p&gt;You learn how to: &lt;/p&gt; &lt;ul&gt; &lt;li&gt;Implement a highly decoupled architecture following the popular n-tier, widget-based application model  &lt;/li&gt;&lt;li&gt;Provide drag-and-drop functionality, and use ASP.NET 3.5 to build the server-side part of the web layer  &lt;/li&gt;&lt;li&gt;Use LINQ to build the data access layer, and Windows Workflow Foundation to build the business layer as a collection of workflows  &lt;/li&gt;&lt;li&gt;Build client-side widgets using JavaScript for faster performance and better caching  &lt;/li&gt;&lt;li&gt;Get maximum performance out of the ASP.NET AJAX Framework for faster, more dynamic, and scalable sites  &lt;/li&gt;&lt;li&gt;Build a custom web service call handler to overcome shortcomings in ASP.NET AJAX 1.0 for asynchronous, transactional, cache-friendly web services  &lt;/li&gt;&lt;li&gt;Overcome JavaScript performance problems, and help the user interface load faster and be more responsive  &lt;/li&gt;&lt;li&gt;Solve various scalability and security problems as your site grows from hundreds to millions of users  &lt;/li&gt;&lt;li&gt;Deploy and run a high-volume production site while solving software, hardware, hosting, and Internet infrastructure problems &lt;/li&gt;&lt;/ul&gt;If you&amp;#39;re ready to build state-of-the art, high-volume web applications that can withstand millions of hits per day, this book has exactly what you need.&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1461326" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/sql+server/default.aspx">sql server</category><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/pageflakes/default.aspx">pageflakes</category><category domain="http://msmvps.com/blogs/omar/archive/tags/production/default.aspx">production</category><category domain="http://msmvps.com/blogs/omar/archive/tags/linq/default.aspx">linq</category><category domain="http://msmvps.com/blogs/omar/archive/tags/workflow/default.aspx">workflow</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/IIS/default.aspx">IIS</category></item><item><title>On-demand UI loading on AJAX websites</title><link>http://msmvps.com/blogs/omar/archive/2007/11/09/on-demand-ui-loading-on-ajax-websites.aspx</link><pubDate>Fri, 09 Nov 2007 09:01:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1289498</guid><dc:creator>omar</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1289498</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2007/11/09/on-demand-ui-loading-on-ajax-websites.aspx#comments</comments><description>&lt;p&gt;AJAX websites are all about loading as many features as possible
into the browser without having any postback. If you look at the
Start Pages like 
&lt;a href="http://www.pageflakes.com"&gt;Pageflakes&lt;/a&gt;, it&amp;#39;s only one
single page that gives you all the features of the whole
application with zero postback. A quick and dirty approach for
doing this is to deliver every possible html snippets inside hidden
divs during page load and then make those divs visible when needed.
But this makes first time loading way too long and browser gives
sluggish performance as too much stuff is on the DOM. So, a better
approach is to load html snippet and necessary javascript
on-demand. In my 
&lt;a href="http://www.dropthings.com"&gt;dropthings&lt;/a&gt; project, I have
shown an example how this is done.&lt;/p&gt;
&lt;p&gt;
&lt;img height="424" alt="clip_image002" src="http://omar.mvps.org/images/IncrementalUIloadingonAJAXwebsites_12E95/clip_image002.gif" width="480" /&gt;
&lt;/p&gt;
&lt;p&gt;When you click on the &amp;quot;help&amp;quot; link, it loads the content of the
help dynamically. This html is not delivered as part of the 
&lt;u&gt;default.aspx&lt;/u&gt; that renders the first page. Thus the giant
html and graphics related to the help section has no effect on site
load performance. It is only loaded when user clicks the &amp;quot;help&amp;quot;
link. Moreover, it gets cached on the browser and thus loads only
once. When user clicks the &amp;quot;help&amp;quot; link again, it&amp;#39;s served directly
from the browser cache, instead of fetching from the origin server
again.&lt;/p&gt;
&lt;p&gt;The principle is making an XMLHTTP call to an 
&lt;u&gt;.aspx&lt;/u&gt; page, get the response html, put that response html
inside a container DIV, make that DIV visible.&lt;/p&gt;
&lt;p&gt;AJAX framework has a 
&lt;u&gt;Sys.Net.WebRequest&lt;/u&gt; class which you can use to make regular
HTTP calls. You can define http method, URI, headers and the body
of the call. It&amp;rsquo;s kind of a low level function for making
direct calls via XMLHTTP. Once you construct a web request, you can
execute it using 
&lt;u&gt;Sys.Net.XMLHttpExecutor&lt;/u&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   1:&lt;/span&gt; function showHelp()
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   2:&lt;/span&gt; {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   3:&lt;/span&gt;     var request = 
&lt;span class="kwrd"&gt;new&lt;/span&gt; Sys.Net.WebRequest();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   4:&lt;/span&gt;     request.set_httpVerb(
&lt;span class="str"&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   5:&lt;/span&gt;     request.set_url(
&lt;span class="str"&gt;&amp;#39;help.aspx&amp;#39;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   6:&lt;/span&gt;     request.add_completed(
function( executor )
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   7:&lt;/span&gt;     {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   8:&lt;/span&gt;         
&lt;span class="kwrd"&gt;if&lt;/span&gt; (executor.get_responseAvailable()) 
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   9:&lt;/span&gt;         {
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  10:&lt;/span&gt;             var helpDiv = $get(
&lt;span class="str"&gt;&amp;#39;HelpDiv&amp;#39;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  11:&lt;/span&gt;             var helpLink = $get(
&lt;span class="str"&gt;&amp;#39;HelpLink&amp;#39;&lt;/span&gt;);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  12:&lt;/span&gt;             
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  13:&lt;/span&gt;             var helpLinkBounds =
Sys.UI.DomElement.getBounds(helpLink);
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  14:&lt;/span&gt;             
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  15:&lt;/span&gt;             helpDiv.style.top =
(helpLinkBounds.y + helpLinkBounds.height) + 
&lt;span class="str"&gt;&amp;quot;px&amp;quot;&lt;/span&gt;;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  16:&lt;/span&gt;             
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  17:&lt;/span&gt;             var content =
executor.get_responseData();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  18:&lt;/span&gt;             helpDiv.innerHTML =
content;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  19:&lt;/span&gt;             helpDiv.style.display =

&lt;span class="str"&gt;&amp;quot;block&amp;quot;&lt;/span&gt;;                       
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  20:&lt;/span&gt;         }
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  21:&lt;/span&gt;     });
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  22:&lt;/span&gt;     
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  23:&lt;/span&gt;     var executor = 
&lt;span class="kwrd"&gt;new&lt;/span&gt; Sys.Net.XMLHttpExecutor();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  24:&lt;/span&gt;     request.set_executor(executor);

&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  25:&lt;/span&gt;     executor.executeRequest();
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;  26:&lt;/span&gt; }
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The example shows how the help section is loaded by hitting 
&lt;u&gt;help.aspx&lt;/u&gt; and injecting its response inside the 
&lt;u&gt;HelpDiv&lt;/u&gt;. The response can be cached by the 
&lt;a&gt;output cache directive&lt;/a&gt; set on 
&lt;u&gt;help.aspx&lt;/u&gt;. So, next time when user clicks on the link, the
UI pops up immediately. The 
&lt;u&gt;help.aspx&lt;/u&gt; file has no 
&lt;u&gt;&amp;lt;html&amp;gt;&lt;/u&gt; block, only the content that is set inside the 
&lt;a&gt;DIV&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div class="csharpcode"&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   1:&lt;/span&gt; 
&lt;span class="asp"&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; AutoEventWireup=&amp;quot;true&amp;quot;
CodeFile=&amp;quot;Help.aspx.cs&amp;quot; Inherits=&amp;quot;Help&amp;quot; %&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   2:&lt;/span&gt; 
&lt;span class="asp"&gt;&amp;lt;%@ OutputCache Location=&amp;quot;ServerAndClient&amp;quot;
Duration=&amp;quot;604800&amp;quot; VaryByParam=&amp;quot;none&amp;quot; %&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   3:&lt;/span&gt; 
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;
&lt;span class="html"&gt;div&lt;/span&gt; 
&lt;span class="attr"&gt;class&lt;/span&gt;
&lt;span class="kwrd"&gt;=&amp;quot;helpContent&amp;quot;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   4:&lt;/span&gt; 
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;
&lt;span class="html"&gt;div&lt;/span&gt; 
&lt;span class="attr"&gt;id&lt;/span&gt;
&lt;span class="kwrd"&gt;=&amp;quot;lipsum&amp;quot;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   5:&lt;/span&gt; 
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;
&lt;span class="html"&gt;p&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   6:&lt;/span&gt; Lorem ipsum dolor sit amet,
consectetuer adipiscing elit. Duis lorem
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   7:&lt;/span&gt; eros, volutpat sit amet, venenatis
vitae, condimentum at, dolor. Nunc
&lt;/pre&gt;
&lt;pre&gt;
&lt;span class="lnum"&gt;   8:&lt;/span&gt; porttitor eleifend tellus. Praesent
vitae neque ut mi rutrum cursus.
&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Using this approach, you can break the UI into smaller 
&lt;u&gt;.aspx&lt;/u&gt; files. Although these 
&lt;u&gt;.aspx&lt;/u&gt; files cannot have JavaScript or stylesheet blocks, but
they can contain large amount of html that you need to show on the
UI on-demand. Thus you can keep initial download to absolute
minimum just for loading the basic stuffs. When user explores new
features on the site, load those areas incrementally.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1289498" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item><item><title>10 cool web development related articles in 2007</title><link>http://msmvps.com/blogs/omar/archive/2007/10/02/10-cool-web-development-related-articles-in-2007.aspx</link><pubDate>Tue, 02 Oct 2007 17:26:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1225686</guid><dc:creator>omar</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/omar/rsscomments.aspx?PostID=1225686</wfw:commentRss><comments>http://msmvps.com/blogs/omar/archive/2007/10/02/10-cool-web-development-related-articles-in-2007.aspx#comments</comments><description>&lt;p&gt;Here&amp;#39;s a list of 10 cool ASP.NET, AJAX and web development related articles and blog posts that I have written this year that you might want to take a look:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.codeproject.com/install/13disasters.asp"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.codeproject.com/install/13disasters.asp"&gt;13 disasters for production website and their solutions&lt;/a&gt; &lt;br /&gt;Talks about 13 production disasters that can happen to any website any time and bring down your business.&amp;nbsp;&lt;/p&gt;&lt;a href="http://www.codeproject.com/Ajax/MakingGoogleIG.asp"&gt;Build Google IG like Ajax Start Page in 7 days using ASP.NET Ajax and .NET 3.0&lt;/a&gt; &lt;br /&gt;This block buster article shows how ASP.NET AJAX, Linq to XML, Linq to SQL and Workflow Foundation can be used to create a Google IG like start page in just 7 nights. Learn how to put together such hot technologies into one project and make a production site out of it.  &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/04/29/serve-extensionless-url-from-asp-net-without-using-isapi-module-or-iis-6-wildcard-mapping.aspx"&gt;Serve extensionless URL from ASP.NET without using ISAPI module or IIS 6 Wildcard mapping&lt;/a&gt; &lt;br /&gt;Currently there are only two ways to service extentionless URL like &lt;a href="http://www.pageflakes.com/omar"&gt;www.pageflakes.com/omar&lt;/a&gt; that hits something besides the default document - use a custom ISAPI module or use IIS 6 wildcard mapping. Both has performance and scalability problems because both intercepts each and every hit. Learn how you can solve it by using a custom 404 handler.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/09/19/request-format-is-unrecognized-for-url-unexpectedly-ending-in-somewebservicemethod.aspx"&gt;Request format is unrecognized for URL unexpectedly ending in /SomeWebServiceMethod&lt;/a&gt; &lt;br /&gt;Since ASP.NET AJAX 1.0 release, Microsoft prevented JSON hijacking by adding a special content type header. But this caused us some trouble. &lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/25/cleanup-inactive-anonymous-users-from-asp-net-membership-tables.aspx"&gt;Cleanup inactive anonymous users from ASP.NET Membership Tables&lt;/a&gt; &lt;br /&gt;When you store anonymous user profile using ASP.NET Membership provider and Anonymous Identification provider, you soon end up with lots of idle anonymous user data where those users never come back. We (Pageflakes) went through a lot of difficulty keeping our database size down as we allow anonymous users to do almost everything that a registered user can do. This introduces scalability challenge. See how we solved this problem.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/24/prevent-denial-of-service-dos-attacks-in-your-web-application.aspx"&gt;Prevent Denial of Service (DOS) attacks in your web application&lt;/a&gt; &lt;br /&gt;Web applications can be brought down to its knees by hitting the site repeatedly or by calling expensive webservices randomly. Anyone can write a simple loop that hits a webserver very frequently from a high bandwidth connectivity and bring your production server down. See how to prevent such application level DOS attacks.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/22/asp-net-ajax-extender-for-multi-column-widget-drag-drop.aspx"&gt;ASP.NET Ajax Extender for multi-column widget drag &amp;amp; drop&lt;/a&gt; &lt;br /&gt;It&amp;#39;s an ASP.NET AJAX extender that allows Pageflakes style drag &amp;amp; drop functionality between columns and rows. &lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/03/16/asp-net-ajax-in-depth-performance-analysis.aspx"&gt;ASP.NET Ajax in-depth performance analysis&lt;/a&gt; &lt;br /&gt;While building an open source start page using ASP.NET AJAX, I have done a lot of performance analysis on AJAX framework in order to improve first time load and perceived speed of javascript rich pages. Check out my analysis.&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/01/20/think-you-know-how-to-write-update-statement-think-again.aspx"&gt;Think you know how to write UPDATE statement? Think again.&lt;/a&gt; &lt;br /&gt;Learn how to optimize common UPDATE statements&lt;/p&gt; &lt;p&gt;&lt;a href="http://msmvps.com/blogs/omar/archive/2007/01/07/make-a-surveillance-application-which-captures-desktop-and-emails-you-as-attachment.aspx"&gt;Make a surveillance application which captures desktop and then emails you as attachment&lt;/a&gt; &lt;br /&gt;Some time back I needed to capture a certain computers desktop in order to find out what that user is doing every day. So, I made a .NET 2.0 Winforms Application which stays on system tray (optional) and capture the desktop in given time interval (say every 60 secs) and emailed the captured images to me as message attachment (say every 30 mins).&lt;/p&gt; &lt;hr /&gt;  &lt;p&gt;Today I received MVP award for the 3rd time on Visual C#. Thanks to Microsoft for the award and setting up my &lt;a href="http://weblogs.asp.net/omarzabir"&gt;new blog&lt;/a&gt;. I will continue both my &lt;a href="http://msmvps.com/omar"&gt;MVPS Blog&lt;/a&gt; and this blog from now on.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1225686" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/omar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://msmvps.com/blogs/omar/archive/tags/production/default.aspx">production</category><category domain="http://msmvps.com/blogs/omar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://msmvps.com/blogs/omar/archive/tags/ajax/default.aspx">ajax</category><category domain="http://msmvps.com/blogs/omar/archive/tags/.net/default.aspx">.net</category></item></channel></rss>