<rss version="2.0"><channel><title>DotNetSlackers: ASP.NET News for lazy Developers</title><link>http://dotnetslackers.com/</link><description>Latest combined ASP.NET news from DotNetSlackers.</description><ttl>60</ttl><item><title>ASP.NET 4.0 and the Entity Framework 4 - Part 1 - Create a Database using Model-First Development</title><link>http://aspalliance.com/1912_ASPNET_40_and_the_Entity_Framework_4__Part_1__Create_a_Database_using_ModelFirst_Development</link><description>This is the first in a series of articles that will develop an ASP.NET application that uses the Entity Framework 4.  This article will demonstrate how to use Visual Studio 2010 and the Entity Framework 4 to create a database in a step-by-step approach. The database created in this article will then be used in future articles to demonstrate how to add, update, delete, and select records using the Entity Framework.</description><author>ASPAlliance.com - The #1 ASP.NET Community                                                          </author><pubDate>Tue, 09 Feb 2010 00:00:00 GMT</pubDate></item><item><title>ASP.NET Horizontal Menu Control</title><link>http://aspalliance.com/1916_ASPNET_Horizontal_Menu_Control</link><description>A few weeks ago, I was working on an ASP.NET web application and needed a simple horizontal menu with a submenu. I decided to use ASP.NET's Menu control: Just drag and drop the control on to the page. Simple enough, but the control did not provide access key and target window support on menu items. I have put together a tutorial on how to include an access key attribute, include a target attribute, and include a site map path.</description><author>ASPAlliance.com - The #1 ASP.NET Community                                                          </author><pubDate>Tue, 02 Feb 2010 00:00:00 GMT</pubDate></item><item><title>IIS URL Rewrite  Hosting multiple domains under one site</title><link>http://weblogs.asp.net/owscott/archive/2010/01/26/iis-url-rewrite-hosting-multiple-domains-under-one-site.aspx</link><description>&lt;p&gt;In a shared hosting environment, its a common desire to have a single IIS website that handles multiple sites with different domain names.&amp;#160; This saves the cost of setting up additional sites with the hoster.&amp;#160; &lt;/p&gt;  &lt;p&gt;At &lt;a href="http://www.orcsweb.com" target="_blank"&gt;ORCS Web&lt;/a&gt;, weve supported this situation for many years using ISAPI Rewrite.&amp;#160; Now, with &lt;a href="http://www.iis.net/expand/URLRewrite" target="_blank"&gt;URL Rewrite&lt;/a&gt; for IIS 7, its easier and its integrated right into web.config.&amp;#160; In this blog post Ill set out to cover the essentials for hosting multiple domain names under a single account using URL Rewrite.&lt;/p&gt;  &lt;p&gt;This post assumes that you are using URL Rewrite 1.0, 1.1 or 2.0.&amp;#160; Ill follow-up in a later post on more advanced ways to take this further yet, using the new features of URL Rewrite 2.0.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;First, the file structure&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Lets lay out the directory structure for this example.&amp;#160; Assume that you have 3 domain names.&amp;#160; They are: masterdomain.com, site2.com and hawaiivisit.site2.com.&amp;#160; Youve created your directory structure like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/owscott/image_1C67C112.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/owscott/image_thumb_49E8E0D5.png" width="164" height="70" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Lets assume that masterdomain.com was already in the root of the site and cant easily be moved.&amp;#160; However, site2.com and hawaiivisit.site.com need to be set up.&amp;#160; Each of these folders have a website within them.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Directing the domain name to the server&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;First, make sure that when you browse to the website by domain name, that it resolves to the correct IP address.&amp;#160; This is handled at the DNS level.&amp;#160; Your DNS entry for site2.com and hawaiivisit.site2.com will often be identical to masterdomain.com and are managed through your DNS provider.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Catching the site when on the server&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If you host with a web hosting company then they will take care of this.&amp;#160; If you host yourself, make sure to set a site binding so that the expected site processes the domain name.&amp;#160; If you use host headers, be sure to add the extra bindings for them.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Redirecting the site to a subfolder&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Now that you have the domain name directed to the server and site, URL Rewrite comes in to direct it to a subfolder.&lt;/p&gt;  &lt;p&gt;First, make sure that your web host supports URL Rewrite on the server that youre hosted on.&amp;#160; The following assumes that its installed and supported.&lt;/p&gt;  &lt;p&gt;You can use IIS 7 Manager which gives a friendly interface for creating rules.&amp;#160; If you prefer to write them directly in web.config, Ill include the rules below.&lt;/p&gt;  &lt;p&gt;First, open up URL Rewrite:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/owscott/image_5B5941AD.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/owscott/image_thumb_00768C1A.png" width="426" height="328" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Ive come to prefer RegEx rules instead of wildcard rules.&amp;#160; I find that wildcard rules reach their limit pretty quickly.&amp;#160; Regular expressions can be daunting at first but its pretty easy to pick up the basics.&amp;#160; Heres an excellent reference to get started: &lt;a href="http://www.regular-expressions.info/reference.html"&gt;http://www.regular-expressions.info/reference.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;To create the rule click on Add Rules.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/owscott/image_0578C9C9.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/owscott/image_thumb_48E0CB2B.png" width="197" height="169" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Select the Blank Rule template and click OK.&lt;/p&gt;  &lt;p&gt;For the name, enter your domain name, or whatever makes the most sense to you.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Match URL section&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In the Match URL Section, leave the defaults to match the pattern and Regular Expressions.&amp;#160; For the pattern, enter (.*) without the parentheses.&amp;#160; The URL is the part after the domain name.&amp;#160; i.e. www.ThisIsTheDomain.com/ThisIsTheURL.&amp;#160; Its the domain that were interested in now, not the URL.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Conditions&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The Conditions section is where well do most of the work.&amp;#160; Expand that section if its collapsed and click Add.&amp;#160; &lt;/p&gt;  &lt;p&gt;The domain name is contained within the HTTP header called {HTTP_HOST}.&amp;#160; Heres where the fun comes.&amp;#160; The regular expression pattern that will match www.site2.com or site2.com (without the www) looks like this: ^(www.)?site2.com$.&amp;#160; &lt;/p&gt;  &lt;p&gt;Heres what that means.&amp;#160; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The ^ is the character that signifies the start of the string.&amp;#160; That ensures that something.www.site2.com doesnt also get included with this rule. &lt;/li&gt;    &lt;li&gt;The $ is the character that marks the end of the string. &lt;/li&gt;    &lt;li&gt;( ) parentheses are used to create section groups.&amp;#160; &lt;/li&gt;    &lt;li&gt;? means that something is optional. &lt;/li&gt;    &lt;li&gt;Therefore, (www.)? means that with www. or without, either are accepted. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;After filling in these fields you should have something like the following:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/owscott/image_244F3DA7.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/owscott/image_thumb_7CA8C17C.png" width="483" height="316" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Now, heres the part that many people wouldnt guess at first.&amp;#160; Since URL Rewrite works on the URL only, while most code (ASP.NET, ASP, PHP, etc) works at the server level, they arent aware of each other.&amp;#160; Just because you rewrite the URL doesnt mean that the code has any clue of the change.&amp;#160; As a result, any time that ASP.NET automatically creates the path, it will likely clash with the URL Rewrite rule.&amp;#160; For example, Response.Redirect(~/) will redirect to the root of the application.&amp;#160; That means that it can create a path like www.site2.com/site2.&amp;#160; Notice the extra site2 in the path.&amp;#160; The login page for ASP.NET will mess with you too. &lt;/p&gt;  &lt;p&gt;A future blog post will cover how to hide the /site2 using URL Rewrite 2.0, but the easy solution is to ensure that www.site2.com and www.site2.com/site2 both go to the same place.&amp;#160; Both should be served from \masterdomain.com\site2.&amp;#160; It means that the URL can be longer than you may prefer, but it allows the site to continue to function.&lt;/p&gt;  &lt;p&gt;To achieve this, add an exclusion condition so that this rule doesnt redirect at all if the URL starts with /site2/.&lt;/p&gt;  &lt;p&gt;There are 2 ways to achieve this.&amp;#160; You could go back to the URL section where we previously entered .* and update that section.&amp;#160; There isnt anything wrong with that at all.&amp;#160; For no particular reason that I can think of right now, I prefer to do this from the conditions section.&amp;#160; Heres how to do it:&lt;/p&gt;  &lt;p&gt;Add another condition where the condition input is {PATH_INFO}, and set the dropdown to Does Not Match the Pattern, and set the Pattern to ^/site2/.&amp;#160; That means that the PATH_INFO must start with /site2/.&amp;#160; Note that you shouldnt end with the $ this time because you want sub-sub folders to work too.&amp;#160; It should look like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/owscott/image_55024552.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/owscott/image_thumb_5429DF68.png" width="485" height="318" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Action Section&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Were nearly done.&amp;#160; In the Action section, first set the Action Type to &lt;em&gt;Rewrite.&amp;#160; &lt;/em&gt;Then set the Rewrite URL to \site2\{R:0} and ensure that the Append query string checkbox is checked.&amp;#160; The {R:0} is a back reference to the URL.&amp;#160; It will allow the URL to be carried through dynamically in the request.&amp;#160; The Append query string ensures that the query string itself will carry through.&lt;/p&gt;  &lt;p&gt;The complete rule should look like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/owscott/image_0BFC238C.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/owscott/image_thumb_3E7F80FE.png" width="549" height="822" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Thats it.&amp;#160; Save and test.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Using a Text Editor&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;You may prefer to use a text editor or to see the config directly.&amp;#160; The rule generated for web.config looks like this:&lt;/p&gt;          &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&amp;lt;&lt;/span&gt;rewrite&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &amp;lt;&lt;/span&gt;rules&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &amp;lt;&lt;/span&gt;rule&lt;/span&gt; name&lt;/span&gt;=&amp;quot;site2.com&amp;quot;&lt;/span&gt; stopProcessing&lt;/span&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;match&lt;/span&gt; url&lt;/span&gt;=&amp;quot;.*&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;conditions&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;                &amp;lt;&lt;/span&gt;add&lt;/span&gt; input&lt;/span&gt;=&amp;quot;{HTTP_HOST}&amp;quot;&lt;/span&gt; pattern&lt;/span&gt;=&amp;quot;^(www.)?site2.com&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;                &amp;lt;&lt;/span&gt;add&lt;/span&gt; input&lt;/span&gt;=&amp;quot;{PATH_INFO}&amp;quot;&lt;/span&gt; pattern&lt;/span&gt;=&amp;quot;^/site2/&amp;quot;&lt;/span&gt; negate&lt;/span&gt;=&amp;quot;true&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;/&lt;/span&gt;conditions&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;action&lt;/span&gt; type&lt;/span&gt;=&amp;quot;Rewrite&amp;quot;&lt;/span&gt; url&lt;/span&gt;=&amp;quot;\site2\{R:0}&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &amp;lt;/&lt;/span&gt;rule&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &amp;lt;/&lt;/span&gt;rules&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&amp;lt;/&lt;/span&gt;rewrite&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;p&gt;And, the rule for hawaiivisit.site2.com is similar.&amp;#160; It looks like this:&lt;/p&gt;      &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&amp;lt;&lt;/span&gt;rewrite&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &amp;lt;&lt;/span&gt;rules&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &amp;lt;&lt;/span&gt;rule&lt;/span&gt; name&lt;/span&gt;=&amp;quot;hawaiivisit.site2.com&amp;quot;&lt;/span&gt; stopProcessing&lt;/span&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;match&lt;/span&gt; url&lt;/span&gt;=&amp;quot;.*&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;conditions&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;                &amp;lt;&lt;/span&gt;add&lt;/span&gt; input&lt;/span&gt;=&amp;quot;{HTTP_HOST}&amp;quot;&lt;/span&gt; pattern&lt;/span&gt;=&amp;quot;^hawaiivisit.site2.com$&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;                &amp;lt;&lt;/span&gt;add&lt;/span&gt; input&lt;/span&gt;=&amp;quot;{PATH_INFO}&amp;quot;&lt;/span&gt; pattern&lt;/span&gt;=&amp;quot;^/hawaiivisit/&amp;quot;&lt;/span&gt; negate&lt;/span&gt;=&amp;quot;true&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;/&lt;/span&gt;conditions&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;action&lt;/span&gt; type&lt;/span&gt;=&amp;quot;Rewrite&amp;quot;&lt;/span&gt; url&lt;/span&gt;=&amp;quot;\hawaiivisit\{R:0}&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &amp;lt;/&lt;/span&gt;rule&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &amp;lt;/&lt;/span&gt;rules&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&amp;lt;/&lt;/span&gt;rewrite&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;p&gt;&lt;strong&gt;The other things&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;I wanted to briefly mention what isnt covered in this blog post that you may want to consider.&amp;#160; &lt;/p&gt;&lt;ul&gt;  &lt;li&gt;DNS. The how to for your domain name purchase and directing isnt covered here. &lt;/li&gt;  &lt;li&gt;Statistics. If you use&amp;#160; a client-side option like Google Analytics then this will work just as well under a single account.&amp;#160; However, if you are using a log based statistics program like SmarterStats then its up to you to set rules in SmarterStats to filter out or sub-divide the statistics into useful sections i.e. 1 per site. &lt;/li&gt;  &lt;li&gt;Email. You will likely need to setup another mail account with your host, or add the new domain as a domain alias to your existing account. &lt;/li&gt;  &lt;li&gt;ASP.NET inheritance. web.config inherits down the entire path but the ASP.NET folders do not inherit past application boundaries.&amp;#160; More on that &lt;a href="http://weblogs.asp.net/owscott/archive/2005/12/29/ASP.NET-files-and-inheritance.aspx" target="_blank"&gt;here&lt;/a&gt;.&amp;#160; One workaround if ASP.NET inheritance fights with you is to not have a site in the website root.&amp;#160; Instead, place all sites in their own subfolder. &lt;/li&gt;  &lt;li&gt;Youll likely need to mark the folder as an application so that it is an ASP.NET application.&amp;#160; (assuming ASP.NET of course) &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Happy URL Rewriting!&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7324543" width="1" height="1"&gt;</description><author>Scott Forsyths WebLog</author><pubDate>Wed, 27 Jan 2010 00:00:00 GMT</pubDate></item><item><title>jQuery 1.4 Opacity and IE Filters</title><link>http://feedproxy.google.com/~r/RickStrahl/~3/A_HPrHMscI8/191612.aspx</link><description>&lt;p&gt;Ran into a small problem today with my client side jQuery library after switching to jQuery 1.4. I ran into a problem with a shadow plugin that I use to provide drop shadows for absolute elements  for Mozilla WebKit browsers the moz-box-shadow and webkit-box-shadow CSS attributes are used but for IE a manual element is created to provide the shadow that underlays the original element along with a blur filter to provide the fuzziness in the shadow. Some of the key pieces are:&lt;/p&gt;  &lt;pre class="code"&gt;var &lt;/span&gt;vis = el.is(&amp;quot;:visible&amp;quot;&lt;/span&gt;);if &lt;/span&gt;(!vis)    el.show();  // must be visible to get .position&lt;/span&gt;var &lt;/span&gt;pos = el.position();&lt;/pre&gt;&lt;pre class="code"&gt;&lt;strong&gt;if &lt;/span&gt;(typeof &lt;/span&gt;shEl.style.filter == &amp;quot;string&amp;quot;&lt;/span&gt;)    sh.css(&amp;quot;filter&amp;quot;&lt;/span&gt;, 'progid:DXImageTransform.Microsoft.Blur(makeShadow=true, pixelradius=3, shadowOpacity=' &lt;/span&gt;+ opt.opacity.toString() + ')'&lt;/span&gt;);&lt;/strong&gt;sh.show()  .css({ position: &amp;quot;absolute&amp;quot;&lt;/span&gt;,      width: el.outerWidth(),      height: el.outerHeight(),      opacity: opt.opacity,      background: opt.color,      left: pos.left + opt.offset,      top: pos.top + opt.offset  });&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;This has always worked in previous versions of jQuery, but with 1.4 the original filter no longer works. It appears that applying the opacity after the original filter wipes out the original filter. IOW, the opacity filter is not applied incrementally, but absolutely which is a real bummer.&lt;/p&gt;&lt;p&gt;Luckily the workaround is relatively easy by just switching the order in which the opacity and filter are applied. If I apply the blur after the opacity I get my correct behavior back with both opacity:&lt;/p&gt;&lt;pre class="code"&gt;sh.show()  .css({ position: &amp;quot;absolute&amp;quot;&lt;/span&gt;,      width: el.outerWidth(),      height: el.outerHeight(),      opacity: opt.opacity,      background: opt.color,      left: pos.left + opt.offset,      top: pos.top + opt.offset  }); &lt;strong&gt; if &lt;/span&gt;(typeof &lt;/span&gt;shEl.style.filter == &amp;quot;string&amp;quot;&lt;/span&gt;)      sh.css(&amp;quot;filter&amp;quot;&lt;/span&gt;, 'progid:DXImageTransform.Microsoft.Blur(makeShadow=true, pixelradius=3, shadowOpacity=' &lt;/span&gt;+ opt.opacity.toString() + ')'&lt;/span&gt;);&lt;/strong&gt;&lt;/pre&gt;&lt;p&gt;While this works this still causes problems in other areas where opacity is implicitly set in code such as for fade operations or in the case of my shadow component the style/property watcher that keeps the shadow and main object linked. Both of these may set the opacity explicitly and that is still broken as it will effectively kill the blur filter.&lt;/p&gt;&lt;p&gt;This seems like a really strange design decision by the jQuery team, since clearly the jquery css function does the right thing for setting filters. Internally however, the opacity setting doesnt use .css instead hardcoding the filter which given jQuerys usual flexibility and smart code seems really inappropriate. &lt;/p&gt;&lt;p&gt;The following is from jQuery.js 1.4:&lt;/p&gt;&lt;pre class="code"&gt;var &lt;/span&gt;style = elem.style || elem, set &lt;/span&gt;= value !== undefined;// IE uses filters for opacity&lt;/span&gt;if &lt;/span&gt;( !jQuery.support.opacity &amp;&amp; name === &amp;quot;opacity&amp;quot; &lt;/span&gt;) {    if &lt;/span&gt;( set &lt;/span&gt;) {        // IE has trouble with opacity if it does not have layout        // Force it by setting the zoom level        &lt;/span&gt;style.zoom = 1;        // Set the alpha filter to set the opacity        &lt;/span&gt;var &lt;/span&gt;opacity = parseInt( value, 10 ) + &amp;quot;&amp;quot; &lt;/span&gt;=== &amp;quot;NaN&amp;quot; &lt;/span&gt;? &amp;quot;&amp;quot; &lt;/span&gt;: &amp;quot;alpha(opacity=&amp;quot; &lt;/span&gt;+ value * 100 + &amp;quot;)&amp;quot;&lt;/span&gt;;        var &lt;/span&gt;filter = style.filter || jQuery.curCSS( elem, &amp;quot;filter&amp;quot; &lt;/span&gt;) || &amp;quot;&amp;quot;&lt;/span&gt;;        style.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : opacity;    }    return &lt;/span&gt;style.filter &amp;&amp; style.filter.indexOf(&amp;quot;opacity=&amp;quot;&lt;/span&gt;) &amp;gt;= 0 ?        (parseFloat( ropacity.exec(style.filter)[1] ) / 100) + &amp;quot;&amp;quot;&lt;/span&gt;:        &amp;quot;&amp;quot;&lt;/span&gt;;}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;You can see here that the style is explicitly set in code rather than relying on $.css() to assign the value resulting in the old filter getting wiped out. &lt;/p&gt;&lt;p&gt;jQuery 1.32 looks a little different:&lt;/p&gt;&lt;pre class="code"&gt;// IE uses filters for opacity&lt;/span&gt;if &lt;/span&gt;( !jQuery.support.opacity &amp;&amp; name == &amp;quot;opacity&amp;quot; &lt;/span&gt;) {    if &lt;/span&gt;( set &lt;/span&gt;) {        // IE has trouble with opacity if it does not have layout        // Force it by setting the zoom level        &lt;/span&gt;elem.zoom = 1;        // Set the alpha filter to set the opacity        &lt;/span&gt;elem.filter = (elem.filter || &amp;quot;&amp;quot;&lt;/span&gt;).replace( /alpha\([^)]*\)/, &amp;quot;&amp;quot; &lt;/span&gt;) +            (parseInt( value ) + '' &lt;/span&gt;== &amp;quot;NaN&amp;quot; &lt;/span&gt;? &amp;quot;&amp;quot; &lt;/span&gt;: &amp;quot;alpha(opacity=&amp;quot; &lt;/span&gt;+ value * 100 + &amp;quot;)&amp;quot;&lt;/span&gt;);    }    return &lt;/span&gt;elem.filter &amp;&amp; elem.filter.indexOf(&amp;quot;opacity=&amp;quot;&lt;/span&gt;) &amp;gt;= 0 ?        (parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100) + ''&lt;/span&gt;:        &amp;quot;&amp;quot;&lt;/span&gt;;}&lt;/pre&gt;&lt;p&gt;Offhand Im not sure why the latter works better since it too is assigning the filter. However, when checking with the IE script debugger I can see that there are actually a couple of filter tags assigned when using jQuery 1.32 but only one when I use jQuery 1.4.&lt;/p&gt;&lt;p&gt;Note also that the jQuery 1.3 compatibility plugin for jQUery 1.4 doesnt address this issue either.&lt;/p&gt;&lt;h3&gt;Resources&lt;/h3&gt;&lt;ul&gt;  &lt;li&gt;&lt;a href="http://codepaste.net/ShowUrl?url=http%3A%2F%2Fwww.west-wind.com%3A8080%2Fsvn%2FWestwindWebToolkit%2Ftrunk%2FWestwind.Web%2FResources%2Fww.jquery.js&amp;Language=JavaScript"&gt;ww.jquery.js&lt;/a&gt; (shadow plug-in $.fn.shadow)&lt;/li&gt;&lt;/ul&gt;&lt;small&gt; Rick Strahl, West Wind Technologies, 2005-2010&lt;/small&gt;&lt;a href='/Weblog/ShowPosts.aspx?Category=jQuery'&gt;jQuery&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f191612.aspx&amp;title=jQuery+1.4+Opacity+and+IE+Filters"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f191612.aspx" border='0' alt='kick it on DotNetKicks.com' /&gt;&lt;/a&gt;&lt;/small&gt;&lt;p&gt;&lt;a href='http://west-wind.com/Weblog/wwBanner.ashx?a=c&amp;id=e47b9595&amp;t=634000088748180000' target='_top'&gt;&lt;img src='http://www.west-wind.com/banners/wwstore_small.gif' border='0'&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=A_HPrHMscI8:GpuoJ_LT0F0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=A_HPrHMscI8:GpuoJ_LT0F0:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=A_HPrHMscI8:GpuoJ_LT0F0:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=A_HPrHMscI8:GpuoJ_LT0F0:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=A_HPrHMscI8:GpuoJ_LT0F0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=A_HPrHMscI8:GpuoJ_LT0F0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=A_HPrHMscI8:GpuoJ_LT0F0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=A_HPrHMscI8:GpuoJ_LT0F0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=A_HPrHMscI8:GpuoJ_LT0F0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/RickStrahl/~4/A_HPrHMscI8" height="1" width="1"/&gt;</description><author>Rick Strahls WebLog                                                                                 </author><pubDate>Mon, 25 Jan 2010 00:00:00 GMT</pubDate></item><item><title>HttpContext.Items and Server.Transfer/Execute</title><link>http://feedproxy.google.com/~r/RickStrahl/~3/ijBcDFMzwYM/184857.aspx</link><description>&lt;p&gt;A few days ago my buddy Ben Jones pointed out that he ran into a bug in the ScriptContainer control in the &lt;a href="http://www.west-wind.com/WestwindWebToolkit/" target="_blank"&gt;West Wind Web and Ajax Toolkit&lt;/a&gt;. The problem was basically that when a Server.Transfer call was applied the script container (and also various ClientScriptProxy script embedding routines) would potentially fail to load up the specified scripts.&lt;/p&gt;  &lt;p&gt;It turns out the problem is due to the fact that the various components in the toolkit use &lt;a href="https://www.west-wind.com/Weblog/posts/417588.aspx" target="_blank"&gt;request specific singletons&lt;/a&gt; via a Current property. I use a static Current property tied to a Context.Items[] entry to handle this type of operation which looks something like this:&lt;/p&gt;  &lt;pre class="code"&gt;/// &amp;lt;summary&amp;gt;/// &lt;/span&gt;Current instance of this class which should always be used to &lt;/span&gt;/// &lt;/span&gt;access this object. There are no public constructors to&lt;/span&gt;/// &lt;/span&gt;ensure the reference is used as a Singleton to further&lt;/span&gt;/// &lt;/span&gt;ensure that all scripts are written to the same clientscript&lt;/span&gt;/// &lt;/span&gt;manager.&lt;/span&gt;/// &amp;lt;/summary&amp;gt;        &lt;/span&gt;public static &lt;/span&gt;ClientScriptProxy &lt;/span&gt;Current{    get    &lt;/span&gt;{        if &lt;/span&gt;(HttpContext&lt;/span&gt;.Current == null&lt;/span&gt;)            return new &lt;/span&gt;ClientScriptProxy&lt;/span&gt;();        ClientScriptProxy &lt;/span&gt;proxy = null&lt;/span&gt;;&lt;strong&gt;        if &lt;/span&gt;(HttpContext&lt;/span&gt;.Current.Items.Contains(STR_CONTEXTID))            proxy = HttpContext&lt;/span&gt;.Current.Items[STR_CONTEXTID] as &lt;/span&gt;ClientScriptProxy&lt;/span&gt;;&lt;/strong&gt;        else        &lt;/span&gt;{            proxy = new &lt;/span&gt;ClientScriptProxy&lt;/span&gt;();&lt;strong&gt;            HttpContext&lt;/span&gt;.Current.Items[STR_CONTEXTID] = proxy;&lt;/strong&gt;        }                return &lt;/span&gt;proxy;    }}&lt;/pre&gt;&lt;p&gt;The proxy is attached to a Context.Items[] item which makes the instance Request specific. This works perfectly fine in most situations EXCEPT when youre dealing with Server.Transfer/Execute requests. Server.Transfer doesnt cause Context.Items to be cleared so both the current transferred request and the original requests Context.Items collection apply. &lt;/p&gt;&lt;p&gt;For the ClientScriptProxy this causes a problem because script references are tracked on a per request basis in Context.Items to check for script duplication. Once a script is rendered an ID is written into the Context collection and so considered rendered:&lt;/p&gt;&lt;pre class="code"&gt;// No dupes - ref script include only once&lt;/span&gt;if &lt;/span&gt;(HttpContext&lt;/span&gt;.Current.Items.Contains( STR_SCRIPTITEM_IDENTITIFIER + fileId ) )    return&lt;/span&gt;;HttpContext&lt;/span&gt;.Current.Items.Add(STR_SCRIPTITEM_IDENTITIFIER + fileId, string&lt;/span&gt;.Empty);&lt;/pre&gt;&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;  &lt;br /&gt;where the fileId is the script name or unique identifier. The problem is on the Transferred page the item will already exist in Context and so fail to render because it thinks the script has already rendered based on the Context item. Bummer.&lt;/p&gt;&lt;p&gt;The workaround for this is simple once you know whats going on, but in this case it was a bitch to track down because the context items are used in many places throughout this class. The trick is to determine when a request is transferred and then removing the specific keys.&lt;/p&gt;&lt;p&gt;The first issue is to determine if a script is in a Trransfer or Execute call:&lt;/p&gt;&lt;pre class="code"&gt;if &lt;/span&gt;(HttpContext&lt;/span&gt;.Current.CurrentHandler != HttpContext&lt;/span&gt;.Current.Handler)&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;Context.Handler is the original handler and CurrentHandler is the actual currently executing handler that is running when a Transfer/Execute is active. You can also use Context.PreviousHandler to get the last handler and chain through the whole list of handlers applied if Transfer calls are nested (dog help us all for the person debugging that).&lt;/p&gt;&lt;p&gt;For the ClientScriptProxy the full logic to check for a transfer and remove the code looks like this:&lt;/p&gt;&lt;pre class="code"&gt;/// &amp;lt;summary&amp;gt;/// &lt;/span&gt;Clears all the request specific context items which are script references&lt;/span&gt;/// &lt;/span&gt;and the script placement index.&lt;/span&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;public void &lt;/span&gt;ClearContextItemsOnTransfer(){    if &lt;/span&gt;(HttpContext&lt;/span&gt;.Current != null&lt;/span&gt;)    {        // Check for Server.Transfer/Execute calls - we need to clear out Context.Items        &lt;/span&gt;if &lt;/span&gt;(HttpContext&lt;/span&gt;.Current.CurrentHandler != HttpContext&lt;/span&gt;.Current.Handler)        {            List&lt;/span&gt;&amp;lt;string&lt;/span&gt;&amp;gt; Keys = HttpContext&lt;/span&gt;.Current.Items.Keys.Cast&amp;lt;string&lt;/span&gt;&amp;gt;().Where(s =&amp;gt; s.StartsWith(STR_SCRIPTITEM_IDENTITIFIER) || s == STR_ScriptResourceIndex).ToList();            foreach &lt;/span&gt;(string &lt;/span&gt;key in &lt;/span&gt;Keys)            {                HttpContext&lt;/span&gt;.Current.Items.Remove(key);            }        }    }}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;along with a small update to the Current property getter that sets a global flag to indicate whether the request was transferred:&lt;/p&gt;&lt;pre class="code"&gt;if &lt;/span&gt;(!proxy.IsTransferred &amp;&amp; HttpContext&lt;/span&gt;.Current.Handler != HttpContext&lt;/span&gt;.Current.CurrentHandler){    proxy.ClearContextItemsOnTransfer();    proxy.IsTransferred = true&lt;/span&gt;;}return &lt;/span&gt;proxy;&lt;/pre&gt;&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;I know this is pretty ugly, but it works and its actually minimal fuss without affecting the behavior of the rest of the class. Ben had a different solution that involved explicitly clearing out the Context items and replacing the collection with a manually maintained list of items which also works, but required changes through the code to make this work.&lt;/p&gt;&lt;p&gt;In hindsight, it would have been better to use a single object that encapsulates all the persisted values and store that object in Context instead of all these individual small morsels. Hindsight is always 20/20 though :-}.&lt;/p&gt;&lt;h3&gt;If possible use Page.Items&lt;/h3&gt;&lt;p&gt;ClientScriptProxy is a generic component that can be used from anywhere in ASP.NET, so there are various methods that are not Page specific on this component which is why I used Context.Items, rather than the Page.Items collection.Page.Items would be a better choice since it will sidestep the above Server.Transfer nightmares as the Page is reloaded completely and so any new Page gets a new Items collection. No fuss there.&lt;/p&gt;&lt;p&gt;So for the ScriptContainer control, which has to live on the page the behavior is a little different. It is attached to Page.Items (since its a control):&lt;/p&gt;&lt;pre class="code"&gt;/// &amp;lt;summary&amp;gt;/// &lt;/span&gt;Returns a current instance of this control if an instance&lt;/span&gt;/// &lt;/span&gt;is already loaded on the page. Otherwise a new instance is&lt;/span&gt;/// &lt;/span&gt;created, added to the Form and returned.&lt;/span&gt;/// /// &lt;/span&gt;It's important this function is not called too early in the&lt;/span&gt;/// &lt;/span&gt;page cycle - it should not be called before Page.OnInit().&lt;/span&gt;/// /// &lt;/span&gt;This property is the preferred way to get a reference to a&lt;/span&gt;/// &lt;/span&gt;ScriptContainer control that is either already on a page&lt;/span&gt;/// &lt;/span&gt;or needs to be created. Controls in particular should always&lt;/span&gt;/// &lt;/span&gt;use this property.&lt;/span&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;public static &lt;/span&gt;ScriptContainer &lt;/span&gt;Current{    get    &lt;/span&gt;{        // We need a context for this to work!        &lt;/span&gt;if &lt;/span&gt;(HttpContext&lt;/span&gt;.Current == null&lt;/span&gt;)            return null&lt;/span&gt;;        Page &lt;/span&gt;page = HttpContext&lt;/span&gt;.Current.CurrentHandler as &lt;/span&gt;Page&lt;/span&gt;;        if &lt;/span&gt;(page == null&lt;/span&gt;)            throw new &lt;/span&gt;InvalidOperationException&lt;/span&gt;(Resources&lt;/span&gt;.ERROR_ScriptContainer_OnlyWorks_With_PageBasedHandlers);         ScriptContainer &lt;/span&gt;ctl = null&lt;/span&gt;;        // Retrieve the current instance        &lt;/span&gt;ctl = page.Items[STR_CONTEXTID] as &lt;/span&gt;ScriptContainer&lt;/span&gt;;        if &lt;/span&gt;(ctl != null&lt;/span&gt;)            return &lt;/span&gt;ctl;                ctl = new &lt;/span&gt;ScriptContainer&lt;/span&gt;();                page.Form.Controls.Add(ctl);        return &lt;/span&gt;ctl;    }}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;The biggest issue with this approach is that you have to explicitly retrieve the page in the static Current property. Notice again the use of CurrentHandler (rather than Handler which was my original implementation) to ensure you get the latest page including the one that Server.Transfer fired. &lt;/p&gt;&lt;h3&gt;Server.Transfer and Server.Execute are Evil&lt;/h3&gt;&lt;p&gt;All that said  this fix is probably for the 2 people who are crazy enough to rely on Server.Transfer/Execute. :-} There are so many weird behavior problems with these commands that I avoid them at all costs. I dont think I have a single application that uses either of these commands&lt;/p&gt;&lt;small&gt; Rick Strahl, West Wind Technologies, 2005-2010&lt;/small&gt;&lt;a href='/Weblog/ShowPosts.aspx?Category= ASP.NET'&gt; ASP.NET&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f184857.aspx&amp;title=HttpContext.Items+and+Server.Transfer%2fExecute"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f184857.aspx" border='0' alt='kick it on DotNetKicks.com' /&gt;&lt;/a&gt;&lt;/small&gt;&lt;p&gt;&lt;a href='http://west-wind.com/Weblog/wwBanner.ashx?a=c&amp;id=ac59a8bf&amp;t=633996347453450000' target='_top'&gt;&lt;img src='http://www.west-wind.com/banners/WestwindWebToolkit.jpg' border='0'&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=ijBcDFMzwYM:GBX4WcWJL7w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=ijBcDFMzwYM:GBX4WcWJL7w:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=ijBcDFMzwYM:GBX4WcWJL7w:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=ijBcDFMzwYM:GBX4WcWJL7w:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=ijBcDFMzwYM:GBX4WcWJL7w:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=ijBcDFMzwYM:GBX4WcWJL7w:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=ijBcDFMzwYM:GBX4WcWJL7w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=ijBcDFMzwYM:GBX4WcWJL7w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=ijBcDFMzwYM:GBX4WcWJL7w:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/RickStrahl/~4/ijBcDFMzwYM" height="1" width="1"/&gt;</description><author>Rick Strahls WebLog                                                                                 </author><pubDate>Thu, 21 Jan 2010 00:00:00 GMT</pubDate></item><item><title>Solution to ASP.net Theme Conflict with FCKEditor</title><link>http://aspalliance.com/1908_Solution_to_ASPnet_Theme_Conflict_with_FCKEditor</link><description>Solution to Asp.net theme conflict with FCKEditor</description><author>ASPAlliance.com - The #1 ASP.NET Community                                                          </author><pubDate>Wed, 20 Jan 2010 00:00:00 GMT</pubDate></item><item><title>Silverlight - Creating Image Map with Hotspots</title><link>http://aspalliance.com/1913_Silverlight__Creating_Image_Map_with_Hotspots</link><description>Recently, I was working on a Silverlight application and one of the pages contained a graphic. One of the requirements was that the graphic should contain clickable regions (Hotspots) and display a dynamic navigation menu when clicked on. An image that contains one or more Hotspots or clickable areas is called an image map. I have put together a simple tutorial on how to get this done.</description><author>ASPAlliance.com - The #1 ASP.NET Community                                                          </author><pubDate>Tue, 19 Jan 2010 00:00:00 GMT</pubDate></item><item><title>Client Centric Approach of AJAX using Toolkit</title><link>http://aspalliance.com/1909_Client_Centric_Approach_of_AJAX_using_Toolkit</link><description>In this article, the author discusses the client-centric approach for AJAX using the ASP.NET AJAX Toolkit. In general, server-centric (use of Update panel) is very popular in this field. But when it comes to performance, the client-centric approach is preferred. Sandeep also demonstrates how to call a webservice using javascript.</description><author>ASPAlliance.com - The #1 ASP.NET Community                                                          </author><pubDate>Tue, 12 Jan 2010 00:00:00 GMT</pubDate></item><item><title>ASP.NET Slideshow Control with jQuery and XML</title><link>http://aspalliance.com/1900_ASPNET_Slideshow_Control_with_jQuery_and_XML</link><description>For the past few years, image sliders, slide-shows, and ad rotator scripts have become increasingly popular for web pages. There are thousands of these scripts on the Web but is difficult to find one that can fit your requirements. Ideally, you would want a script that is flexible enough for to use as an ad rotator, for slide-shows, or for image rotators with navigation controls and extract the slides information from XML file. After spending some time researching for it, I found the jQuery based slideshow with navigation controls from Dynamic Drive and the article reading-xml-with-jquery. I have put together a step by step tutorial on how I have accomplished this. </description><author>ASPAlliance.com - The #1 ASP.NET Community                                                          </author><pubDate>Tue, 05 Jan 2010 00:00:00 GMT</pubDate></item><item><title>Rendering ASP.NET Script References into the Html Header</title><link>http://feedproxy.google.com/~r/RickStrahl/~3/KNhRLQI5gWY/154797.aspx</link><description>&lt;p&gt;One thing that Ive come to appreciate in control development in ASP.NET that use JavaScript is the ability to have more control over script and script include placement than ASP.NET provides natively. Specifically in ASP.NET you can use either the ClientScriptManager or ScriptManager to embed scripts and script references into pages via code.&lt;/p&gt;  &lt;p&gt;This works reasonably well, but the script references that get generated are generated into the HTML body and theres very little operational control for placement of scripts. If you have multiple controls or several of the same control that need to place the same scripts onto the page its not difficult to end up with scripts that render in the wrong order and stop working correctly. This is especially critical if you load script libraries with dependencies either via resources or even if you are rendering referenced to CDN resources.&lt;/p&gt;  &lt;p&gt;Natively ASP.NET provides a host of methods that help embedding scripts into the page via either Page.ClientScript or the ASP.NET ScriptManager control (both with slightly different syntax):&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;RegisterClientScriptBlock        &lt;br /&gt;&lt;/strong&gt;Renders a script block at the top of the HTML body and should be used for embedding callable functions/classes.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;RegisterStartupScript&lt;/strong&gt;       &lt;br /&gt;Renders a script block just prior to the &amp;lt;/form&amp;gt; tag and should be used to for embedding code that should execute when the page is first loaded. Not recommended  use jQuery.ready() or equivalent load time routines.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;RegisterClientScriptInclude        &lt;br /&gt;&lt;/strong&gt;Embeds a reference to a script from a url into the page.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;RegisterClientScriptResource&lt;/strong&gt;       &lt;br /&gt;Embeds a reference to a Script from a resource file generating a long resource file string &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;All 4 of these methods render their &amp;lt;script&amp;gt; tags into the HTML body. The script blocks give you a little bit of control by having a top and bottom of the document location which gives you some flexibility over script placement and precedence. Script includes and resource url unfortunately do not even get that much control  references are simply rendered into the page in the order of declaration.&lt;/p&gt;  &lt;p&gt;The ASP.NET ScriptManager control facilitates this task a little bit with the abililty to specify scripts in code and the ability to programmatically check what scripts have already been registered, but it doesnt provide any more control over the script rendering process itself. Further the ScriptManager is a bear to deal with generically because generic code has to always check and see if it is actually present.&lt;/p&gt;  &lt;p&gt;Some time ago I posted a ClientScriptProxy class that helps with managing the latter process of sending script references either to ClientScript or ScriptManager if its available. Since I last posted about this there have been a number of improvements in this API, one of which is the ability to control placement of scripts and script includes in the page which I think is rather important and a missing feature in the ASP.NET native functionality.&lt;/p&gt;  &lt;h3&gt;Handling ScriptRenderModes&lt;/h3&gt;  &lt;p&gt;One of the big enhancements that Ive come to rely on is the ability of the various script rendering functions described above to support rendering in multiple locations:    &lt;br /&gt;    &lt;br /&gt;&lt;font face="Courier New"&gt;/// &amp;lt;summary&amp;gt;        &lt;br /&gt;///&lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;Determines how scripts are included into the page        &lt;br /&gt;&lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;/// &amp;lt;/summary&amp;gt;        &lt;br /&gt;&lt;/span&gt;public enum &lt;/span&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;ScriptRenderModes        &lt;br /&gt;&lt;/span&gt;{       &lt;br /&gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New"&gt;/// &amp;lt;summary&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ///&lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;Inherits the setting from the control or from the ClientScript.DefaultScriptRenderMode        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;/// &amp;lt;/summary&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;Inherit,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ///&lt;/span&gt;&lt;/font&gt;&lt;font face="Courier New"&gt;Renders the script include at the location of the control        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;/// &amp;lt;/summary&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;Inline,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New"&gt;/// &amp;lt;summary&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ///&lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;Renders the script include into the bottom of the header of the page        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;/// &amp;lt;/summary&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;Header,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New"&gt;/// &amp;lt;summary&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ///&lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;Renders the script include into the top of the header of the page        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;/// &amp;lt;/summary&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;HeaderTop,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New"&gt;/// &amp;lt;summary&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ///&lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;Uses ClientScript or ScriptManager to embed the script include        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/font&gt;&lt;/span&gt;&lt;font face="Courier New"&gt;/// &amp;lt;/summary&amp;gt;        &lt;br /&gt;&amp;#160;&amp;#160; &lt;/span&gt;Script       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;This enum is then applied to the various Register functions to allow more control over where scripts actually show up. Why is this useful? For me I often render scripts out of control resources and these scripts often include things like a JavaScript Library (jquery) and a few plug-ins. The order in which these can be loaded is critical so that jQuery.js always loads before any plug-in for example. &lt;/p&gt;  &lt;p&gt;Typically I end up with a general script layout like this:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Core Libraries- HeaderTop &lt;/li&gt;    &lt;li&gt;Plug-ins: Header &lt;/li&gt;    &lt;li&gt;ScriptBlocks: Header or Script depending on other dependencies &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The API syntax of the ClientScriptProxy methods is closely compatible with ScriptManagers using static methods and control references to gain access to the page and embedding scripts.&lt;/p&gt;  &lt;p&gt;For example, to render some script into the current page in the header:&lt;/p&gt;  &lt;pre class="code"&gt;// Create script block in header&lt;/span&gt;ClientScriptProxy&lt;/span&gt;.Current.RegisterClientScriptBlock(this&lt;/span&gt;, typeof&lt;/span&gt;(ControlResources&lt;/span&gt;),                &amp;quot;hello_function&amp;quot;&lt;/span&gt;, &amp;quot;function helloWorld() { alert('hello'); }&amp;quot;&lt;/span&gt;, true&lt;/span&gt;,                ScriptRenderModes&lt;/span&gt;.Header);// Same again - shouldn't be rendered because it's the same id&lt;/span&gt;ClientScriptProxy&lt;/span&gt;.Current.RegisterClientScriptBlock(this&lt;/span&gt;, typeof&lt;/span&gt;(ControlResources&lt;/span&gt;),         &amp;quot;hello_function&amp;quot;&lt;/span&gt;, &amp;quot;function helloWorld() { alert('hello'); }&amp;quot;&lt;/span&gt;, true&lt;/span&gt;,         ScriptRenderModes&lt;/span&gt;.Header);// Create a second script block in header&lt;/span&gt;ClientScriptProxy&lt;/span&gt;.Current.RegisterClientScriptBlock(this&lt;/span&gt;, typeof&lt;/span&gt;(ControlResources&lt;/span&gt;),    &amp;quot;hello_function2&amp;quot;&lt;/span&gt;, &amp;quot;function helloWorld2() { alert('hello2'); }&amp;quot;&lt;/span&gt;, true&lt;/span&gt;,    ScriptRenderModes&lt;/span&gt;.Header);// This just calls ClientScript and renders into bottom of document&lt;/span&gt;ClientScriptProxy&lt;/span&gt;.Current.RegisterStartupScript(this&lt;/span&gt;,typeof&lt;/span&gt;(ControlResources&lt;/span&gt;),                &amp;quot;call_hello&amp;quot;&lt;/span&gt;, &amp;quot;helloWorld();helloWorld2();&amp;quot;&lt;/span&gt;, true&lt;/span&gt;);&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;which generates:&lt;/p&gt;&lt;pre class="code"&gt;&amp;lt;&lt;/span&gt;html &lt;/span&gt;xmlns&lt;/span&gt;=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot; &amp;gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&amp;gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&amp;gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;script &lt;/span&gt;type&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;function &lt;/span&gt;helloWorld() { alert('hello'&lt;/span&gt;); }&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;script &lt;/span&gt;type&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;function &lt;/span&gt;helloWorld2() { alert('hello2'&lt;/span&gt;); }&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&amp;gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&amp;gt;&lt;/span&gt;    &lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;script &lt;/span&gt;type&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;//&amp;lt;![CDATA[&lt;/span&gt;helloWorld();helloWorld2();&lt;/strong&gt;&lt;strong&gt;//]]&amp;gt;&lt;/span&gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&amp;lt;/&lt;/span&gt;form&lt;/span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;For script includes the following demonstrates how to embed script includes into the header in this case for loading jQuery from the Google CDN:&lt;/p&gt;&lt;pre class="code"&gt;// load jquery from CDN&lt;/span&gt;ClientScriptProxy&lt;/span&gt;.Current.RegisterClientScriptInclude(this&lt;/span&gt;, typeof&lt;/span&gt;(ControlResources&lt;/span&gt;),                &amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&amp;quot;&lt;/span&gt;,                ScriptRenderModes&lt;/span&gt;.HeaderTop);// check if jquery loaded - if it didn't we're not online&lt;/span&gt;string &lt;/span&gt;scriptCheck =    @&amp;quot;if (typeof jQuery != 'object')          document.write(unescape(&amp;quot;&amp;quot;%3Cscript src='{0}' type='text/javascript'%3E%3C/script%3E&amp;quot;&amp;quot;));&amp;quot;&lt;/span&gt;;string &lt;/span&gt;jQueryUrl = ClientScriptProxy&lt;/span&gt;.Current.GetWebResourceUrl(this&lt;/span&gt;, typeof&lt;/span&gt;(ControlResources&lt;/span&gt;),                ControlResources&lt;/span&gt;.JQUERY_SCRIPT_RESOURCE);            ClientScriptProxy&lt;/span&gt;.Current.RegisterClientScriptBlock(this&lt;/span&gt;, typeof&lt;/span&gt;(ControlResources&lt;/span&gt;),                &amp;quot;jquery_register&amp;quot;&lt;/span&gt;, string&lt;/span&gt;.Format(scriptCheck,jQueryUrl),true&lt;/span&gt;,                ScriptRenderModes&lt;/span&gt;.HeaderTop);                            // Load jquery-ui from cdn&lt;/span&gt;ClientScriptProxy&lt;/span&gt;.Current.RegisterClientScriptInclude(this&lt;/span&gt;, typeof&lt;/span&gt;(ControlResources&lt;/span&gt;),                &amp;quot;http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js&amp;quot;&lt;/span&gt;,                ScriptRenderModes&lt;/span&gt;.Header);// check if we need to load from local&lt;/span&gt;string &lt;/span&gt;jQueryUiUrl = ResolveUrl(&amp;quot;~/scripts/jquery-ui-custom.min.js&amp;quot;&lt;/span&gt;); ClientScriptProxy&lt;/span&gt;.Current.RegisterClientScriptBlock(this&lt;/span&gt;, typeof&lt;/span&gt;(ControlResources&lt;/span&gt;),    &amp;quot;jqueryui_register&amp;quot;&lt;/span&gt;, string&lt;/span&gt;.Format(scriptCheck, jQueryUiUrl), true&lt;/span&gt;,    ScriptRenderModes&lt;/span&gt;.Header); // Create script block in header&lt;/span&gt;ClientScriptProxy&lt;/span&gt;.Current.RegisterClientScriptBlock(this&lt;/span&gt;, typeof&lt;/span&gt;(ControlResources&lt;/span&gt;),                &amp;quot;hello_function&amp;quot;&lt;/span&gt;, &amp;quot;$().ready( function() { alert('hello'); });&amp;quot;&lt;/span&gt;, true&lt;/span&gt;,                ScriptRenderModes&lt;/span&gt;.Header);&lt;/pre&gt;&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;which in turn generates this HTML:&lt;/p&gt;&lt;pre class="code"&gt;&amp;lt;&lt;/span&gt;html &lt;/span&gt;xmlns&lt;/span&gt;=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot; &amp;gt;&amp;lt;&lt;/span&gt;head&lt;/span&gt;&amp;gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;script &lt;/span&gt;src&lt;/span&gt;=&amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&amp;quot; &lt;/span&gt;type&lt;/span&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&amp;gt;&amp;lt;&lt;/span&gt;script &lt;/span&gt;type&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;    if &lt;/span&gt;(typeof &lt;/span&gt;jQuery != 'object'&lt;/span&gt;)        document.write(unescape(&amp;quot;%3Cscript src='/WestWindWebToolkitWeb/WebResource.axd?d=DIykvYhJ_oXCr-TA_dr35i4AayJoV1mgnQAQGPaZsoPM2LCdvoD3cIsRRitHKlKJfV5K_jQvylK7tsqO3lQIFw2&amp;t=633979863959332352' type='text/javascript'%3E%3C/script%3E&amp;quot;&lt;/span&gt;));&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&amp;lt;&lt;/span&gt;title&lt;/span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;title&lt;/span&gt;&amp;gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;script &lt;/span&gt;src&lt;/span&gt;=&amp;quot;http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js&amp;quot; &lt;/span&gt;type&lt;/span&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&amp;gt;&amp;lt;&lt;/span&gt;script &lt;/span&gt;type&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;    if &lt;/span&gt;(typeof &lt;/span&gt;jQuery != 'object'&lt;/span&gt;)        document.write(unescape(&amp;quot;%3Cscript src='/WestWindWebToolkitWeb/scripts/jquery-ui-custom.min.js' type='text/javascript'%3E%3C/script%3E&amp;quot;&lt;/span&gt;));&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;script &lt;/span&gt;type&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;    &lt;/span&gt;$().ready(function&lt;/span&gt;() { alert('hello'&lt;/span&gt;); });&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&lt;/strong&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&amp;lt;/&lt;/span&gt;head&lt;/span&gt;&amp;gt;&amp;lt;&lt;/span&gt;body&lt;/span&gt;&amp;gt;&lt;br /&gt;&lt;/span&gt;&amp;lt;/&lt;/span&gt;body&lt;/span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;html&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt;As you can see theres a bit more control in this process as you can inject both script includes and script blocks into the document at the top or bottom of the header, plus if necessary at the usual body locations. This is quite useful especially if you create custom server controls that interoperate with script and have certain dependencies. The above is a good example of a useful switchable routine where you can switch where scripts load from by default  the above pulls from Google CDN but a configuration switch may automatically switch to pull from the local development copies if your doing development for example.&lt;/p&gt;&lt;h3&gt;How does it work?&lt;/h3&gt;&lt;p&gt;As mentioned the ClientScriptProxy object mimicks many of the ScriptManager script related methods and so provides close API compatibility with it although it contains many additional overloads that enhance functionality. It does however work against ScriptManager if its available on the page, or Page.ClientScript if its not so it provides a single unified frontend to script access. There are however many overloads of the original SM methods like the above to provide additional functionality.&lt;/p&gt;&lt;p&gt;The implementation of script header rendering is pretty straight forward  as long as a server header (ie. it has to have runat=server set) is available. Otherwise these routines fall back to using the default document level insertions of ScriptManager/ClientScript. Given that there is a server header its relatively easy to generate the script tags and code and append them to the header either at the top or bottom. I suspect Microsoft didnt provide header rendering functionality precisely because a runat=server header is not required by ASP.NET so behavior would be slightly unpredictable. Thats not really a problem for a custom implementation however.&lt;/p&gt;&lt;p&gt;Heres the RegisterClientScriptBlock implementation that takes a ScriptRenderModes parameter to allow header rendering:&lt;/p&gt;&lt;pre class="code"&gt;/// &amp;lt;summary&amp;gt;/// &lt;/span&gt;Renders client script block with the option of rendering the script block in&lt;/span&gt;/// &lt;/span&gt;the Html header&lt;/span&gt;/// /// &lt;/span&gt;For this to work Header must be defined as runat=&amp;quot;server&amp;quot;&lt;/span&gt;/// &amp;lt;/summary&amp;gt;/// &amp;lt;param name=&amp;quot;control&amp;quot;&amp;gt;&lt;/span&gt;any control that instance typically page&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;type&amp;quot;&amp;gt;&lt;/span&gt;Type that identifies this rendering&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;key&amp;quot;&amp;gt;&lt;/span&gt;unique script block id&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;script&amp;quot;&amp;gt;&lt;/span&gt;The script code to render&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;addScriptTags&amp;quot;&amp;gt;&lt;/span&gt;Ignored for header rendering used for all other insertions&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;renderMode&amp;quot;&amp;gt;&lt;/span&gt;Where the block is rendered&lt;/span&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;public void &lt;/span&gt;RegisterClientScriptBlock(Control &lt;/span&gt;control, Type &lt;/span&gt;type, string &lt;/span&gt;key, string &lt;/span&gt;script, bool &lt;/span&gt;addScriptTags, ScriptRenderModes &lt;/span&gt;renderMode){    if &lt;/span&gt;(renderMode == ScriptRenderModes&lt;/span&gt;.Inherit)        renderMode = DefaultScriptRenderMode;    if &lt;/span&gt;(control.Page.Header == null &lt;/span&gt;|| renderMode != ScriptRenderModes&lt;/span&gt;.HeaderTop &amp;&amp; renderMode != ScriptRenderModes&lt;/span&gt;.Header)    {        RegisterClientScriptBlock(control, type, key, script, addScriptTags);        return&lt;/span&gt;;    }    // No dupes - ref script include only once    &lt;/span&gt;const string &lt;/span&gt;identifier = &amp;quot;scriptblock_&amp;quot;&lt;/span&gt;;    if &lt;/span&gt;(HttpContext&lt;/span&gt;.Current.Items.Contains(identifier + key))        return&lt;/span&gt;;    HttpContext&lt;/span&gt;.Current.Items.Add(identifier + key, string&lt;/span&gt;.Empty);    StringBuilder &lt;/span&gt;sb = new &lt;/span&gt;StringBuilder&lt;/span&gt;();    // Embed in header    &lt;/span&gt;sb.AppendLine(&amp;quot;\r\n&amp;lt;script type=\&amp;quot;text/javascript\&amp;quot;&amp;gt;&amp;quot;&lt;/span&gt;);    sb.AppendLine(script);                sb.AppendLine(&amp;quot;&amp;lt;/script&amp;gt;&amp;quot;&lt;/span&gt;);    int&lt;/span&gt;? index = HttpContext&lt;/span&gt;.Current.Items[&amp;quot;__ScriptResourceIndex&amp;quot;&lt;/span&gt;] as int&lt;/span&gt;?;    if &lt;/span&gt;(index == null&lt;/span&gt;)        index = 0;    if &lt;/span&gt;(renderMode == ScriptRenderModes&lt;/span&gt;.HeaderTop)    {        control.Page.Header.Controls.AddAt(index.Value, new &lt;/span&gt;LiteralControl&lt;/span&gt;(sb.ToString()));        index++;    }    else        &lt;/span&gt;control.Page.Header.Controls.Add(new &lt;/span&gt;LiteralControl&lt;/span&gt;(sb.ToString()));        HttpContext&lt;/span&gt;.Current.Items[&amp;quot;__ScriptResourceIndex&amp;quot;&lt;/span&gt;] = index;            }&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;Note that the routine has to keep track of items inserted by id so that if the same item is added again with the same key it wont generate two script entries. Additionally the code has to keep track of how many insertions have been made at the top of the document so that entries are added in the proper order.&lt;/p&gt;&lt;p&gt;The RegisterScriptInclude method is similar but theres some additional logic in here to deal with script file references and ClientScriptProxys (optional) custom resource handler that provides script compression&lt;/p&gt;&lt;pre class="code"&gt;/// &amp;lt;summary&amp;gt;/// &lt;/span&gt;Registers a client script reference into the page with the option to specify&lt;/span&gt;/// &lt;/span&gt;the script location in the page&lt;/span&gt;/// &amp;lt;/summary&amp;gt;/// &amp;lt;param name=&amp;quot;control&amp;quot;&amp;gt;&lt;/span&gt;Any control instance - typically page&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;type&amp;quot;&amp;gt;&lt;/span&gt;Type that acts as qualifier (uniqueness)&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;url&amp;quot;&amp;gt;&lt;/span&gt;the Url to the script resource&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;ScriptRenderModes&amp;quot;&amp;gt;&lt;/span&gt;Determines where the script is rendered&lt;/span&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;public void &lt;/span&gt;RegisterClientScriptInclude(Control &lt;/span&gt;control, Type &lt;/span&gt;type, string &lt;/span&gt;url, ScriptRenderModes &lt;/span&gt;renderMode){    if &lt;/span&gt;(string&lt;/span&gt;.IsNullOrEmpty(url))        return&lt;/span&gt;;    if &lt;/span&gt;(renderMode == ScriptRenderModes&lt;/span&gt;.Inherit)        renderMode = DefaultScriptRenderMode;    // Extract just the script filename    &lt;/span&gt;string &lt;/span&gt;fileId = null&lt;/span&gt;;            // Check resource IDs and try to match to mapped file resources    // Used to allow scripts not to be loaded more than once whether    // embedded manually (script tag) or via resources with ClientScriptProxy    &lt;/span&gt;if &lt;/span&gt;(url.Contains(&amp;quot;.axd?r=&amp;quot;&lt;/span&gt;))    {        string &lt;/span&gt;res = HttpUtility&lt;/span&gt;.UrlDecode( StringUtils&lt;/span&gt;.ExtractString(url, &amp;quot;?r=&amp;quot;&lt;/span&gt;, &amp;quot;&amp;&amp;quot;&lt;/span&gt;, false&lt;/span&gt;, true&lt;/span&gt;) );        foreach &lt;/span&gt;(ScriptResourceAlias &lt;/span&gt;item in &lt;/span&gt;ScriptResourceAliases)        {            if &lt;/span&gt;(item.Resource == res)            {                fileId = item.Alias + &amp;quot;.js&amp;quot;&lt;/span&gt;;                break&lt;/span&gt;;            }        }        if &lt;/span&gt;(fileId == null&lt;/span&gt;)            fileId = url.ToLower();    }    else        &lt;/span&gt;fileId = Path&lt;/span&gt;.GetFileName(url).ToLower();    // No dupes - ref script include only once    &lt;/span&gt;const string &lt;/span&gt;identifier = &amp;quot;script_&amp;quot;&lt;/span&gt;;    if &lt;/span&gt;(HttpContext&lt;/span&gt;.Current.Items.Contains( identifier + fileId ) )        return&lt;/span&gt;;        HttpContext&lt;/span&gt;.Current.Items.Add(identifier + fileId, string&lt;/span&gt;.Empty);    if &lt;/span&gt;(control.Page.Header == null &lt;/span&gt;|| renderMode == ScriptRenderModes&lt;/span&gt;.Script || renderMode == ScriptRenderModes&lt;/span&gt;.Inline)    {        RegisterClientScriptInclude(control, type,url, url);        return&lt;/span&gt;;    }    // Retrieve script index in header    &lt;/span&gt;object &lt;/span&gt;val = HttpContext&lt;/span&gt;.Current.Items[&amp;quot;__ScriptResourceIndex&amp;quot;&lt;/span&gt;];    int &lt;/span&gt;index = 0;    if &lt;/span&gt;(val != null&lt;/span&gt;)        index = (int&lt;/span&gt;)val;    StringBuilder &lt;/span&gt;sb = new &lt;/span&gt;StringBuilder&lt;/span&gt;(256);    url = WebUtils&lt;/span&gt;.ResolveUrl(url);    // Embed in header    &lt;/span&gt;sb.AppendLine(@&amp;quot;&amp;lt;script src=&amp;quot;&amp;quot;&amp;quot; &lt;/span&gt;+ url + @&amp;quot;&amp;quot;&amp;quot; type=&amp;quot;&amp;quot;text/javascript&amp;quot;&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;quot;&lt;/span&gt;);    if &lt;/span&gt;(renderMode == ScriptRenderModes&lt;/span&gt;.HeaderTop)    {        control.Page.Header.Controls.AddAt(index, new &lt;/span&gt;LiteralControl&lt;/span&gt;(sb.ToString()));        index++;    }    else        &lt;/span&gt;control.Page.Header.Controls.Add(new &lt;/span&gt;LiteralControl&lt;/span&gt;(sb.ToString()));    HttpContext&lt;/span&gt;.Current.Items[&amp;quot;__ScriptResourceIndex&amp;quot;&lt;/span&gt;] = index;}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;Theres a little more code here that deals with cleaning up the passed in Url and also some custom handling of script resources that run through the ScriptCompressionModule  any script resources loaded in this fashion are automatically cached based on the resource id. Raw urls extract just the filename from the URL and cache based on that. All of this to avoid doubling up of scripts if called multiple times by multiple instances of the same control for example or several controls that all load the same resources/includes.&lt;/p&gt;&lt;p&gt;Finally RegisterClientScriptResource utilizes the previous method to wrap the WebResourceUrl as well as some custom functionality for the resource compression module:&lt;/p&gt;&lt;pre class="code"&gt;/// &amp;lt;summary&amp;gt;/// &lt;/span&gt;Returns a WebResource or ScriptResource URL for script resources that are to be&lt;/span&gt;/// &lt;/span&gt;embedded as script includes.&lt;/span&gt;/// &amp;lt;/summary&amp;gt;/// &amp;lt;param name=&amp;quot;control&amp;quot;&amp;gt;&lt;/span&gt;Any control&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;type&amp;quot;&amp;gt;&lt;/span&gt;A type in assembly where resources are located&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;resourceName&amp;quot;&amp;gt;&lt;/span&gt;Name of the resource to load&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;renderMode&amp;quot;&amp;gt;&lt;/span&gt;Determines where in the document the link is rendered&lt;/span&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;public void &lt;/span&gt;RegisterClientScriptResource(Control &lt;/span&gt;control, Type &lt;/span&gt;type,                                          string &lt;/span&gt;resourceName,                                          ScriptRenderModes &lt;/span&gt;renderMode){     string &lt;/span&gt;resourceUrl = GetClientScriptResourceUrl(control, type, resourceName);    RegisterClientScriptInclude(control, type, resourceUrl, renderMode);}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre class="code"&gt;/// &amp;lt;summary&amp;gt;/// &lt;/span&gt;Works like GetWebResourceUrl but can be used with javascript resources&lt;/span&gt;/// &lt;/span&gt;to allow using of resource compression (if the module is loaded).&lt;/span&gt;/// &amp;lt;/summary&amp;gt;/// &amp;lt;param name=&amp;quot;control&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;type&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;resourceName&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;public string &lt;/span&gt;GetClientScriptResourceUrl(Control &lt;/span&gt;control, Type &lt;/span&gt;type, string &lt;/span&gt;resourceName){                #if &lt;/span&gt;IncludeScriptCompressionModuleSupport    // If wwScriptCompression Module through Web.config is loaded use it to compress     // script resources by using wcSC.axd Url the module intercepts    &lt;/span&gt;if &lt;/span&gt;(ScriptCompressionModule&lt;/span&gt;.ScriptCompressionModuleActive)     {        string &lt;/span&gt;url = &amp;quot;~/wwSC.axd?r=&amp;quot; &lt;/span&gt;+ HttpUtility&lt;/span&gt;.UrlEncode(resourceName);        if &lt;/span&gt;(type.Assembly != GetType().Assembly)            url += &amp;quot;&amp;t=&amp;quot; &lt;/span&gt;+ HttpUtility&lt;/span&gt;.UrlEncode(type.FullName);                return &lt;/span&gt;WebUtils&lt;/span&gt;.ResolveUrl(url);    }        #endif    return &lt;/span&gt;control.Page.ClientScript.GetWebResourceUrl(type, resourceName);}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;This code merely retrieves the resource URL and then simply calls back to RegisterClientScriptInclude with the URL to be embedded which means theres nothing specific to deal with other than the custom compression module logic which is nice and easy.&lt;/p&gt;&lt;h3&gt;What else is there in ClientScriptProxy?&lt;/h3&gt;&lt;p&gt;ClientscriptProxy also provides a few other useful services beyond what Ive already covered here:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Transparent ScriptManager and ClientScript calls&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;ClientScriptProxy includes a host of routines that help figure out whether a script manager is available or not and all functions in this class call the appropriate object  ScriptManager or ClientScript  that is available in the current page to ensure that scripts get embedded into pages properly. This is especially useful for control development where controls have no control over the scripting environment in place on the page.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;RegisterCssLink and RegisterCssResource    &lt;br /&gt;&lt;/strong&gt;Much like the script embedding functions these two methods allow embedding of CSS links. CSS links are appended to the header or to a form declared with runat=server. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;LoadControlScript&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Is a high level resource loading routine that can be used to easily switch between different script linking modes. It supports loading from a WebResource, a url or not loading anything at all. This is very useful if you build controls that deal with specification of resource urls/ids in a standard way.&lt;/p&gt;&lt;h3&gt;Check out the full Code&lt;/h3&gt;&lt;p&gt;You can check out the full code to the ClientScriptProxyClass here:&lt;/p&gt;&lt;p&gt;&lt;a href="http://codepaste.net/ShowUrl?url=http%3A%2F%2Fwww.west-wind.com%3A8080%2Fsvn%2FWestwindWebToolkit%2Ftrunk%2FWestwind.Web%2FSupport%2FClientScriptProxy.cs&amp;Language=C%23" target="_blank"&gt;&lt;strong&gt;ClientScriptProxy.cs&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.west-wind.com/WestwindWebToolkit/docs?page=_2nb07bxb7.htm" target="_blank"&gt;&lt;strong&gt;ClientScriptProxy Documentation&lt;/strong&gt;&lt;/a&gt; (&lt;a href="http://www.west-wind.com/WestwindWebToolkit/docs?page=_2te14de34.htm" target="_blank"&gt;class reference&lt;/a&gt;)&lt;/p&gt;&lt;p&gt;Note that the ClientScriptProxy has a few dependencies in the &lt;a href="http://www.west-wind.com/westwindwebtoolkit/" target="WebToolkit"&gt;West Wind Web Toolkit&lt;/a&gt; of which it is part of. ControlResources holds a few standard constants and script resource links and the ScriptCompressionModule which is referenced in a few of the script inclusion methods. &lt;/p&gt;&lt;p&gt;Theres also another useful &lt;a href="http://www.west-wind.com/WestwindWebToolkit/docs?page=_2nb0uh361.htm" target="_blank"&gt;ScriptContainer companion control&lt;/a&gt;&amp;#160; to the ClientScriptProxy that allows scripts to be placed onto the pages markup including the ability to specify the script location and script minification options.&lt;/p&gt;&lt;p&gt;You can find all the dependencies in the &lt;a href="http://www.west-wind.com/westwindwebtoolkit/" target="WebToolkit"&gt;West Wind Web Toolkit&lt;/a&gt; repository:&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.west-wind.com:8080/svn/WestwindWebToolkit/trunk/Westwind.Web/" target="_blank"&gt;&lt;strong&gt;West Wind Web Toolkit Repository&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.west-wind.com/WestwindWebToolkit/" target="_blank"&gt;&lt;strong&gt;West Wind Web Toolkit Home Page&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;small&gt; Rick Strahl, West Wind Technologies, 2005-2010&lt;/small&gt;&lt;a href='/Weblog/ShowPosts.aspx?Category= ASP.NET'&gt; ASP.NET&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;a href='/Weblog/ShowPosts.aspx?Category=JavaScript'&gt;JavaScript&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f154797.aspx&amp;title=Rendering+ASP.NET+Script+References+into+the+Html+Header"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f154797.aspx" border='0' alt='kick it on DotNetKicks.com' /&gt;&lt;/a&gt;&lt;/small&gt;&lt;p&gt;&lt;a href='http://west-wind.com/Weblog/wwBanner.ashx?a=c&amp;id=8815900f&amp;t=633980291976020000' target='_top'&gt;&lt;img src='http://www.west-wind.com/banners/wwHelpBanner.Gif' border='0'&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=KNhRLQI5gWY:ki5Rav9Oj0w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=KNhRLQI5gWY:ki5Rav9Oj0w:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=KNhRLQI5gWY:ki5Rav9Oj0w:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=KNhRLQI5gWY:ki5Rav9Oj0w:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=KNhRLQI5gWY:ki5Rav9Oj0w:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=KNhRLQI5gWY:ki5Rav9Oj0w:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=KNhRLQI5gWY:ki5Rav9Oj0w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=KNhRLQI5gWY:ki5Rav9Oj0w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=KNhRLQI5gWY:ki5Rav9Oj0w:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/RickStrahl/~4/KNhRLQI5gWY" height="1" width="1"/&gt;</description><author>Rick Strahls WebLog                                                                                 </author><pubDate>Sat, 02 Jan 2010 00:00:00 GMT</pubDate></item><item><title>LINQ to SQL and missing Many to Many EntityRefs</title><link>http://feedproxy.google.com/~r/RickStrahl/~3/g5dJ4kUjFTw/137000.aspx</link><description>&lt;p&gt;Ran into an odd behavior today with a many to many mapping of one of my tables in LINQ to SQL. Many to many mappings arent transparent in LINQ to SQL and it maps the link table the same way the SQL schema has it when creating one. In other words LINQ to SQL isnt smart about many to many mappings and just treats it like the 3 underlying tables that make up the many to many relationship. &lt;a href="http://www.iaingalloway.com/many-to-many-relationships-in-linq-to-sql" target="_blank"&gt;Iain Galloway has a nice blog entry&lt;/a&gt; about Many to Many relationships in LINQ to SQL.&lt;/p&gt;  &lt;p&gt;I can live with that  its not really difficult to deal with this arrangement once mapped, especially when reading data back. Writing is a little more difficult as you do have to insert into two entities for new records, but nothing that cant be handled in a small business object method with a few lines of code.&lt;/p&gt;  &lt;p&gt;When I created a database Ive been using to experiment around with various different OR/Ms recently I found that for some reason LINQ to SQL was completely failing to map even to the linking table. As it turns out theres a good reason why it fails, can you spot it below? (read on :-})&lt;/p&gt;  &lt;p&gt;Here is the original database layout:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Schema" border="0" alt="Schema" src="http://www.west-wind.com/Weblog/images/200901/WindowsLiveWriter/LINQtoSQLandaManytoManyMappingIssue_14709/Schema_80a7a0e0-d09c-418d-9361-363a5d7f3709.png" width="800" height="352" /&gt; &lt;/p&gt;  &lt;p&gt;Theres an items table, a category table and a link table that holds only the foreign keys to the Items and Category tables for a typical M-&amp;gt;M relationship.&lt;/p&gt;  &lt;p&gt;When these three tables are imported into the model the *look* correct  I do get the relationships added (after modifying the entity names to strip the prefix):&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Model" border="0" alt="Model" src="http://www.west-wind.com/Weblog/images/200901/WindowsLiveWriter/LINQtoSQLandaManytoManyMappingIssue_14709/Model_96da4c41-012b-4b51-bcc7-2c0717f830a5.png" width="556" height="397" /&gt; &lt;/p&gt;  &lt;p&gt;The relationship looks perfectly fine, both in the designer as well as in the XML document:&lt;/p&gt;  &lt;pre class="code"&gt;  &amp;lt;&lt;/span&gt;Table &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;dbo.wws_Item_Categories&lt;/span&gt;&amp;quot; Member&lt;/span&gt;=&lt;/span&gt;&amp;quot;ItemCategories&lt;/span&gt;&amp;quot;&amp;gt;    &amp;lt;&lt;/span&gt;Type &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;ItemCategory&lt;/span&gt;&amp;quot;&amp;gt;      &amp;lt;&lt;/span&gt;Column &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;ItemId&lt;/span&gt;&amp;quot; Type&lt;/span&gt;=&lt;/span&gt;&amp;quot;System.Guid&lt;/span&gt;&amp;quot; DbType&lt;/span&gt;=&lt;/span&gt;&amp;quot;uniqueidentifier NOT NULL&lt;/span&gt;&amp;quot; CanBeNull&lt;/span&gt;=&lt;/span&gt;&amp;quot;false&lt;/span&gt;&amp;quot; /&amp;gt;      &amp;lt;&lt;/span&gt;Column &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;CategoryId&lt;/span&gt;&amp;quot; Type&lt;/span&gt;=&lt;/span&gt;&amp;quot;System.Guid&lt;/span&gt;&amp;quot; DbType&lt;/span&gt;=&lt;/span&gt;&amp;quot;uniqueidentifier NOT NULL&lt;/span&gt;&amp;quot; CanBeNull&lt;/span&gt;=&lt;/span&gt;&amp;quot;false&lt;/span&gt;&amp;quot; /&amp;gt;&lt;strong&gt;      &amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;Association &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;ItemCategory_Category&lt;/span&gt;&amp;quot; Member&lt;/span&gt;=&lt;/span&gt;&amp;quot;Categories&lt;/span&gt;&amp;quot; ThisKey&lt;/span&gt;=&lt;/span&gt;&amp;quot;CategoryId&lt;/span&gt;&amp;quot; OtherKey&lt;/span&gt;=&lt;/span&gt;&amp;quot;Id&lt;/span&gt;&amp;quot; Type&lt;/span&gt;=&lt;/span&gt;&amp;quot;Category&lt;/span&gt;&amp;quot; &lt;/strong&gt;&lt;strong&gt;/&amp;gt;      &amp;lt;&lt;/span&gt;Association &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;Item_ItemCategory&lt;/span&gt;&amp;quot; Member&lt;/span&gt;=&lt;/span&gt;&amp;quot;Item&lt;/span&gt;&amp;quot; ThisKey&lt;/span&gt;=&lt;/span&gt;&amp;quot;ItemId&lt;/span&gt;&amp;quot; OtherKey&lt;/span&gt;=&lt;/span&gt;&amp;quot;Id&lt;/span&gt;&amp;quot; Type&lt;/span&gt;=&lt;/span&gt;&amp;quot;Item&lt;/span&gt;&amp;quot; IsForeignKey&lt;/span&gt;=&lt;/span&gt;&amp;quot;true&lt;/span&gt;&amp;quot; &lt;/strong&gt;&lt;strong&gt;/&amp;gt;&lt;/strong&gt;    &amp;lt;/&lt;/span&gt;Type&lt;/span&gt;&amp;gt;  &amp;lt;/&lt;/span&gt;Table&lt;/span&gt;&amp;gt;  &amp;lt;&lt;/span&gt;Table &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;dbo.wws_Categories&lt;/span&gt;&amp;quot; Member&lt;/span&gt;=&lt;/span&gt;&amp;quot;Categories&lt;/span&gt;&amp;quot;&amp;gt;    &amp;lt;&lt;/span&gt;Type &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;Category&lt;/span&gt;&amp;quot;&amp;gt;      &amp;lt;&lt;/span&gt;Column &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;Id&lt;/span&gt;&amp;quot; Type&lt;/span&gt;=&lt;/span&gt;&amp;quot;System.Guid&lt;/span&gt;&amp;quot; DbType&lt;/span&gt;=&lt;/span&gt;&amp;quot;UniqueIdentifier NOT NULL&lt;/span&gt;&amp;quot; IsPrimaryKey&lt;/span&gt;=&lt;/span&gt;&amp;quot;true&lt;/span&gt;&amp;quot; IsDbGenerated&lt;/span&gt;=&lt;/span&gt;&amp;quot;true&lt;/span&gt;&amp;quot; CanBeNull&lt;/span&gt;=&lt;/span&gt;&amp;quot;false&lt;/span&gt;&amp;quot; /&amp;gt;      &amp;lt;&lt;/span&gt;Column &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;ParentId&lt;/span&gt;&amp;quot; Type&lt;/span&gt;=&lt;/span&gt;&amp;quot;System.Guid&lt;/span&gt;&amp;quot; DbType&lt;/span&gt;=&lt;/span&gt;&amp;quot;UniqueIdentifier&lt;/span&gt;&amp;quot; CanBeNull&lt;/span&gt;=&lt;/span&gt;&amp;quot;true&lt;/span&gt;&amp;quot; /&amp;gt;      &amp;lt;&lt;/span&gt;Column &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;CategoryName&lt;/span&gt;&amp;quot; Type&lt;/span&gt;=&lt;/span&gt;&amp;quot;System.String&lt;/span&gt;&amp;quot; DbType&lt;/span&gt;=&lt;/span&gt;&amp;quot;NVarChar(150)&lt;/span&gt;&amp;quot; CanBeNull&lt;/span&gt;=&lt;/span&gt;&amp;quot;true&lt;/span&gt;&amp;quot; /&amp;gt;      &amp;lt;&lt;/span&gt;Column &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;CategoryDescription&lt;/span&gt;&amp;quot; Type&lt;/span&gt;=&lt;/span&gt;&amp;quot;System.String&lt;/span&gt;&amp;quot; DbType&lt;/span&gt;=&lt;/span&gt;&amp;quot;NVarChar(MAX)&lt;/span&gt;&amp;quot; CanBeNull&lt;/span&gt;=&lt;/span&gt;&amp;quot;true&lt;/span&gt;&amp;quot; /&amp;gt;      &amp;lt;&lt;/span&gt;Column &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;tstamp&lt;/span&gt;&amp;quot; AccessModifier&lt;/span&gt;=&lt;/span&gt;&amp;quot;Internal&lt;/span&gt;&amp;quot; Type&lt;/span&gt;=&lt;/span&gt;&amp;quot;System.Data.Linq.Binary&lt;/span&gt;&amp;quot; DbType&lt;/span&gt;=&lt;/span&gt;&amp;quot;rowversion&lt;/span&gt;&amp;quot; CanBeNull&lt;/span&gt;=&lt;/span&gt;&amp;quot;true&lt;/span&gt;&amp;quot; IsVersion&lt;/span&gt;=&lt;/span&gt;&amp;quot;true&lt;/span&gt;&amp;quot; /&amp;gt;&lt;strong&gt;      &amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;Association &lt;/span&gt;Name&lt;/span&gt;=&lt;/span&gt;&amp;quot;ItemCategory_Category&lt;/span&gt;&amp;quot; Member&lt;/span&gt;=&lt;/span&gt;&amp;quot;ItemCategory&lt;/span&gt;&amp;quot; ThisKey&lt;/span&gt;=&lt;/span&gt;&amp;quot;Id&lt;/span&gt;&amp;quot; OtherKey&lt;/span&gt;=&lt;/span&gt;&amp;quot;CategoryId&lt;/span&gt;&amp;quot; Type&lt;/span&gt;=&lt;/span&gt;&amp;quot;ItemCategory&lt;/span&gt;&amp;quot; IsForeignKey&lt;/span&gt;=&lt;/span&gt;&amp;quot;true&lt;/span&gt;&amp;quot; &lt;/strong&gt;&lt;strong&gt;/&amp;gt;&lt;/strong&gt;    &amp;lt;/&lt;/span&gt;Type&lt;/span&gt;&amp;gt;  &amp;lt;/&lt;/span&gt;Table&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;However when looking at the code generated these navigation properties (also on Item) are completely missing:&lt;/p&gt;&lt;pre class="code"&gt;[global&lt;/span&gt;::System.Data.Linq.Mapping.TableAttribute&lt;/span&gt;(Name=&amp;quot;dbo.wws_Item_Categories&amp;quot;&lt;/span&gt;)][global&lt;/span&gt;::System.Runtime.Serialization.DataContractAttribute&lt;/span&gt;()]public partial class &lt;/span&gt;ItemCategory &lt;/span&gt;: Westwind.BusinessFramework.EntityBase&lt;/span&gt;{    private &lt;/span&gt;System.Guid &lt;/span&gt;_ItemId;    private &lt;/span&gt;System.Guid &lt;/span&gt;_CategoryId;        public &lt;/span&gt;ItemCategory()    {    }        [global&lt;/span&gt;::System.Data.Linq.Mapping.ColumnAttribute&lt;/span&gt;(Storage=&amp;quot;_ItemId&amp;quot;&lt;/span&gt;, DbType=&amp;quot;uniqueidentifier NOT NULL&amp;quot;&lt;/span&gt;)]    [global&lt;/span&gt;::System.Runtime.Serialization.DataMemberAttribute&lt;/span&gt;(Order=1&lt;/span&gt;)]    public &lt;/span&gt;System.Guid &lt;/span&gt;ItemId    {        get        &lt;/span&gt;{            return this&lt;/span&gt;._ItemId;        }        set        &lt;/span&gt;{            if &lt;/span&gt;((this&lt;/span&gt;._ItemId != value&lt;/span&gt;))            {                this&lt;/span&gt;._ItemId = value&lt;/span&gt;;            }        }    }        [global&lt;/span&gt;::System.Data.Linq.Mapping.ColumnAttribute&lt;/span&gt;(Storage=&amp;quot;_CategoryId&amp;quot;&lt;/span&gt;, DbType=&amp;quot;uniqueidentifier NOT NULL&amp;quot;&lt;/span&gt;)]    [global&lt;/span&gt;::System.Runtime.Serialization.DataMemberAttribute&lt;/span&gt;(Order=2&lt;/span&gt;)]    public &lt;/span&gt;System.Guid &lt;/span&gt;CategoryId    {        get        &lt;/span&gt;{            return this&lt;/span&gt;._CategoryId;        }        set        &lt;/span&gt;{            if &lt;/span&gt;((this&lt;/span&gt;._CategoryId != value&lt;/span&gt;))            {                this&lt;/span&gt;._CategoryId = value&lt;/span&gt;;            }        }    }}&lt;/pre&gt;&lt;p&gt;Notice that the Item and Category association properties which should be EntityRef properties are completely missing. Theyre there in the model, but the generated code  not so much.&lt;/p&gt;&lt;p&gt;So whats the problem here?&lt;/p&gt;&lt;p&gt;The problem  it appears  is that LINQ to SQL requires primary keys on all entities it tracks. In order to support tracking  even of the link table entity  the link table requires a primary key. Real obvious aint it, especially since the designer happily lets you import the table and even shows the relationship and implicitly the related properties.&lt;/p&gt;&lt;p&gt;Adding an Id field as a Pk to the database and then importing results in this model layout:&lt;/p&gt;&lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="ModelLinkWithPk" border="0" alt="ModelLinkWithPk" src="http://www.west-wind.com/Weblog/images/200901/WindowsLiveWriter/LINQtoSQLandaManytoManyMappingIssue_14709/ModelLinkWithPk_c984b31e-5315-4b1f-9f2e-1ac0b958ac4b.png" width="871" height="410" /&gt; &lt;/p&gt;&lt;p&gt;which properly generates the Item and Category properties into the link entity.&lt;/p&gt;&lt;p&gt;Its ironic that LINQ to SQL *requires* the PK in the middle  the Entity Framework requires that a link table have *only* the two foreign key fields in a table in order to recognize a many to many relation. EF actually handles the M-&amp;gt;M relation directly without the intermediate link entity unlike LINQ to SQL.&lt;/p&gt;&lt;p&gt;It took me a while to figure out WTF was going on here  lulled by the designer to think that the properties should be when they were not. Its actually a well documented feature of L2S that each entity in the model requires a Pk but of course thats easy to miss when the model viewer shows it to you and even the underlying XML model shows the Associations properly. &lt;/p&gt;&lt;p&gt;This is one of the issue with L2S of course  you have to play by its rules and once you hit one of those rules theres no way around them  youre stuck with what it requires which in this case meant changing the database.&lt;/p&gt;&lt;small&gt; Rick Strahl, West Wind Technologies, 2005-2009&lt;/small&gt;&lt;a href='/Weblog/ShowPosts.aspx?Category=ADO.NET'&gt;ADO.NET&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;a href='/Weblog/ShowPosts.aspx?Category=LINQ'&gt;LINQ&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f137000.aspx&amp;title=LINQ+to+SQL+and+missing+Many+to+Many+EntityRefs"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f137000.aspx" border='0' alt='kick it on DotNetKicks.com' /&gt;&lt;/a&gt;&lt;/small&gt;&lt;p&gt;&lt;a href='http://west-wind.com/Weblog/wwBanner.ashx?a=c&amp;id=e47b9595&amp;t=633972517308720000' target='_top'&gt;&lt;img src='http://www.west-wind.com/banners/wwstore_small.gif' border='0'&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=g5dJ4kUjFTw:wPOKNBxPyOc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=g5dJ4kUjFTw:wPOKNBxPyOc:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=g5dJ4kUjFTw:wPOKNBxPyOc:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=g5dJ4kUjFTw:wPOKNBxPyOc:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=g5dJ4kUjFTw:wPOKNBxPyOc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=g5dJ4kUjFTw:wPOKNBxPyOc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=g5dJ4kUjFTw:wPOKNBxPyOc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=g5dJ4kUjFTw:wPOKNBxPyOc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=g5dJ4kUjFTw:wPOKNBxPyOc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/RickStrahl/~4/g5dJ4kUjFTw" height="1" width="1"/&gt;</description><author>Rick Strahls WebLog                                                                                 </author><pubDate>Thu, 24 Dec 2009 00:00:00 GMT</pubDate></item><item><title>Making Sense of ASP.NET Paths</title><link>http://feedproxy.google.com/~r/RickStrahl/~3/XCBN-wW6uZk/132081.aspx</link><description>&lt;p&gt;ASP.Net includes quite a plethora of properties to retrieve path information about the current request, control and application. There's a ton of information available about paths on the Request object, some of it appearing to overlap and some of it buried several levels down, and it can be confusing to find just the right path that you are looking for. &lt;/p&gt;  &lt;p&gt;To keep things straight I thought it a good idea to summarize the path options along with descriptions and example paths. I wrote a post about this a long time ago in 2004 and I find myself frequently going back to that page to quickly figure out which path Im looking for in processing the current URL. Apparently &lt;strong&gt;a lot&lt;/strong&gt; of people must be doing the same, because the original post is the second most visited hit even to this date on this blog to the tune of nearly 500 per day. So, I decided to update and expand a bit on the original post with a little more information and clarification based on the original comments.&lt;/p&gt;  &lt;h3&gt;Request Object Paths Available&lt;/h3&gt;  &lt;p&gt;So, here's a list of the Path related properties on the Request object (and the Page object). Assume a path like &lt;em&gt;http://www.west-wind.com/webstore/admin/paths.aspx&lt;/em&gt; for the paths below.&lt;/p&gt; &lt;style type="text/css"&gt;.blackborder td{   border-bottom: solid 1px silver;   border-left: solid 1px silver;}&lt;/style&gt;  &lt;table class="blackborder" border="0" cellspacing="0" cellpadding="5" width="776"&gt;&lt;tbody&gt;     &lt;tr class="gridheader"&gt;       &lt;td valign="top" width="261" align="center"&gt;&lt;strong&gt;Request Property&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="515" align="center"&gt;&lt;strong&gt;Description and Value&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="261"&gt;ApplicationPath&lt;/td&gt;        &lt;td valign="top" width="515"&gt;Returns the web root-relative logical path to the &lt;em&gt;virtual root&lt;/em&gt; of this app.           &lt;br /&gt;&lt;strong&gt;/webstore/&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="261"&gt;PhysicalApplicationPath&lt;/td&gt;        &lt;td valign="top" width="515"&gt;Returns &lt;em&gt;local file system path&lt;/em&gt; of the &lt;em&gt;virtual root&lt;/em&gt; for this app.           &lt;br /&gt;&lt;strong&gt;c:\inetpub\wwwroot\webstore&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="261"&gt;PhysicalPath&lt;/td&gt;        &lt;td valign="top" width="515"&gt;Returns the &lt;em&gt;local file system path&lt;/em&gt; to the &lt;em&gt;current script or path&lt;/em&gt;.           &lt;br /&gt;&lt;strong&gt;c:\inetpub\wwwroot\webstore\admin\paths.aspx&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="261"&gt;CurrentExecutionFilePath          &lt;br /&gt;FilePath           &lt;br /&gt;Path&lt;/td&gt;        &lt;td valign="top" width="515"&gt;All of these return the full &lt;em&gt;root relative logical path&lt;/em&gt; to the script page including path and scriptname.           &lt;br /&gt;&lt;strong&gt;/webstore/admin/paths.aspx&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="261"&gt;AppRelativeCurrentExecutionFilePath&lt;/td&gt;        &lt;td valign="top" width="515"&gt;Returns an ASP.NET &lt;em&gt;root relative virtual path&lt;/em&gt; to the script or path           &lt;br /&gt;&lt;strong&gt;~/admin/paths.aspx&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="261"&gt;PathInfo&lt;/td&gt;        &lt;td valign="top" width="515"&gt;Returns any extra path following the script name. If no extra path is provided returns the root-relative path &lt;font size="1" face="ver"&gt;(returns text in red below)&lt;/font&gt;. string.Empty if no PathInfo is available.           &lt;br /&gt;&lt;strong&gt;/webstore/admin/paths.aspx&lt;font color="#800000"&gt;/ExtraPathInfo &lt;/font&gt;&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="261"&gt;RawUrl&lt;/td&gt;        &lt;td valign="top" width="515"&gt;Returns the full root &lt;em&gt;relative relative URL&lt;/em&gt; including querystring and extra path as a string.           &lt;br /&gt;&lt;strong&gt;/webstore/admin/paths.aspx?sku=wwhelp40&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="261"&gt;Url&lt;/td&gt;        &lt;td valign="top" width="515"&gt;Returns a &lt;em&gt;fully qualified URL&lt;/em&gt; including querystring and extra path. Note this is a &lt;em&gt;Uri &lt;/em&gt;instance rather than string.           &lt;br /&gt;&lt;strong&gt;http://www.west-wind.com/webstore/admin/paths.aspx?sku=wwhelp40&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="261"&gt;UrlReferrer&lt;/td&gt;        &lt;td valign="top" width="515"&gt;The &lt;em&gt;fully qualified URL&lt;/em&gt; of the &lt;em&gt;page that sent the request&lt;/em&gt;. This is also a &lt;em&gt;Uri&lt;/em&gt; instance and this value is null if the page was directly accessed by typing into the address bar or using an HttpClient. Based Referrer client Http header.           &lt;br /&gt;&lt;strong&gt;http://www.west-wind.com/webstore/default.aspx?Info&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="261"&gt;&lt;em&gt;Control&lt;/em&gt;.TemplateSourceDirectory&lt;/td&gt;        &lt;td valign="top" width="515"&gt;Returns the &lt;em&gt;logical path to the folder&lt;/em&gt; of the page, master or user control on which it is called. This is useful if you need to know the&lt;em&gt; path only &lt;/em&gt;to a Page or control from within the control. For non-file controls this returns the Page path.           &lt;br /&gt;&lt;strong&gt;/webstore/admin/&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;As you can see theres a ton of information available there for each of the three common path formats:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Physical Path        &lt;br /&gt;&lt;/strong&gt;is an OS type path that points to a path or file on disk.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Logical Path        &lt;br /&gt;&lt;/strong&gt;is a Web path that is relative to the Web servers root. It includes the virtual plus the application relative path.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Virtual Path (~/ aka. root-relative URLs)        &lt;br /&gt;&lt;/strong&gt;is an ASP.NET specific path that includes ~/ to indicate the virtual root Web path. ASP.NET can convert virtual paths into either logical paths using Control.ResolveUrl(), or physical paths using Server.MapPath(). Virtual paths are useful for specifying portable URLs that dont rely on relative directory structures. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;You should be able to get any necessary format from ASP.NET from just about any path or script using these mechanisms.&lt;/p&gt;  &lt;h3&gt;~/ Root Relative Paths and ResolveUrl()&lt;/h3&gt;  &lt;p&gt;ASP.NET supports root-relative virtual path syntax in most of its URL properties in Web Forms. So you can easily specify a root relative path in a control rather than a location relative path:&lt;/p&gt;  &lt;pre class="code"&gt;&amp;lt;&lt;/span&gt;asp&lt;/span&gt;:&lt;/span&gt;Image &lt;/span&gt;runat&lt;/span&gt;=&amp;quot;server&amp;quot; &lt;/span&gt;ID&lt;/span&gt;=&amp;quot;imgHelp&amp;quot;  &lt;/span&gt;&lt;strong&gt;ImageUrl&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;=&amp;quot;~/images/help.gif&amp;quot;&lt;/strong&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;ASP.NET internally resolves this URL by using &lt;strong&gt;ResolveUrl(&amp;quot;~/images/help.gif&amp;quot;)&lt;/strong&gt; to arrive at the root-relative URL of /webstore/images/help.gif which uses the Request.ApplicationPath as the basepath to replace the ~. By convention any custom Web controls also should use ResolveUrl() on URL properties to provide the same functionality.&lt;/p&gt;&lt;p&gt;In your own code you can use Page.ResolveUrl() or Control.ResolveUrl() to accomplish the same thing:&lt;/p&gt;&lt;pre class="code"&gt;string &lt;/span&gt;imgPath = this&lt;/span&gt;.ResolveUrl(&amp;quot;~/images/help.gif&amp;quot;&lt;/span&gt;);imgHelp.ImageUrl = imgPath;&lt;/pre&gt;&lt;p&gt;Unfortunately ResolveUrl() is limited to WebForm pages, so if youre in an HttpHandler or Module its not available. &lt;/p&gt;&lt;p&gt;ASP.NET Mvc also has its own more generic version of ResolveUrl in Url.Decode:&lt;/p&gt;&lt;pre class="code"&gt;&amp;lt;&lt;/span&gt;script &lt;/span&gt;src&lt;/span&gt;=&amp;quot;&lt;/span&gt;&lt;strong&gt;&amp;lt;%&lt;/span&gt;= Url.Content(&amp;quot;~/scripts/new.js&amp;quot;) %&amp;gt;&lt;/span&gt;&lt;/strong&gt;&amp;quot; &lt;/span&gt;type&lt;/span&gt;=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;script&lt;/span&gt;&amp;gt; &lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;which is part of the UrlHelper class. In ASP.NET MVC the above sort of syntax is actually even more crucial than in WebForms due to the fact that views are not referencing specific pages but rather are often path based which can lead to various variations on how a particular view is referenced.&lt;/p&gt;&lt;p&gt;In a Module or Handler code you can also rely on the static VirtualPathUtility class:&lt;/p&gt;&lt;pre class="code"&gt;string &lt;/span&gt;path = VirtualPathUtility&lt;/span&gt;.ToAbsolute(&amp;quot;~/admin/paths.aspx&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.web.virtualpathutility_methods.aspx" target="_blank"&gt;VirtualPathUtility&lt;/a&gt; also many other quite useful methods for dealing with paths and converting between the various kinds of paths supported. One thing to watch out for is that ToAbsolute() will throw an exception if a query string is provided and doesnt work on fully qualified URLs. I wrote about this topic with a custom solution that works fully qualified URLs and query strings &lt;a href="http://www.west-wind.com/Weblog/posts/154812.aspx" target="_blank"&gt;here&lt;/a&gt; (check comments for some interesting discussions too).&lt;/p&gt;&lt;h3&gt;Mapping Virtual Paths to Physical Paths with Server.MapPath()&lt;/h3&gt;&lt;p&gt;If you need to map root relative or current folder relative URLs to physical URLs or you can use HttpContext.Current.Server.MapPath(). Inside of a Page you can do the following:&lt;/p&gt;&lt;pre class="code"&gt;string &lt;/span&gt;physicalPath = Server.MapPath(&amp;quot;~/scripts/ww.jquery.js&amp;quot;&lt;/span&gt;));&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;MapPath is pretty flexible and it understands both ASP.NET style virtual paths as well as plain relative paths, so the following also works.&lt;/p&gt;&lt;pre class="code"&gt;string &lt;/span&gt;physicalPath = Server.MapPath(&amp;quot;scripts/silverlight.js&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;as well as dot relative syntax:&lt;/p&gt;&lt;pre class="code"&gt;string &lt;/span&gt;physicalPath = Server.MapPath(&amp;quot;../scripts/jquery.js&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;Once you have the physical path you can perform standard System.IO Path and File operations on the file. Remember with physical paths and IO or copy operations you need to make sure you have permissions to access files and folders based on the Web server user account that is active (NETWORK SERVICE, ASPNET typically).&lt;/p&gt;&lt;h3&gt;Server and Host Information&lt;/h3&gt;&lt;p&gt;Between these settings you can get all the information you may need to figure out where you are at and to build new Url if necessary. If you need to build a URL completely from scratch you can get access to information about the server you are accessing:&lt;/p&gt;&lt;table class="blackborder" border="0" cellspacing="0" cellpadding="5" width="781"&gt;&lt;tbody&gt;    &lt;tr class="gridheader"&gt;      &lt;td valign="top" width="389" align="center"&gt;&lt;strong&gt;Server Variable&lt;/strong&gt;&lt;/td&gt;      &lt;td valign="top" width="390" align="center"&gt;&lt;strong&gt;Function and Example&lt;/strong&gt;&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="389"&gt;SERVER_NAME&lt;/td&gt;      &lt;td valign="top" width="390"&gt;The of the domain or IP Address         &lt;br /&gt;&lt;strong&gt;wwww.west-wind.com or 127.0.0.1&lt;/strong&gt;&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="389"&gt;SERVER_PORT&lt;/td&gt;      &lt;td valign="top" width="390"&gt;The port that the request runs under.         &lt;br /&gt;&lt;strong&gt;80&lt;/strong&gt;&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="389"&gt;SERVER_PORT_SECURE&lt;/td&gt;      &lt;td valign="top" width="390"&gt;Determines whether https: was used.         &lt;br /&gt;&lt;strong&gt;0 or 1&lt;/strong&gt;&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="389"&gt;APPL_MD_PATH&lt;/td&gt;      &lt;td valign="top" width="390"&gt;ADSI DirectoryServices path to the virtual root directory. Note that LM typically doesnt work for ADSI access so you should replace that with LOCALHOST or the machines NetBios name.         &lt;br /&gt;&lt;strong&gt;/LM/W3SVC/1/ROOT/webstore&lt;/strong&gt;&lt;/td&gt;    &lt;/tr&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h3&gt;Request.Url and Uri Parsing&lt;/h3&gt;&lt;p&gt;If you still need more control over the current request URL or&amp;#160; you need to create new URLs from an existing one, the current Request.Url Uri property offers a lot of control. Using the Uri class and UriBuilder makes it easy to retrieve parts of a URL and create new URLs based on existing URL. The &lt;a href="http://msdn.microsoft.com/en-us/library/system.uribuilder.aspx" target="_blank"&gt;UriBuilder class&lt;/a&gt; is the preferred way to create URLs  much preferable over creating URIs via string concatenation.&lt;/p&gt;&lt;table class="blackborder" border="0" cellspacing="0" cellpadding="5" width="780"&gt;&lt;tbody&gt;    &lt;tr class="gridheader"&gt;      &lt;td valign="top" width="390" align="center"&gt;&lt;strong&gt;Uri Property&lt;/strong&gt;&lt;/td&gt;      &lt;td valign="top" width="390" align="center"&gt;&lt;strong&gt;Function&lt;/strong&gt;&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="390"&gt;Scheme&lt;/td&gt;      &lt;td valign="top" width="390"&gt;The URL scheme or protocol prefix.         &lt;br /&gt;&lt;strong&gt;http or https&lt;/strong&gt;&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="390"&gt;Port&lt;/td&gt;      &lt;td valign="top" width="390"&gt;The port if specifically specified.&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="390"&gt;DnsSafeHost&lt;/td&gt;      &lt;td valign="top" width="390"&gt;The domain name or local host NetBios machine name         &lt;br /&gt;&lt;strong&gt;www.west-wind.com or rasnote&lt;/strong&gt;&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="390"&gt;LocalPath&lt;/td&gt;      &lt;td valign="top" width="390"&gt;The full path of the URL including script name and extra PathInfo.         &lt;br /&gt;&lt;strong&gt;/webstore/admin/paths.aspx&lt;/strong&gt;&lt;/td&gt;    &lt;/tr&gt;    &lt;tr&gt;      &lt;td valign="top" width="390"&gt;Query&lt;/td&gt;      &lt;td valign="top" width="390"&gt;The query string if any         &lt;br /&gt;&lt;strong&gt;?id=1&lt;/strong&gt;&lt;/td&gt;    &lt;/tr&gt;  &lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;The Uri class itself is great for retrieving Uri parts, but most of the properties are read only if you need to modify a URL in order to change it you can use the UriBuilder class to load up an existing URL and modify it to create a new one.&lt;/p&gt;&lt;p&gt;Here are a few common operations Ive needed to do to get specific URLs:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Convert the Request URL to an SSL/HTTPS link&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;For example to take the current request URL and converted&amp;#160; it to a secure URL can be done like this:&lt;/p&gt;&lt;pre class="code"&gt;UriBuilder &lt;/span&gt;build = new &lt;/span&gt;UriBuilder&lt;/span&gt;(Request.Url);build.Scheme = &amp;quot;https&amp;quot;&lt;/span&gt;;build.Port = -1;  // don't inject port&lt;/span&gt;Uri &lt;/span&gt;newUri = build.Uri;string &lt;/span&gt;newUrl = build.ToString();&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;&lt;strong&gt;Retrieve the fully qualified URL without a QueryString     &lt;br /&gt;&lt;/strong&gt;AFAIK, theres no native routine to retrieve the current request URL without the query string. Its easy to do with UriBuilder however:&lt;/p&gt;&lt;p&gt;&lt;font face="Courier New"&gt;UriBuilder &lt;/span&gt;builder = new&lt;/span&gt;UriBuilder&lt;/span&gt;(Request.Url);     &lt;br /&gt;builder.Query = &amp;quot;&amp;quot;&lt;/span&gt;;     &lt;br /&gt;string&lt;/span&gt;logicalPathWithoutQuery = builder.ToString();&lt;/font&gt;&lt;/p&gt;&lt;h3&gt;What else?&lt;/h3&gt;&lt;p&gt;I took a look through the old posts comments and addressed as many of the questions and comments that came up in there. With a few small and silly exceptions this update post handles most of these.&lt;/p&gt;&lt;p&gt;But Im sure there are a more things that go in here. What else would be useful to put onto this post so it serves as a nice all in one place to go for path references? If you think of something leave a comment and Ill try to update the post with it in the future.&lt;/p&gt;&lt;small&gt; Rick Strahl, West Wind Technologies, 2005-2009&lt;/small&gt;&lt;a href='/Weblog/ShowPosts.aspx?Category= ASP.NET'&gt; ASP.NET&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f132081.aspx&amp;title=Making+Sense+of+ASP.NET+Paths"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f132081.aspx" border='0' alt='kick it on DotNetKicks.com' /&gt;&lt;/a&gt;&lt;/small&gt;&lt;p&gt;&lt;a href='http://west-wind.com/Weblog/wwBanner.ashx?a=c&amp;id=8815900f&amp;t=633969847531700000' target='_top'&gt;&lt;img src='http://www.west-wind.com/banners/wwHelpBanner.Gif' border='0'&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=XCBN-wW6uZk:FN94dFoxp0E:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=XCBN-wW6uZk:FN94dFoxp0E:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=XCBN-wW6uZk:FN94dFoxp0E:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=XCBN-wW6uZk:FN94dFoxp0E:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=XCBN-wW6uZk:FN94dFoxp0E:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=XCBN-wW6uZk:FN94dFoxp0E:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=XCBN-wW6uZk:FN94dFoxp0E:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=XCBN-wW6uZk:FN94dFoxp0E:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=XCBN-wW6uZk:FN94dFoxp0E:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/RickStrahl/~4/XCBN-wW6uZk" height="1" width="1"/&gt;</description><author>Rick Strahls WebLog                                                                                 </author><pubDate>Mon, 21 Dec 2009 00:00:00 GMT</pubDate></item><item><title>SmtpClient and Locked File Attachments</title><link>http://feedproxy.google.com/~r/RickStrahl/~3/T0KcyIZAVv0/126745.aspx</link><description>&lt;p&gt;Got a note a couple of days ago from a client using one of my generic routines that wraps SmtpClient. Apparently whenever a file has been attached to a message and emailed with SmtpClient the file remains locked after the message has been sent. Oddly this particular issue hasnt cropped up before for me although these routines are in use in a number of applications Ive built.&lt;/p&gt;  &lt;p&gt;The wrapper I use was built mainly to backfit an old pre-.NET 2.0 email I built using Sockets to avoid the CDO nightmares of the .NET 1.x mail client. The current class retained the same class interface but now internally uses SmtpClient which holds a flat property interface that makes it less verbose to send off messages.&lt;/p&gt;  &lt;p&gt;File attachments in this interface are handled by providing a comma delimited list for files in an Attachments property which is then collected along with the other flat property settings and eventually passed on to SmtpClient.&lt;/p&gt;  &lt;p&gt;The jist of the code is something like this:&lt;/p&gt;  &lt;pre class="code"&gt;/// &amp;lt;summary&amp;gt;/// &lt;/span&gt;Fully self contained mail sending method. Sends an email message by connecting &lt;/span&gt;/// &lt;/span&gt;and disconnecting from the email server.&lt;/span&gt;/// &amp;lt;/summary&amp;gt;/// &amp;lt;returns&amp;gt;&lt;/span&gt;true or false&lt;/span&gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;public bool &lt;/span&gt;SendMail(){    if &lt;/span&gt;(!this&lt;/span&gt;.Connect())        return false&lt;/span&gt;;    &lt;strong&gt;try    &lt;/span&gt;{        &lt;/strong&gt;&lt;strong&gt;// Create and configure the message         &lt;/span&gt;MailMessage &lt;/span&gt;msg = this&lt;/span&gt;.GetMessage();        smtp.Send(msg);        this&lt;/span&gt;.OnSendComplete(this&lt;/span&gt;);    }&lt;/strong&gt;    catch &lt;/span&gt;(Exception &lt;/span&gt;ex)    {        string &lt;/span&gt;msg = ex.Message;        if &lt;/span&gt;(ex.InnerException != null&lt;/span&gt;)                            msg = ex.InnerException.Message;                this&lt;/span&gt;.SetError(msg);&lt;/pre&gt;&lt;pre class="code"&gt;        this&lt;/span&gt;.OnSendError(this&lt;/span&gt;);        return false&lt;/span&gt;;    }    finally    &lt;/span&gt;{        // close connection and clear out headers&lt;br /&gt;        // SmtpClient instance nulled out&lt;strong&gt;        &lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;this&lt;/span&gt;.Close();&lt;/strong&gt;    }        return true&lt;/span&gt;;}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre class="code"&gt;/// &amp;lt;summary&amp;gt;/// &lt;/span&gt;Configures the message interface&lt;/span&gt;/// &amp;lt;/summary&amp;gt;/// &amp;lt;param name=&amp;quot;msg&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;protected virtual &lt;/span&gt;MailMessage &lt;/span&gt;GetMessage(){    MailMessage &lt;/span&gt;msg = new &lt;/span&gt;MailMessage&lt;/span&gt;();                msg.Body = this&lt;/span&gt;.Message;    msg.Subject = this&lt;/span&gt;.Subject;    msg.From = new &lt;/span&gt;MailAddress&lt;/span&gt;(this&lt;/span&gt;.SenderEmail, this&lt;/span&gt;.SenderName);    if &lt;/span&gt;(!string&lt;/span&gt;.IsNullOrEmpty(this&lt;/span&gt;.ReplyTo))        msg.ReplyTo = new &lt;/span&gt;MailAddress&lt;/span&gt;(this&lt;/span&gt;.ReplyTo);    // Send all the different recipients    &lt;/span&gt;this&lt;/span&gt;.AssignMailAddresses(msg.To, this&lt;/span&gt;.Recipient);    this&lt;/span&gt;.AssignMailAddresses(msg.CC, this&lt;/span&gt;.CC);    this&lt;/span&gt;.AssignMailAddresses(msg.Bcc, this&lt;/span&gt;.BCC);&lt;strong&gt;    if &lt;/span&gt;(!string&lt;/span&gt;.IsNullOrEmpty(this&lt;/span&gt;.Attachments))    {        string&lt;/span&gt;[] files = this&lt;/span&gt;.Attachments.Split(new char&lt;/span&gt;[2] { ','&lt;/span&gt;, ';' &lt;/span&gt;}, StringSplitOptions&lt;/span&gt;.RemoveEmptyEntries);        foreach &lt;/span&gt;(string &lt;/span&gt;file in &lt;/span&gt;files)        {            msg.Attachments.Add(new &lt;/span&gt;Attachment&lt;/span&gt;(file));        }    }&lt;/strong&gt;    if &lt;/span&gt;(this&lt;/span&gt;.ContentType.StartsWith(&amp;quot;text/html&amp;quot;&lt;/span&gt;))        msg.IsBodyHtml = true&lt;/span&gt;;    else        &lt;/span&gt;msg.IsBodyHtml = false&lt;/span&gt;;    msg.BodyEncoding = this&lt;/span&gt;.Encoding;&lt;/pre&gt;&lt;pre class="code"&gt;     additional code  omitted&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre class="code"&gt;    return &lt;/span&gt;msg;&lt;/pre&gt;}&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;Basically this code collects all the property settings of the wrapper object and applies them to the SmtpClient and in GetMessage() to an individual message. Specifically notice that attachment filenames are converted from a comma-delimited string to filenames from which new attachments are created. &lt;/p&gt;&lt;p&gt;The code as its written however, will cause the problem with file attachments not being released properly. Internally .NET opens up stream handles and reads the files from disk to dump them into the email send stream. The attachments are always sent correctly but the local files are not immediately closed.&lt;/p&gt;&lt;p&gt;As you probably guessed the issue is simply that some resources are not properly being disposed and sure enough the following fixes the problem:&lt;/p&gt;&lt;pre class="code"&gt;// Create and configure the message &lt;/span&gt;&lt;strong&gt;using &lt;/span&gt;(MailMessage &lt;/span&gt;msg = this&lt;/span&gt;.GetMessage()){&lt;/strong&gt;    smtp.Send(msg);    if &lt;/span&gt;(this&lt;/span&gt;.SendComplete != null&lt;/span&gt;)        this&lt;/span&gt;.OnSendComplete(this&lt;/span&gt;);&lt;/pre&gt;&lt;pre class="code"&gt;    // or use an explicit msg.Dispose() here&lt;/span&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/pre&gt;&lt;p&gt;The Message object requires an explicit call to Dispose() (or a using() block as I have here) to force the attachment files to get closed. &lt;/p&gt;&lt;p&gt;I think this is rather odd behavior for this scenario however. The code I use passes in filenames and my expectation of an API that accepts file names is that it uses the files by opening and streaming them and then closes them when done. Why keep the streams open and require an explicit .Dispose() by the calling code which is bound to lead to unexpected behavior just as my customer ran into? Any API level code should clean up as much as possible and this is clearly not happening here.&lt;/p&gt;&lt;p&gt;Odd to me too is that SmtpClient() doesnt implement IDisposable  its only the Message (and Attachments) that implement it and require it to clean up for left over resources like open file handles. This means that you couldnt even use a using() statement around the SmtpClient code to resolve this  instead youd have to wrap it around the message object which is rather unexpected.&lt;/p&gt;&lt;p&gt;Well, chalk that one up to another small unexpected behavior that wasted a half an hour of my time  hopefully this post will help someone avoid this same half an hour of hunt and peck.&lt;/p&gt;&lt;h3&gt;Resources:&lt;/h3&gt;&lt;ul&gt;  &lt;li&gt;&lt;a href="http://www.west-wind.com:8080/svn/WestwindWebToolkit/trunk/Westwind.Utilities/Westwind.InternetTools/SmtpClientNative.cs" target="_blank"&gt;Full code to SmptClientNative (West Wind Web Toolkit Repository)&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.aspx" target="_blank"&gt;SmtpClient Documentation MSDN&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;small&gt; Rick Strahl, West Wind Technologies, 2005-2009&lt;/small&gt;&lt;a href='/Weblog/ShowPosts.aspx?Category=.NET'&gt;.NET&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f126745.aspx&amp;title=SmtpClient+and+Locked+File+Attachments"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f126745.aspx" border='0' alt='kick it on DotNetKicks.com' /&gt;&lt;/a&gt;&lt;/small&gt;&lt;p&gt;&lt;a href='http://west-wind.com/Weblog/wwBanner.ashx?a=c&amp;id=e47b9595&amp;t=633967760207410000' target='_top'&gt;&lt;img src='http://www.west-wind.com/banners/wwstore_small.gif' border='0'&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=T0KcyIZAVv0:adxya741CRM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=T0KcyIZAVv0:adxya741CRM:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=T0KcyIZAVv0:adxya741CRM:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=T0KcyIZAVv0:adxya741CRM:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=T0KcyIZAVv0:adxya741CRM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=T0KcyIZAVv0:adxya741CRM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=T0KcyIZAVv0:adxya741CRM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=T0KcyIZAVv0:adxya741CRM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=T0KcyIZAVv0:adxya741CRM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/RickStrahl/~4/T0KcyIZAVv0" height="1" width="1"/&gt;</description><author>Rick Strahls WebLog                                                                                 </author><pubDate>Fri, 18 Dec 2009 00:00:00 GMT</pubDate></item><item><title>Building Reports using ASP.NET and Crystal Reports - Part 7 Using Subreports to Create Advanced Reports</title><link>http://aspalliance.com/1907_Building_Reports_using_ASPNET_and_Crystal_Reports__Part_7_Using_Subreports_to_Create_Advanced_Reports</link><description>In this article, Vince examines the creation of a report that connects to two databases but displays the data on one report with he help of relevant screenshots and source code. Sub reports embed one report inside another while linking on a common field. They can be useful when you need to report data from more than one data source or when you need to run separate and distinct queries to retrieve data on a report.</description><author>ASPAlliance.com - The #1 ASP.NET Community                                                          </author><pubDate>Tue, 15 Dec 2009 00:00:00 GMT</pubDate></item><item><title>A free standing ASP.NET Pager Web Control</title><link>http://feedproxy.google.com/~r/RickStrahl/~3/bvGSMm_4Cz4/114621.aspx</link><description>&lt;p&gt;Paging in ASP.NET has been relatively easy with stock controls supporting basic paging functionality. However, recently I built an MVC application and one of the things I ran into was that I HAD TO build manual paging support into a few of my pages. Dealing with list controls and rendering markup is easy enough, but doing paging is a little more involved. I ended up with a small but flexible component that can be dropped anywhere. As it turns out the task of creating a semi-generic Pager control for MVC was fairly easily.&lt;/p&gt;  &lt;p&gt;Now Im back to working in Web Forms and thought to myself that the way I created the pager in MVC actually would also work in ASP.NET  in fact quite a bit easier since the whole thing can be conveniently wrapped up into an easily reusable control. A standalone pager would provider easier reuse in various pages and a more consistent pager display regardless of what kind of 'control the pager is associated with.&lt;/p&gt;  &lt;h3&gt;Why a Pager Control?&lt;/h3&gt;  &lt;p&gt;At first blush it might sound silly to create a new pager control  after all Web Forms has pretty decent paging support, doesnt it? Well, sort of. Yes the GridView control has automatic paging built in and the ListView control has the related DataPager control. &lt;/p&gt;  &lt;p&gt;The built in ASP.NET paging has several issues though:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Postback and JavaScript requirements&lt;/strong&gt;       &lt;br /&gt;If you look at paging links in ASP.NET they are always postback links with javascript:__doPostback() calls that go back to the server. While that works fine and actually has some benefit like the fact that paging saves changes to the page and post them back, its not very SEO friendly. Basically if you use javascript based navigation nosearch engine will follow the paging links which effectively cuts off list content on the first page. The &lt;em&gt;DataPager&lt;/em&gt; control&lt;em&gt; does&lt;/em&gt; support GET based links via the QueryStringParameter property, but the control is effectively tied to the ListView control (which is the only control that implements IPageableItemContainer).       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;DataSource Controls required for Efficient Data Paging Retrieval        &lt;br /&gt;&lt;/strong&gt;The only way you can get paging to work efficiently where only the few records you display on the page are queried for and retrieved from the database you have to use a DataSource control - only the Linq and Entity DataSource controls&amp;#160; support this natively. While you can retrieve this data yourself manually, theres no way to just assign the page number and render the pager based on this custom subset. Other than that default paging requires a full resultset for ASP.NET to filter the data and display only a subset which can be very resource intensive and wasteful if youre dealing with largish resultsets (although Im a firm believer in returning actually usable sets :-}). If you use your own business layer that doesnt fit an ObjectDataSource youre SOL. Thats a real shame too because with LINQ based querying its real easy to retrieve a subset of data that is just the data you want to display but the native Pager functionality doesnt support just setting properties to display just the subset AFAIK.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;DataPager is not Free Standing&lt;/strong&gt;       &lt;br /&gt;The DataPager control is the closest thing to a decent Pager implementation that ASP.NET has, but alas its not a free standing component  it works off a related control and the only one that it effectively supports from the stock ASP.NET controls is the ListView control. This means you cant use the same data pager formatting for a grid and a list view or vice versa and youre always tied to the control.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Paging Events        &lt;br /&gt;&lt;/strong&gt;In order to handle paging you have to deal with paging events. The events fire at specific time instances in the page pipeline and because of this you often have to handle data binding in a way to work around the paging events or else end up double binding your data sources based on paging. Yuk.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Styling&lt;/strong&gt;       &lt;br /&gt;The GridView pager is a royal pain to beat into submission for styled rendering. The DataPager control has many more options and template layout and it renders somewhat cleaner, but it too is not exactly easy to get a decent display for.       &lt;br /&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Not a Generic Solution        &lt;br /&gt;&lt;/strong&gt;The problem with the ASP.NET controls too is that its not generic. GridView, DataGrid use their own internal paging, ListView can use a DataPager and if you want to manually create data layout  well youre on your own. IOW, depending on what you use you likely have very different looking Paging experiences. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So, I figured Ive struggled with this once too many and finally sat down and built a Pager control.&lt;/p&gt;  &lt;h3&gt;The Pager Control&lt;/h3&gt;  &lt;p&gt;My goal was to create a totally free standing control that has no dependencies on other controls and certainly no requirements for using DataSource controls. The idea is that you should be able to use this pager control without any sort of data requirements at all  you should just be able to set properties and be able to display a pager.&lt;/p&gt;  &lt;p&gt;The Pager control I ended up with has the following features:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Completely free standing Pager control  no control or data dependencies &lt;/li&gt;    &lt;li&gt;Complete manual control  Pager can render without any data dependency &lt;/li&gt;    &lt;li&gt;Easy to use: Only need to set PageSize, ActivePage and TotalItems &lt;/li&gt;    &lt;li&gt;Supports optional filtering of IQueryable for efficient queries and Pager rendering &lt;/li&gt;    &lt;li&gt;Supports optional full set filtering of IEnumerable&amp;lt;T&amp;gt; and DataTable &lt;/li&gt;    &lt;li&gt;Page links are plain HTTP GET href Links &lt;/li&gt;    &lt;li&gt;Control automatically picks up Page links on the URL and assigns them      &lt;br /&gt;(automatic page detection no page index changing events to hookup) &lt;/li&gt;    &lt;li&gt;Full CSS Styling support &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;On the downside theres no templating support for the control so the layout of the pager is relatively fixed. All elements however are stylable and there are options to control the text, and layout options such as whether to display first and last pages and the previous/next buttons and so on. &lt;/p&gt;  &lt;p&gt;To give you an idea what the pager looks like, here are two differently styled examples (all via CSS):&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Pagers[4]" border="0" alt="Pagers[4]" src="http://www.west-wind.com/Weblog/images/200901/WindowsLiveWriter/AfreestandingASP.NETPagerWebControl_DE0/Pagers%5B4%5D_530095a4-583f-489c-ba4e-af39904d0b31.png" width="670" height="237" /&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;The markup for these two pagers looks like this:&lt;/p&gt;  &lt;pre class="code"&gt;&amp;lt;&lt;/span&gt;ww&lt;/span&gt;:&lt;/span&gt;Pager &lt;/span&gt;runat&lt;/span&gt;=&amp;quot;server&amp;quot; &lt;/span&gt;id&lt;/span&gt;=&amp;quot;ItemPager&amp;quot;           &lt;/span&gt;PageSize&lt;/span&gt;=&amp;quot;5&amp;quot;           &lt;/span&gt;PageLinkCssClass&lt;/span&gt;=&amp;quot;gridpagerbutton&amp;quot;           &lt;/span&gt;SelectedPageCssClass&lt;/span&gt;=&amp;quot;gridpagerbutton-selected&amp;quot;          &lt;/span&gt;PagesTextCssClass&lt;/span&gt;=&amp;quot;gridpagertext&amp;quot;          &lt;/span&gt;CssClass&lt;/span&gt;=&amp;quot;gridpager&amp;quot;           &lt;/span&gt;RenderContainerDiv&lt;/span&gt;=&amp;quot;true&amp;quot;          &lt;/span&gt;ContainerDivCssClass&lt;/span&gt;=&amp;quot;gridpagercontainer&amp;quot;          &lt;/span&gt;MaxPagesToDisplay&lt;/span&gt;=&amp;quot;6&amp;quot;           &lt;/span&gt;PagesText&lt;/span&gt;=&amp;quot;Item Pages:&amp;quot;           &lt;/span&gt;NextText&lt;/span&gt;=&amp;quot;next&amp;quot;          &lt;/span&gt;PreviousText&lt;/span&gt;=&amp;quot;previous&amp;quot;          /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre class="code"&gt;&amp;lt;&lt;/span&gt;ww&lt;/span&gt;:&lt;/span&gt;Pager &lt;/span&gt;runat&lt;/span&gt;=&amp;quot;server&amp;quot; &lt;/span&gt;id&lt;/span&gt;=&amp;quot;ItemPager2&amp;quot;           &lt;/span&gt;PageSize&lt;/span&gt;=&amp;quot;5&amp;quot; &lt;/span&gt;          &lt;/span&gt;RenderContainerDiv&lt;/span&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;          &lt;/span&gt;MaxPagesToDisplay&lt;/span&gt;=&amp;quot;6&amp;quot; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;The latter example uses default style settings so it theres not much to set. The first example on the other hand explicitly assigns custom styles and overrides a few of the formatting options. &lt;/p&gt;&lt;h3&gt;Styling&lt;/h3&gt;&lt;p&gt;The styling is based on a number of CSS classes of which the the main pager, pagerbutton and pagerbutton-selected classes are the important ones. Other styles like pagerbutton-next/prev/first/last are based on the pagerbutton style.&lt;/p&gt;&lt;p&gt;The default styling shown for the red outlined pager looks like this:&lt;/p&gt;&lt;pre class="code"&gt;.pagercontainer&lt;/span&gt;{    margin&lt;/span&gt;: 20px 0&lt;/span&gt;;    background&lt;/span&gt;: whitesmoke&lt;/span&gt;;        padding&lt;/span&gt;: 5px&lt;/span&gt;;    }.pager&lt;/span&gt;{    float&lt;/span&gt;: right&lt;/span&gt;;    font-size&lt;/span&gt;: 10pt&lt;/span&gt;;    text-align&lt;/span&gt;: left&lt;/span&gt;;}.pagerbutton&lt;/span&gt;,.pagerbutton-selected&lt;/span&gt;,.pagertext&lt;/span&gt;{    display&lt;/span&gt;: block&lt;/span&gt;;            float&lt;/span&gt;: left&lt;/span&gt;;        text-align&lt;/span&gt;: center&lt;/span&gt;;    border&lt;/span&gt;: solid 2px maroon&lt;/span&gt;;            min-width&lt;/span&gt;: 18px&lt;/span&gt;;          margin-left&lt;/span&gt;: 3px&lt;/span&gt;;        text-decoration&lt;/span&gt;: none&lt;/span&gt;;            padding&lt;/span&gt;: 4px&lt;/span&gt;;}.pagerbutton-selected&lt;/span&gt;{    font-size&lt;/span&gt;: 130%&lt;/span&gt;;    font-weight&lt;/span&gt;: bold&lt;/span&gt;;            color&lt;/span&gt;: maroon&lt;/span&gt;;    border-width&lt;/span&gt;: 0px&lt;/span&gt;;    background&lt;/span&gt;: khaki&lt;/span&gt;;}.pagerbutton-first&lt;/span&gt;{    margin-right&lt;/span&gt;: 12px&lt;/span&gt;;        }.pagerbutton-last&lt;/span&gt;,.pagerbutton-prev&lt;/span&gt;{    margin-left&lt;/span&gt;: 12px&lt;/span&gt;;        }.pagertext&lt;/span&gt;{    border&lt;/span&gt;: none&lt;/span&gt;;    margin-left&lt;/span&gt;: 30px&lt;/span&gt;;    font-weight&lt;/span&gt;: bold&lt;/span&gt;;}.pagerbutton a&lt;/span&gt;{    text-decoration&lt;/span&gt;: none&lt;/span&gt;;}.pagerbutton:hover&lt;/span&gt;{    background-color&lt;/span&gt;: maroon&lt;/span&gt;;    color&lt;/span&gt;: cornsilk&lt;/span&gt;;}.pagerbutton-prev&lt;/span&gt;{    background-image&lt;/span&gt;: url(images/prev.png)&lt;/span&gt;;    background-position&lt;/span&gt;: 2px center&lt;/span&gt;;    background-repeat&lt;/span&gt;: no-repeat&lt;/span&gt;;    width&lt;/span&gt;: 35px&lt;/span&gt;;    padding-left&lt;/span&gt;: 20px&lt;/span&gt;;}.pagerbutton-next&lt;/span&gt;{    background-image&lt;/span&gt;: url(images/next.png)&lt;/span&gt;;    background-position&lt;/span&gt;: 40px center&lt;/span&gt;;    background-repeat&lt;/span&gt;: no-repeat&lt;/span&gt;;    width&lt;/span&gt;: 35px&lt;/span&gt;;    padding-right&lt;/span&gt;: 20px&lt;/span&gt;;    margin-right&lt;/span&gt;: 0px&lt;/span&gt;;}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;Yup thats a lot of styling settings although not all of them are required. The key ones are pagerbutton, pager and pager selection. The others (which are implicitly created by the control based on the pagerbutton style) are for custom markup of the special buttons.&lt;/p&gt;&lt;p&gt;In my apps I tend to have two kinds of pages: Those that are associated with typical grid displays that display purely tabular data and those that have a more looser list like layout. The two pagers shown above represent these two views and the pager and gridpager styles in my &lt;a href="http://www.west-wind.com:8080/svn/WestwindWebToolkit/trunk/WestwindWebToolkitWeb/Css/Westwind.css" target="_blank"&gt;standard style sheet&lt;/a&gt; reflect these two styles.&lt;/p&gt;&lt;h3&gt;&lt;/h3&gt;&lt;h3&gt;Configuring the Pager with Code&lt;/h3&gt;&lt;p&gt;Finally lets look at what it takes to hook up the pager. As mentioned in the highlights the Pager control is completely independent of other controls so if you just want to display a pager on its own its as simple as dropping the control and assigning the PageSize, ActivePage and either TotalPages or TotalItems.&lt;/p&gt;&lt;p&gt;So for this markup:&lt;/p&gt;&lt;pre class="code"&gt;&amp;lt;&lt;/span&gt;ww&lt;/span&gt;:&lt;/span&gt;Pager &lt;/span&gt;runat&lt;/span&gt;=&amp;quot;server&amp;quot; &lt;/span&gt;id&lt;/span&gt;=&amp;quot;ItemPagerManual&amp;quot;           &lt;/span&gt;PageSize&lt;/span&gt;=&amp;quot;5&amp;quot;           &lt;/span&gt;MaxPagesToDisplay&lt;/span&gt;=&amp;quot;6&amp;quot; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;I can use code as simple as:&lt;/p&gt;&lt;pre class="code"&gt;ItemPagerManual.PageSize = &lt;font color="#a52a2a"&gt;3&lt;/font&gt;;ItemPagerManual.ActivePage = 4;&lt;br /&gt;ItemPagerManual.TotalItems = 20;            &lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;Note that ActivePage is not required - it will automatically use any Page=x query string value and assign it, although you can override it as I did above. TotalItems can be any value that you retrieve from a result set or manually assign as I did above.&lt;/p&gt;&lt;p&gt;A more realistic scenario based on a LINQ to SQL IQueryable result is even easier. In this example, I have a UserControl that contains a ListView control that renders IQueryable data. I use a User Control here because there are different views the user can choose from with each view being a different user control. This incidentally also highlights one of the nice features of the pager: Because the pager is independent of the control I can put the pager on the host page instead of into each of the user controls. IOW, theres only one Pager control, but there are potentially many user controls/listviews that hold the actual display data.&lt;/p&gt;&lt;p&gt;The following code demonstrates how to use the Pager with an IQueryable that loads only the records it displays: &lt;font face="Courier New"&gt;protected void&lt;/span&gt;Page_Load(object&lt;/span&gt;sender, EventArgs &lt;/span&gt;e)     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Category = Request.Params[&amp;quot;Category&amp;quot;&lt;/span&gt;] ?? string&lt;/span&gt;.Empty;     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; IQueryable&lt;/span&gt;&amp;lt;wws_Item&lt;/span&gt;&amp;gt; ItemList = ItemRepository.GetItemsByCategory(Category);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/font&gt;&lt;font face="Courier New"&gt;// Update the page and filter the list down       &lt;br /&gt;&lt;/font&gt;&lt;/span&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;&amp;#160;&amp;#160;&amp;#160; ItemList = ItemPager.FilterIQueryable&amp;lt;wws_Item&lt;/span&gt;&amp;gt;(ItemList);       &lt;br /&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;pre class="code"&gt;    // Render user control with a list view &lt;/span&gt;    &lt;br /&gt;&lt;br /&gt;    Control &lt;/span&gt;ulItemList = LoadControl(&amp;quot;~/usercontrols/&amp;quot; + App.Configuration.ItemListType + &amp;quot;.ascx&amp;quot;&lt;/span&gt;);&lt;strong&gt;    ((IInventoryItemListControl&lt;/span&gt;)ulItemList).InventoryItemList = ItemList;&lt;/strong&gt;    phItemList.Controls.Add(ulItemList);  // placeholder    }&lt;/pre&gt;&lt;p&gt;The code uses a business object to retrieve Items by category as an IQueryable which means that the result is only an expression tree that hasnt execute SQL yet and can be further filtered. I then pass this IQueryable to the FilterIQueryable() helper method of the control which does two main things:&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;Filters the IQueryable to retrieve &lt;strong&gt;only the data displayed&lt;/strong&gt; on the active page &lt;/li&gt;  &lt;li&gt;Sets the Totaltems property and calculates TotalPages on the Pager &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;and thats it! When the Pager renders it uses those values, plus the PageSize and ActivePage properties to render the Pager.&lt;/p&gt;&lt;p&gt;In addition to IQueryable there are also filter methods for IEnumerable&amp;lt;T&amp;gt; and DataTable, but these versions just filter the data by removing rows/items from the entire already retrieved data.&lt;/p&gt;&lt;h3&gt;Output Generated and Paging Links&lt;/h3&gt;&lt;p&gt;The output generated creates pager links as plain href links. Heres what the output looks like:&lt;/p&gt;&lt;pre class="code"&gt;&amp;lt;&lt;/span&gt;div &lt;/span&gt;id&lt;/span&gt;=&amp;quot;ItemPager&amp;quot; &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pagercontainer&amp;quot;&amp;gt;    &amp;lt;&lt;/span&gt;div &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pager&amp;quot;&amp;gt;        &amp;lt;&lt;/span&gt;span &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pagertext&amp;quot;&amp;gt;&lt;/span&gt;Pages: &amp;lt;/&lt;/span&gt;span&lt;/span&gt;&amp;gt;&amp;lt;&lt;/span&gt;a &lt;/span&gt;href&lt;/span&gt;=&amp;quot;http://localhost/WestWindWebStore/itemlist.aspx?Page=1&amp;quot; &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pagerbutton&amp;quot; /&amp;gt;&lt;/span&gt;1&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&amp;gt;        &amp;lt;&lt;/span&gt;a &lt;/span&gt;href&lt;/span&gt;=&amp;quot;http://localhost/WestWindWebStore/itemlist.aspx?Page=2&amp;quot; &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pagerbutton&amp;quot; /&amp;gt;&lt;/span&gt;2&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&amp;gt;        &amp;lt;&lt;/span&gt;a &lt;/span&gt;href&lt;/span&gt;=&amp;quot;http://localhost/WestWindWebStore/itemlist.aspx?Page=3&amp;quot; &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pagerbutton&amp;quot; /&amp;gt;&lt;/span&gt;3&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&amp;gt;        &amp;lt;&lt;/span&gt;span &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pagerbutton-selected&amp;quot;&amp;gt;&lt;/span&gt;4&amp;lt;/&lt;/span&gt;span&lt;/span&gt;&amp;gt;        &amp;lt;&lt;/span&gt;a &lt;/span&gt;href&lt;/span&gt;=&amp;quot;http://localhost/WestWindWebStore/itemlist.aspx?Page=5&amp;quot; &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pagerbutton&amp;quot; /&amp;gt;&lt;/span&gt;5&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&amp;gt;        &amp;lt;&lt;/span&gt;a &lt;/span&gt;href&lt;/span&gt;=&amp;quot;http://localhost/WestWindWebStore/itemlist.aspx?Page=6&amp;quot; &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pagerbutton&amp;quot; /&amp;gt;&lt;/span&gt;6&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&amp;gt;        &amp;lt;&lt;/span&gt;a &lt;/span&gt;href&lt;/span&gt;=&amp;quot;http://localhost/WestWindWebStore/itemlist.aspx?Page=20&amp;quot; &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pagerbutton pagerbutton-last&amp;quot; /&amp;gt;&lt;/span&gt;20&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;&lt;/span&gt;a &lt;/span&gt;href&lt;/span&gt;=&amp;quot;http://localhost/WestWindWebStore/itemlist.aspx?Page=3&amp;quot; &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pagerbutton pagerbutton-prev&amp;quot; /&amp;gt;&lt;/span&gt;Prev&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&amp;gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt;&lt;/span&gt;a &lt;/span&gt;href&lt;/span&gt;=&amp;quot;http://localhost/WestWindWebStore/itemlist.aspx?Page=5&amp;quot; &lt;/span&gt;class&lt;/span&gt;=&amp;quot;pagerbutton pagerbutton-next&amp;quot; /&amp;gt;&lt;/span&gt;Next&amp;lt;/&lt;/span&gt;a&lt;/span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&amp;gt;        &amp;lt;&lt;/span&gt;br &lt;/span&gt;clear&lt;/span&gt;=&amp;quot;all&amp;quot; /&amp;gt;    &amp;lt;/&lt;/span&gt;div&lt;/span&gt;&amp;gt;&amp;lt;/&lt;/span&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;The links point back to the current page and simply append a Page= page link into the page. When the page gets reloaded with the new page number the pager automatically detects the page number and automatically assigns the ActivePage property which results in the appropriate page to be displayed. The code shown in the previous section is all thats needed to handle paging.&lt;/p&gt;&lt;p&gt;Note that HTTP GET based paging is different than the Postback paging ASP.NET uses by default. Postback paging preserves modified page content when clicking on pager buttons, but this control will simply load a new page  no page preservation at this time.&lt;/p&gt;&lt;p&gt;The advantage of not using Postback paging is that the URLs generated are plain HTML links that a search engine can follow where __doPostback() links are not. &lt;/p&gt;&lt;h3&gt;Pager with a Grid&lt;/h3&gt;&lt;p&gt;The pager also works in combination with grid controls so its easy to bypass the grid controls paging features if desired. In the following example I use a gridView control and binds it to a DataTable result which is also filterable by the Pager control.&lt;/p&gt;&lt;p&gt;The very basic plain vanilla ASP.NET grid markup looks like this:&lt;/p&gt;&lt;pre class="code"&gt;   &amp;lt;&lt;/span&gt;div &lt;/span&gt;style&lt;/span&gt;=&amp;quot;&lt;/span&gt;width&lt;/span&gt;: 600px; &lt;/span&gt;margin&lt;/span&gt;: 0 auto;&lt;/span&gt;padding&lt;/span&gt;: 20px; &amp;quot;&amp;gt;        &amp;lt;&lt;/span&gt;asp&lt;/span&gt;:&lt;/span&gt;DataGrid &lt;/span&gt;runat&lt;/span&gt;=&amp;quot;server&amp;quot; &lt;/span&gt;AutoGenerateColumns&lt;/span&gt;=&amp;quot;True&amp;quot;                       &lt;/span&gt;ID&lt;/span&gt;=&amp;quot;gdItems&amp;quot; &lt;/span&gt;CssClass&lt;/span&gt;=&amp;quot;blackborder&amp;quot; &lt;/span&gt;style&lt;/span&gt;=&amp;quot;&lt;/span&gt;width&lt;/span&gt;: 600px;&amp;quot;&amp;gt;        &amp;lt;&lt;/span&gt;AlternatingItemStyle &lt;/span&gt;CssClass&lt;/span&gt;=&amp;quot;gridalternate&amp;quot; /&amp;gt;         &amp;lt;&lt;/span&gt;HeaderStyle &lt;/span&gt;CssClass&lt;/span&gt;=&amp;quot;gridheader&amp;quot; /&amp;gt;        &amp;lt;/&lt;/span&gt;asp&lt;/span&gt;:&lt;/span&gt;DataGrid&lt;/span&gt;&amp;gt;                &amp;lt;&lt;/span&gt;ww&lt;/span&gt;:&lt;/span&gt;Pager &lt;/span&gt;runat&lt;/span&gt;=&amp;quot;server&amp;quot; &lt;/span&gt;ID&lt;/span&gt;=&amp;quot;Pager&amp;quot;               &lt;/span&gt;CssClass&lt;/span&gt;=&amp;quot;gridpager&amp;quot;              &lt;/span&gt;ContainerDivCssClass&lt;/span&gt;=&amp;quot;gridpagercontainer&amp;quot;              &lt;/span&gt;PageLinkCssClass&lt;/span&gt;=&amp;quot;gridpagerbutton&amp;quot;              &lt;/span&gt;SelectedPageCssClass&lt;/span&gt;=&amp;quot;gridpagerbutton-selected&amp;quot;              &lt;/span&gt;PageSize&lt;/span&gt;=&amp;quot;8&amp;quot;               &lt;/span&gt;RenderContainerDiv&lt;/span&gt;=&amp;quot;true&amp;quot;              &lt;/span&gt;MaxPagesToDisplay&lt;/span&gt;=&amp;quot;6&amp;quot;  /&amp;gt;        &amp;lt;/&lt;/span&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;and looks like this when rendered:  &lt;br /&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="GridPager" border="0" alt="GridPager" src="http://www.west-wind.com/Weblog/images/200901/WindowsLiveWriter/AfreestandingASP.NETPagerWebControl_DE0/GridPager_e22a298a-947c-4103-94cc-78212cf5b686.png" width="706" height="375" /&gt;  &lt;br /&gt;using custom set of CSS styles. The code behind for this code is also very simple:&lt;/p&gt;&lt;pre class="code"&gt;protected void &lt;/span&gt;Page_Load(object &lt;/span&gt;sender, EventArgs &lt;/span&gt;e){    string &lt;/span&gt;category = Request.Params[&amp;quot;category&amp;quot;&lt;/span&gt;] ?? &amp;quot;&amp;quot;&lt;/span&gt;;    busItem &lt;/span&gt;itemRep = WebStoreFactory&lt;/span&gt;.GetItem();    var &lt;/span&gt;items = itemRep.GetItemsByCategory(category)                       .Select(itm =&amp;gt; new &lt;/span&gt;{Sku = itm.Sku, Description = itm.Description});               // run query into a DataTable for demonstration    &lt;/span&gt;DataTable &lt;/span&gt;dt = itemRep.Converter.ToDataTable(items,&amp;quot;TItems&amp;quot;&lt;/span&gt;);    // Remove all items not on the current page    &lt;/span&gt;dt = Pager.FilterDataTable(dt,0&lt;/span&gt;);        // bind and display    &lt;/span&gt;gdItems.DataSource = dt;    gdItems.DataBind();}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;A little contrived I suppose since the list could already be bound from the list of elements, but this is to demonstrate that you can also bind against DataTable if your business layer returns those. &lt;/p&gt;&lt;p&gt;Unfortunately theres no way to filter a DataReader as its a one way forward only reader and the reader is required by the DataSource to perform the bindings.&amp;#160; However, you can still use a DataReader as long as your business logic filters the data prior to rendering and provides a total item count (most likely as a second query).&lt;/p&gt;&lt;h3&gt;Control Creation&lt;/h3&gt;&lt;p&gt;The control itself is a pretty brute force ASP.NET control. Nothing clever about this other than some basic rendering logic and some simple calculations and update routines to determine which buttons need to be shown. You can take a look at the full code from the &lt;a href="http://www.west-wind.com:8080/svn/WestwindWebToolkit/trunk/Westwind.Web/Extended/Pager.cs" target="_blank"&gt;West Wind Web Toolkits Repository&lt;/a&gt; (note there are a few dependencies).&lt;/p&gt;&lt;p&gt;To give you an idea how the control works here is the Render() method:&lt;/p&gt;&lt;pre class="code"&gt;/// &amp;lt;summary&amp;gt;/// &lt;/span&gt;overridden to handle custom pager rendering for runtime and design time&lt;/span&gt;/// &amp;lt;/summary&amp;gt;/// &amp;lt;param name=&amp;quot;writer&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;&lt;/span&gt;protected override void &lt;/span&gt;Render(HtmlTextWriter &lt;/span&gt;writer){    base&lt;/span&gt;.Render(writer);    if &lt;/span&gt;(TotalPages == 0 &lt;/span&gt;&amp;&amp; TotalItems &amp;gt; 0&lt;/span&gt;)                                   TotalPages = CalculateTotalPagesFromTotalItems();      &lt;/span&gt;if &lt;/span&gt;(DesignMode)        TotalPages = 10&lt;/span&gt;;    // don't render pager if there's only one page    &lt;/span&gt;if &lt;/span&gt;(TotalPages &amp;lt; 2&lt;/span&gt;)        return&lt;/span&gt;;    if &lt;/span&gt;(RenderContainerDiv)    {        if &lt;/span&gt;(!string&lt;/span&gt;.IsNullOrEmpty(ContainerDivCssClass))            writer.AddAttribute(&amp;quot;class&amp;quot;&lt;/span&gt;, ContainerDivCssClass);        writer.RenderBeginTag(&amp;quot;div&amp;quot;&lt;/span&gt;);    }    // main pager wrapper    &lt;/span&gt;writer.WriteBeginTag(&amp;quot;div&amp;quot;&lt;/span&gt;);    writer.AddAttribute(&amp;quot;id&amp;quot;&lt;/span&gt;, this&lt;/span&gt;.ClientID);    if &lt;/span&gt;(!string&lt;/span&gt;.IsNullOrEmpty(CssClass))        writer.WriteAttribute(&amp;quot;class&amp;quot;&lt;/span&gt;, this&lt;/span&gt;.CssClass);    writer.Write(HtmlTextWriter&lt;/span&gt;.TagRightChar + &amp;quot;\r\n&amp;quot;&lt;/span&gt;);    // Pages Text    &lt;/span&gt;writer.WriteBeginTag(&amp;quot;span&amp;quot;&lt;/span&gt;);    if &lt;/span&gt;(!string&lt;/span&gt;.IsNullOrEmpty(PagesTextCssClass))        writer.WriteAttribute(&amp;quot;class&amp;quot;&lt;/span&gt;, PagesTextCssClass);    writer.Write(HtmlTextWriter&lt;/span&gt;.TagRightChar);    writer.Write(this&lt;/span&gt;.PagesText);    writer.WriteEndTag(&amp;quot;span&amp;quot;&lt;/span&gt;);    // if the base url is empty use the current URL    &lt;/span&gt;FixupBaseUrl();            // set _startPage and _endPage    &lt;/span&gt;ConfigurePagesToRender();    // write out first page link    &lt;/span&gt;if &lt;/span&gt;(ShowFirstAndLastPageLinks &amp;&amp; _startPage != 1&lt;/span&gt;)    {        writer.WriteBeginTag(&amp;quot;a&amp;quot;&lt;/span&gt;);        string &lt;/span&gt;pageUrl = StringUtils&lt;/span&gt;.SetUrlEncodedKey(BaseUrl, QueryStringPageField, (1&lt;/span&gt;).ToString());        writer.WriteAttribute(&amp;quot;href&amp;quot;&lt;/span&gt;, pageUrl);        if &lt;/span&gt;(!string&lt;/span&gt;.IsNullOrEmpty(PageLinkCssClass))            writer.WriteAttribute(&amp;quot;class&amp;quot;&lt;/span&gt;, PageLinkCssClass + &amp;quot; &amp;quot; &lt;/span&gt;+ PageLinkCssClass + &amp;quot;-first&amp;quot;&lt;/span&gt;);        writer.Write(HtmlTextWriter&lt;/span&gt;.SelfClosingTagEnd);        writer.Write(&amp;quot;1&amp;quot;&lt;/span&gt;);        writer.WriteEndTag(&amp;quot;a&amp;quot;&lt;/span&gt;);        writer.Write(&amp;quot;&amp;nbsp;&amp;quot;&lt;/span&gt;);    }    // write out all the page links    &lt;/span&gt;for &lt;/span&gt;(int &lt;/span&gt;i = _startPage; i &amp;lt; _endPage + 1&lt;/span&gt;; i++)    {        if &lt;/span&gt;(i == ActivePage)        {            writer.WriteBeginTag(&amp;quot;span&amp;quot;&lt;/span&gt;);            if &lt;/span&gt;(!string&lt;/span&gt;.IsNullOrEmpty(SelectedPageCssClass))                writer.WriteAttribute(&amp;quot;class&amp;quot;&lt;/span&gt;, SelectedPageCssClass);            writer.Write(HtmlTextWriter&lt;/span&gt;.TagRightChar);            writer.Write(i.ToString());            writer.WriteEndTag(&amp;quot;span&amp;quot;&lt;/span&gt;);        }        else        &lt;/span&gt;{            writer.WriteBeginTag(&amp;quot;a&amp;quot;&lt;/span&gt;);            string &lt;/span&gt;pageUrl = StringUtils&lt;/span&gt;.SetUrlEncodedKey(BaseUrl, QueryStringPageField, i.ToString()).TrimEnd('&amp;'&lt;/span&gt;);            writer.WriteAttribute(&amp;quot;href&amp;quot;&lt;/span&gt;, pageUrl);            if &lt;/span&gt;(!string&lt;/span&gt;.IsNullOrEmpty(PageLinkCssClass))                writer.WriteAttribute(&amp;quot;class&amp;quot;&lt;/span&gt;, PageLinkCssClass);            writer.Write(HtmlTextWriter&lt;/span&gt;.SelfClosingTagEnd);            writer.Write(i.ToString());            writer.WriteEndTag(&amp;quot;a&amp;quot;&lt;/span&gt;);        }        writer.Write(&amp;quot;\r\n&amp;quot;&lt;/span&gt;);    }    // write out last page link    &lt;/span&gt;if &lt;/span&gt;(ShowFirstAndLastPageLinks &amp;&amp; _endPage &amp;lt; TotalPages)    {        writer.WriteBeginTag(&amp;quot;a&amp;quot;&lt;/span&gt;);        string &lt;/span&gt;pageUrl = StringUtils&lt;/span&gt;.SetUrlEncodedKey(BaseUrl, QueryStringPageField, TotalPages.ToString());        writer.WriteAttribute(&amp;quot;href&amp;quot;&lt;/span&gt;, pageUrl);        if &lt;/span&gt;(!string&lt;/span&gt;.IsNullOrEmpty(PageLinkCssClass))            writer.WriteAttribute(&amp;quot;class&amp;quot;&lt;/span&gt;, PageLinkCssClass + &amp;quot; &amp;quot; &lt;/span&gt;+ PageLinkCssClass + &amp;quot;-last&amp;quot;&lt;/span&gt;);        writer.Write(HtmlTextWriter&lt;/span&gt;.SelfClosingTagEnd);        writer.Write(TotalPages.ToString());        writer.WriteEndTag(&amp;quot;a&amp;quot;&lt;/span&gt;);    }    // Previous link    &lt;/span&gt;if &lt;/span&gt;(ShowPreviousNextLinks &amp;&amp; !string&lt;/span&gt;.IsNullOrEmpty(PreviousText) &amp;&amp; ActivePage &amp;gt; 1&lt;/span&gt;)    {        writer.Write(&amp;quot;&amp;nbsp;&amp;quot;&lt;/span&gt;);        writer.WriteBeginTag(&amp;quot;a&amp;quot;&lt;/span&gt;);        string &lt;/span&gt;pageUrl = StringUtils&lt;/span&gt;.SetUrlEncodedKey(BaseUrl, QueryStringPageField, (ActivePage - 1&lt;/span&gt;).ToString());        writer.WriteAttribute(&amp;quot;href&amp;quot;&lt;/span&gt;, pageUrl);        if &lt;/span&gt;(!string&lt;/span&gt;.IsNullOrEmpty(PageLinkCssClass))            writer.WriteAttribute(&amp;quot;class&amp;quot;&lt;/span&gt;, PageLinkCssClass + &amp;quot; &amp;quot; &lt;/span&gt;+ PageLinkCssClass + &amp;quot;-prev&amp;quot;&lt;/span&gt;);        writer.Write(HtmlTextWriter&lt;/span&gt;.SelfClosingTagEnd);        writer.Write(PreviousText);        writer.WriteEndTag(&amp;quot;a&amp;quot;&lt;/span&gt;);    }    // Next link    &lt;/span&gt;if &lt;/span&gt;(ShowPreviousNextLinks &amp;&amp; !string&lt;/span&gt;.IsNullOrEmpty(NextText) &amp;&amp; ActivePage &amp;lt; TotalPages)    {        writer.Write(&amp;quot;&amp;nbsp;&amp;quot;&lt;/span&gt;);        writer.WriteBeginTag(&amp;quot;a&amp;quot;&lt;/span&gt;);        string &lt;/span&gt;pageUrl = StringUtils&lt;/span&gt;.SetUrlEncodedKey(BaseUrl, QueryStringPageField, (ActivePage + 1&lt;/span&gt;).ToString());        writer.WriteAttribute(&amp;quot;href&amp;quot;&lt;/span&gt;, pageUrl);        if &lt;/span&gt;(!string&lt;/span&gt;.IsNullOrEmpty(PageLinkCssClass))            writer.WriteAttribute(&amp;quot;class&amp;quot;&lt;/span&gt;, PageLinkCssClass + &amp;quot; &amp;quot; &lt;/span&gt;+ PageLinkCssClass + &amp;quot;-next&amp;quot;&lt;/span&gt;);        writer.Write(HtmlTextWriter&lt;/span&gt;.SelfClosingTagEnd);        writer.Write(NextText);        writer.WriteEndTag(&amp;quot;a&amp;quot;&lt;/span&gt;);    }    writer.WriteEndTag(&amp;quot;div&amp;quot;&lt;/span&gt;);    if &lt;/span&gt;(RenderContainerDiv)    {        if &lt;/span&gt;(RenderContainerDivBreak)&lt;br /&gt;            writer.Write(&amp;quot;&amp;lt;br clear=\&amp;quot;all\&amp;quot; /&amp;gt;\r\n&amp;quot;&lt;/span&gt;);        writer.WriteEndTag(&amp;quot;div&amp;quot;&lt;/span&gt;);    }}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;p&gt;As I said pretty much brute force rendering based on the controls property settings of which there are quite a few:&lt;/p&gt;&lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="PagerVisualStudio" border="0" alt="PagerVisualStudio" src="http://www.west-wind.com/Weblog/images/200901/WindowsLiveWriter/AfreestandingASP.NETPagerWebControl_DE0/PagerVisualStudio_442a296b-9804-4624-a188-53a6efe3a419.png" width="800" height="599" /&gt; &lt;/p&gt;&lt;p&gt;You can also see the pager in the designer above. unfortunately the VS designer (both 2010 and 2008) fails to render the float: left CSS styles properly and starts wrapping after margins are applied in the special buttons. Not a big deal since VS does at least respect the spacing (the floated elements overlay). Then again Im not using the designer anyway :-}.&lt;/p&gt;&lt;h3&gt;Filtering Data&lt;/h3&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;What makes the Pager easy to use is the filter methods built into the control. While this functionality is clearly not the most politically correct design choice as it violates separation of concerns, its very useful for typical pager operation. While I actually have filter methods that do something similar in my business layer, having it exposed on the control makes the control a lot more useful for typical databinding scenarios. Of course these methods are optional  if you have a business layer that can provide filtered page queries for you can use that instead and assign the TotalItems property manually.&lt;/p&gt;&lt;p&gt;There are three filter method types available for IQueryable, IEnumerable and for DataTable which tend to be the most common use cases in my apps old and new. The IQueryable version is pretty simple as it can simply rely on on .Skip() and .Take() with LINQ:&lt;/p&gt;&lt;pre class="code"&gt; /// &amp;lt;summary&amp;gt; /// &amp;lt;summary&amp;gt; /// &lt;/span&gt;Queries the database for the ActivePage applied manually &lt;/span&gt;/// &lt;/span&gt;or from the Request[&amp;quot;page&amp;quot;] variable. This routine &lt;/span&gt;/// &lt;/span&gt;figures out and sets TotalPages, ActivePage and &lt;/span&gt;/// &lt;/span&gt;returns a filtered subset IQueryable that contains &lt;/span&gt;/// &lt;/span&gt;only the items from the ActivePage. &lt;/span&gt;/// &amp;lt;/summary&amp;gt; /// &amp;lt;param name=&amp;quot;query&amp;quot;&amp;gt;&amp;lt;/param&amp;gt; /// &amp;lt;param name=&amp;quot;activePage&amp;quot;&amp;gt; /// &lt;/span&gt;The page you want to display. Sets the ActivePage property when passed.  &lt;/span&gt;/// &lt;/span&gt;Pass 0 or smaller to use ActivePage setting. &lt;/span&gt;/// &amp;lt;/param&amp;gt; /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt; &lt;/span&gt;public &lt;/span&gt;IQueryable&lt;/span&gt;&amp;lt;T&amp;gt; FilterIQueryable&amp;lt;T&amp;gt;(IQueryable&lt;/span&gt;&amp;lt;T&amp;gt; query, int &lt;/span&gt;activePage)       where &lt;/span&gt;T : class&lt;/span&gt;, new&lt;/span&gt;() {     ActivePage = activePage &amp;lt; 1 &lt;/span&gt;? ActivePage : activePage;     if &lt;/span&gt;(ActivePage &amp;lt; 1&lt;/span&gt;)         ActivePage = 1&lt;/span&gt;;     TotalItems = query.Count();      if &lt;/span&gt;(TotalItems &amp;lt;= PageSize)     {         ActivePage = 1&lt;/span&gt;;         TotalPages = 1&lt;/span&gt;;         return &lt;/span&gt;query;     }     int &lt;/span&gt;skip = ActivePage - 1&lt;/span&gt;;     if &lt;/span&gt;(skip &amp;gt; 0&lt;/span&gt;)         query = query.Skip(skip * PageSize);     _TotalPages = CalculateTotalPagesFromTotalItems();     return &lt;/span&gt;query.Take(PageSize); }&lt;/pre&gt;&lt;p&gt;  &lt;br /&gt;The IEnumerable&amp;lt;T&amp;gt; version simply&amp;#160; converts the IEnumerable to an IQuerable and calls back into this method for filtering.&lt;/p&gt;&lt;p&gt;The DataTable version requires a little more work to manually parse and filter records (I didnt want to add the Linq DataSetExtensions assembly just for this):&lt;/p&gt;&lt;pre class="code"&gt;/// &amp;lt;summary&amp;gt;/// &lt;/span&gt;Filters a data table for an ActivePage.&lt;/span&gt;/// /// &lt;/span&gt;Note: Modifies the data set permanently by remove DataRows&lt;/span&gt;/// &amp;lt;/summary&amp;gt;/// &amp;lt;param name=&amp;quot;dt&amp;quot;&amp;gt;&lt;/span&gt;Full result DataTable&lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;param name=&amp;quot;activePage&amp;quot;&amp;gt;&lt;/span&gt;Page to display. 0 to use ActivePage property &lt;/span&gt;&amp;lt;/param&amp;gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;/span&gt;public &lt;/span&gt;DataTable &lt;/span&gt;FilterDataTable(DataTable &lt;/span&gt;dt, int &lt;/span&gt;activePage){    ActivePage = activePage &amp;lt; 1 &lt;/span&gt;? ActivePage : activePage;    if &lt;/span&gt;(ActivePage &amp;lt; 1&lt;/span&gt;)        ActivePage = 1&lt;/span&gt;;    TotalItems = dt.Rows.Count;    if &lt;/span&gt;(TotalItems &amp;lt;= PageSize)    {        ActivePage = 1&lt;/span&gt;;        TotalPages = 1&lt;/span&gt;;        return &lt;/span&gt;dt;    }        int &lt;/span&gt;skip = ActivePage - 1&lt;/span&gt;;                if &lt;/span&gt;(skip &amp;gt; 0&lt;/span&gt;)    {        for &lt;/span&gt;(int &lt;/span&gt;i = 0&lt;/span&gt;; i &amp;lt; skip * PageSize; i++ )            dt.Rows.RemoveAt(0&lt;/span&gt;);    }    while&lt;/span&gt;(dt.Rows.Count &amp;gt; PageSize)        dt.Rows.RemoveAt(PageSize);    return &lt;/span&gt;dt;}&lt;/pre&gt;&lt;h3&gt;Using the Pager Control&lt;/h3&gt;&lt;p&gt;The pager as it is is a first cut I built a couple of weeks ago and since then have been tweaking a little as part of an internal project Im working on. Ive replaced a bunch of pagers on various older pages with this pager without any issues and have what now feels like a more consistent user interface where paging looks and feels the same. With the preset class tags applied too adding a pager is now as easy as dropping the control and adding the style sheet for styling to be just right. &lt;/p&gt;&lt;p&gt;Hopefully some of you find this as useful as I have&lt;/p&gt;&lt;h3&gt;Resources&lt;/h3&gt;&lt;ul&gt;  &lt;li&gt;&lt;a href="http://www.west-wind.com/WestwindWebToolkit/" target="_blank"&gt;&lt;strong&gt;The Pager is part of the West Wind Web &amp; Ajax Toolkit&lt;/strong&gt;&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.west-wind.com:8080/svn/WestwindWebToolkit/trunk/Westwind.Web/Extended/Pager.cs" target="_blank"&gt;&lt;strong&gt;Pager.cs Source Code (some toolkit dependencies)&lt;/strong&gt;&lt;/a&gt; &lt;/li&gt;  &lt;li&gt;&lt;a href="http://www.west-wind.com:8080/svn/WestwindWebToolkit/trunk/WestwindWebToolkitWeb/Css/Westwind.css" target="_blank"&gt;&lt;strong&gt;Westwind.css base stylesheet with .pager and .gridpager styles&lt;/strong&gt;&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;&lt;small&gt; Rick Strahl, West Wind Technologies, 2005-2009&lt;/small&gt;&lt;a href='/Weblog/ShowPosts.aspx?Category=ASP.NET'&gt;ASP.NET&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f114621.aspx&amp;title=A+free+standing+ASP.NET+Pager+Web+Control"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f114621.aspx" border='0' alt='kick it on DotNetKicks.com' /&gt;&lt;/a&gt;&lt;/small&gt;&lt;p&gt;&lt;a href='http://west-wind.com/Weblog/wwBanner.ashx?a=c&amp;id=ab6940fc&amp;t=633963658888101811' target='_top'&gt;&lt;img src='http://www.west-wind.com/banners/codemag3.jpg' border='0'&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=bvGSMm_4Cz4:CqGTWYbW_KU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=bvGSMm_4Cz4:CqGTWYbW_KU:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=bvGSMm_4Cz4:CqGTWYbW_KU:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=bvGSMm_4Cz4:CqGTWYbW_KU:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=bvGSMm_4Cz4:CqGTWYbW_KU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=bvGSMm_4Cz4:CqGTWYbW_KU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=bvGSMm_4Cz4:CqGTWYbW_KU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=bvGSMm_4Cz4:CqGTWYbW_KU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=bvGSMm_4Cz4:CqGTWYbW_KU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/RickStrahl/~4/bvGSMm_4Cz4" height="1" width="1"/&gt;</description><author>Rick Strahls WebLog                                                                                 </author><pubDate>Mon, 14 Dec 2009 00:00:00 GMT</pubDate></item><item><title>Visual Studio 2010 Beta 2 Startup Failures</title><link>http://feedproxy.google.com/~r/RickStrahl/~3/321gLr_kx6w/98126.aspx</link><description>&lt;p&gt;Ive been working with VS 2010 Beta 2 for a while now and while it works Ok most of the time it seems the environment is very, very fragile when it comes to crashes and installed packages. Specifically Ive been working just fine for days, then when VS 2010 crashes it will not re-start. Instead I get the good old &lt;em&gt;Application cannot start &lt;/em&gt;dialog:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="ApplicationCannotStart" border="0" alt="ApplicationCannotStart" src="http://www.west-wind.com/Weblog/images/200901/WindowsLiveWriter/VisualStudio2010StartupFailures_E314/ApplicationCannotStart_f0bed4d1-c1e2-4234-9d71-6737e0858d36.png" width="282" height="173" /&gt; &lt;/p&gt;  &lt;p&gt;Other failures Ive seen bring forth other just as useful dialogs with information overload like &lt;em&gt;Operation cannot be performed &lt;/em&gt;which for me specifically happens when trying to compile any project.&lt;/p&gt;  &lt;p&gt;After a bit of digging around and a post to Microsoft Connect the solution boils down to resetting the VS.NET environment. The Application Cannot Start issue stems from a package load failure of some sort, so the work around for this is typically:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;c:\program files\Visual Studio 2010\Common7\IDE\devenv.exe /ResetSkipPkgs&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;In most cases that should do the trick. If it doesnt and the error doesnt go away the more drastic:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;c:\program files\Visual Studio 2010\Common7\IDE\devenv.exe /ResetSettings &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;is required which resets all settings in VS to its installation defaults. Between these two Ive always been able to get VS to startup and run properly.&lt;/p&gt;  &lt;p&gt;BTW its handy to keep a list of command line options for Visual Studio around:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/xee0c8y7%28VS.100%29.aspx" href="http://msdn.microsoft.com/en-us/library/xee0c8y7%28VS.100%29.aspx"&gt;http://msdn.microsoft.com/en-us/library/xee0c8y7%28VS.100%29.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Note that the /? option in VS 2010 doesnt display all the options available but rather displays the demo version message instead, so the above should be helpful. Also note that unless you install Visual C++ the Visual Studio Command Prompt icon is not automatically installed so you may have to navigate manually to the appropriate folder above.&lt;/p&gt;  &lt;h3&gt;Cannot Build Failures&lt;/h3&gt;  &lt;p&gt;If you get the Cannot compile error dialog, there is another thing that have worked for me: Change your project build target from Debug to Release (or whatever  just change it) and compile again. If that doesnt work doing the reset steps above will do it for me.&lt;/p&gt;  &lt;p&gt;It appears this failure comes from some sort of interference of other versions of Visual Studio installed on the system and running another version first. Resetting the build target explicitly seems to reset the build providers to a normalized state so that things work in many cases. But not all. Worst case  resetting settings will do it.&lt;/p&gt;  &lt;p&gt;The bottom line for working in VS 2010 has been  dont get too attached to your custom settings as they will get blown away quite a bit. Ive probably been through 20 or more of these VS resets although Ive been working with it quite a bit on an internal project.&lt;/p&gt;  &lt;p&gt;Its kind of frustrating to see this kind of high level instability in a Beta 2 product which is supposedly the last public beta they will put out. On the other hand this beta has been otherwise rather stable and performance is roughly equivalent to VS 2008. Although I mention the crash above  crashes Ive seen have been relatively rare and no more frequent than in VS 2008 it seems. Given the drastic UI changes in VS 2010 (using WPF for the shell and editor) Im actually impressed that the product is as stable as it is at this point. Also I was seriously worried about text quality going to a WPF model, but thankfully WPF 4.0 addresses the blurry text issue with native font rendering to render text on non-cleartype enabled systems crisply.&lt;/p&gt;  &lt;p&gt;Anyway I hope that these notes are helpful to some of you playing around with the beta and running into problems. Hopefully you wont need them :-}&lt;/p&gt;&lt;small&gt; Rick Strahl, West Wind Technologies, 2005-2009&lt;/small&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f98126.aspx&amp;title=Visual+Studio+2010+Beta+2+Startup+Failures"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.west-wind.com%2fweblog%2fposts%2f98126.aspx" border='0' alt='kick it on DotNetKicks.com' /&gt;&lt;/a&gt;&lt;/small&gt;&lt;p&gt;&lt;a href='http://west-wind.com/Weblog/wwBanner.ashx?a=c&amp;id=8815900f&amp;t=633956676646779204' target='_top'&gt;&lt;img src='http://www.west-wind.com/banners/wwHelpBanner.Gif' border='0'&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=321gLr_kx6w:MxUmEMXo6K0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=321gLr_kx6w:MxUmEMXo6K0:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=321gLr_kx6w:MxUmEMXo6K0:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=321gLr_kx6w:MxUmEMXo6K0:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=321gLr_kx6w:MxUmEMXo6K0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=321gLr_kx6w:MxUmEMXo6K0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=321gLr_kx6w:MxUmEMXo6K0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?i=321gLr_kx6w:MxUmEMXo6K0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RickStrahl?a=321gLr_kx6w:MxUmEMXo6K0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RickStrahl?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;&lt;img src="http://feeds.feedburner.com/~r/RickStrahl/~4/321gLr_kx6w" height="1" width="1"/&gt;</description><author>Rick Strahls WebLog                                                                                 </author><pubDate>Sun, 06 Dec 2009 00:00:00 GMT</pubDate></item><item><title>How to read cookie values in JavaScript</title><link>http://ajaxaspects.blogspot.com/2009/12/how-to-read-cookie-values-in-javascript.html</link><description>&lt;p&gt;I recently had some odd effects with some pages that use cookies to store some local information. The bug seems to be widely spread in many web applications so here are my findings:&lt;/p&gt;  &lt;p&gt;To read the value of a specific cookie that was set previously you have to analyze the string in document.cookie that contains all cookies. Its a very readable format and looks like: &lt;/p&gt;  &lt;pre class="code"&gt;a=a101; aha=aha101; bob=bob101; b=b101; c01=c0101&lt;/pre&gt;&lt;p&gt;The trick is to find the right cookie in this string and extract the value.&lt;/p&gt;&lt;p&gt;I used a JavaScript function, named getCookie() that searched for the position of the cookie name by using&lt;/p&gt;&lt;pre class="code"&gt;start = document.cookie.indexOf(name + &amp;quot;=&amp;quot;);&lt;/pre&gt;&lt;p&gt; and this is wrong in some cases.&lt;/p&gt;&lt;p&gt;If you search for the cookie named &amp;quot;b&amp;quot; in the sample above you will get a starting-position within the cookie named &amp;quot;bob&amp;quot; because the indexOf function stops at the first occurrence of the text &amp;quot;b=&amp;quot;.&lt;/p&gt;&lt;p&gt;This seems to be a very common approach and some educational web sites still publish this kind of code that contains the mistake.&lt;/p&gt;&lt;p&gt;&lt;a title="http://www.w3schools.com/js/js_cookies.asp" href="http://www.w3schools.com/js/js_cookies.asp"&gt;http://www.w3schools.com/js/js_cookies.asp&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Its easy to fix this line by including the space character:&lt;/p&gt;&lt;pre class="code"&gt;var start = document.cookie.indexOf(&amp;quot; &amp;quot; + name + &amp;quot;=&amp;quot;);if (start &amp;gt;= 0) {  start += 1} else if (document.cookie.indexOf(name + &amp;quot;=&amp;quot;) == 0) {  start = 0;} // if&lt;/pre&gt;&lt;p&gt;But there is a more elegant solution when using regular expressions and even the retrieval of the value gets easier that I found at&lt;/p&gt;&lt;p&gt;&lt;a title="http://www.elated.com/articles/javascript-and-cookies/" href="http://www.elated.com/articles/javascript-and-cookies/"&gt;http://www.elated.com/articles/javascript-and-cookies/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Here is the full function:&lt;/p&gt;&lt;pre class="code"&gt;function get_cookie (cookie_name){  var results = document.cookie.match('(^;) ?' + cookie_name + '=([^;]*)(;$)');  if (results)    return (unescape(results[2]));  else    return (null);}&lt;/pre&gt;&lt;p&gt;Check your code.&lt;/p&gt;  &lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7581919-4723884146556010487?l=ajaxaspects.blogspot.com' alt='' /&gt;</description><author>Aspects of AJAX</author><pubDate>Sat, 05 Dec 2009 00:00:00 GMT</pubDate></item><item><title>IIS URL Rewrite  Redirect multiple domain names to one</title><link>http://weblogs.asp.net/owscott/archive/2009/11/30/iis-url-rewrite-redirect-multiple-domain-names-to-one.aspx</link><description>&lt;p&gt;Consider this a 2nd part to &lt;a href="http://weblogs.asp.net/owscott/archive/2009/11/27/iis-url-rewrite-rewriting-non-www-to-www.aspx" target="_blank"&gt;IIS URL Rewrite  rewriting non-www to www&lt;/a&gt;.&amp;#160; Reader Rubens asked about redirecting multiple domain names in a single rule.&amp;#160; Thats a good question and worth writing a part II blog post about it.&lt;/p&gt;  &lt;p&gt;Heres his question: &lt;/p&gt;     &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;&lt;p&gt;If there any generic way to do that if we have multiple domains with &lt;br /&gt;multiple extensions?example:&lt;br /&gt;mydomain.com to www.mydomain.com (already done)&lt;br /&gt;mydomain.net to www.mydomain.com&lt;br /&gt;www.mydomain.net to www.mydomain.com&lt;br /&gt;etccc...&lt;br /&gt;and maybe also&lt;br /&gt;www.mydomain2.net to www.mydomain.com&lt;br /&gt;etccc...&lt;br /&gt;Thanks.&lt;br /&gt;&lt;/p&gt;&lt;/pre&gt;  &lt;br /&gt;Regular expressions are great for handling .com / .net / .org in a single condition.&amp;#160; You can do this using a Condition input check for {HTTP_HOST} with a Pattern of:  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;^domain.(com|net|org)$&lt;/pre&gt;  &lt;br /&gt;&lt;em&gt;Match Any&lt;/em&gt;&lt;/strong&gt;.&amp;#160; This allows any of the rules to cause the rule to match the condition and redirect.&amp;#160; After setting to Match Any, you can add as many domains as you want with a single rule with multiple conditions.  &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;^(www.)?mydomain2.(com|net)$&lt;/pre&gt;  &lt;br /&gt;&lt;ul&gt;  &lt;li&gt;domain.com (1st condition) &lt;/li&gt;  &lt;li&gt;domain.net (1st condition) &lt;/li&gt;  &lt;li&gt;www.mydomain2.com (2nd condition) &lt;/li&gt;  &lt;li&gt;www.mydomain2.net (2nd condition) &lt;/li&gt;  &lt;li&gt;mydomain2.com (2nd condition) &lt;/li&gt;  &lt;li&gt;mydomain2.com (2nd condition) &lt;/li&gt;  &lt;li&gt;www.domain.net (3rd condition) &lt;/li&gt;&lt;/ul&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/owscott/image_thumb_66509B73.png" width="540" height="290" /&gt;&lt;/a&gt;       &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&amp;lt;&lt;/span&gt;rewrite&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &amp;lt;&lt;/span&gt;globalRules&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &amp;lt;&lt;/span&gt;rule&lt;/span&gt; name&lt;/span&gt;=&amp;quot;Redirects to www.domain.com&amp;quot;&lt;/span&gt; patternSyntax&lt;/span&gt;=&amp;quot;ECMAScript&amp;quot;&lt;/span&gt; stopProcessing&lt;/span&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;match&lt;/span&gt; url&lt;/span&gt;=&amp;quot;.*&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;conditions&lt;/span&gt; logicalGrouping&lt;/span&gt;=&amp;quot;MatchAny&amp;quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;                &amp;lt;&lt;/span&gt;add&lt;/span&gt; input&lt;/span&gt;=&amp;quot;{HTTP_HOST}&amp;quot;&lt;/span&gt; pattern&lt;/span&gt;=&amp;quot;^domain.*(com|net)$&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;                &amp;lt;&lt;/span&gt;add&lt;/span&gt; input&lt;/span&gt;=&amp;quot;{HTTP_HOST}&amp;quot;&lt;/span&gt; pattern&lt;/span&gt;=&amp;quot;^(www.)?mydomain2.(com|net)$&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;                &amp;lt;&lt;/span&gt;add&lt;/span&gt; input&lt;/span&gt;=&amp;quot;{HTTP_HOST}&amp;quot;&lt;/span&gt; pattern&lt;/span&gt;=&amp;quot;^www.domain.net$&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;/&lt;/span&gt;conditions&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;action&lt;/span&gt; type&lt;/span&gt;=&amp;quot;Redirect&amp;quot;&lt;/span&gt; url&lt;/span&gt;=&amp;quot;http://www.domain.com/{R:0}&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &amp;lt;/&lt;/span&gt;rule&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &amp;lt;/&lt;/span&gt;globalRules&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&amp;lt;/&lt;/span&gt;rewrite&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7267481" width="1" height="1"&gt;</description><author>Scott Forsyths WebLog</author><pubDate>Mon, 30 Nov 2009 00:00:00 GMT</pubDate></item><item><title>More Complex Operations in ADO.NET Data Services</title><link>http://aspalliance.com/1867_More_Complex_Operations_in_ADONET_Data_Services</link><description>In this article, Sergey describes how to define custom user operations in ADO.NET Data Services or Astoria. These operations can return plain content or a collection of objects. The article examines this aspect with the help of relevant code snippets. Sergey provides a brief overview of the data model instance control and delves deep into Service operations. Towards the end of the article, Sergey points out the various data representation formats, which Astoria returns when a web service is executed.</description><author>ASPAlliance.com - The #1 ASP.NET Community                                                          </author><pubDate>Mon, 30 Nov 2009 00:00:00 GMT</pubDate></item><item><title>IIS URL Rewrite  rewriting non-www to www</title><link>http://weblogs.asp.net/owscott/archive/2009/11/27/iis-url-rewrite-rewriting-non-www-to-www.aspx</link><description>&lt;p&gt;If youre using IIS 7.0 (or 7.5), URL Rewrite is a valuable tool, well worth installing and using.&lt;/p&gt;  &lt;p&gt;One common use of URL Rewrite is redirecting http://domain.com to http://www.domain.com.&amp;#160; Many people are doing this for search engine optimization (SEO) so that search engines only see the one site, rather than two sites.&amp;#160; The goal is to set a permanent 301 redirect.&lt;/p&gt;  &lt;p&gt;You can download URL Rewrite from &lt;a href="http://www.iis.net/expand/URLRewrite" target="_blank"&gt;http://www.iis.net/expand/URLRewrite&lt;/a&gt;.&amp;#160; For this walkthrough and screenshots Ill use URL Rewrite 2.0 RC1, but everything that Ill cover also works for version 1.0 and 1.1.&lt;/p&gt;  &lt;p&gt;URL Rewrite works at the global level, or site level (or application level for that matter).&amp;#160; Where you apply it is really up to how you manage your server.&amp;#160; Either will work for a domain name redirect like this.&lt;/p&gt;  &lt;p&gt;You can choose to create the rules using IIS Manager, or using a text editor and updating web.config directly.&amp;#160; Ill show both, starting with IIS Manager.&lt;/p&gt;  &lt;p&gt;Lets get started.&amp;#160; First, open IIS Manager and double-click on the URL Rewrite icon.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/owscott/image_140396FA.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/owscott/image_thumb_29BD598A.png" width="544" height="374" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Next, click on Add Rules from the Actions pane.&lt;/p&gt;  &lt;p&gt;Here youll have a choice from a few wizard options, and with URL Rewrite 2.0 you can also create outbound rules.&amp;#160; Create a Blank rule (inbound rules).&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/owscott/image_09729D0D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/owscott/image_thumb_28B543E0.png" width="387" height="258" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Give your rule a good friendly Name.&amp;#160; Ill call mine Redirect domain.com to www.&lt;/p&gt;  &lt;p&gt;In the Using&lt;strong&gt; &lt;/strong&gt;dropdown box you can choose between Regular Expressions and Wildcards.&amp;#160; Use wildcards if you arent familiar with regular expressions since they are much more intuitive.&amp;#160; However, if you later need to create more complex rules, regex may be necessary.&lt;/p&gt;  &lt;p&gt;For this demo select &lt;em&gt;Wildcards&lt;/em&gt;&lt;strong&gt;.&amp;#160; &lt;/strong&gt;However, Ill include instructions for those wanting to use regular expressions.&lt;/p&gt;  &lt;p&gt;Enter &lt;strong&gt;*&lt;/strong&gt; for the Pattern&lt;strong&gt;.&lt;/strong&gt;&amp;#160; That means anything qualifies.&amp;#160; Well use a condition later instead of matching to the URL.&amp;#160; (for Regular Expressions, use .*).&lt;/p&gt;  &lt;p&gt;Now expand the Conditions section and click Add.&amp;#160; In the Add Condition dialogue enter the following:&lt;/p&gt;  &lt;table border="0" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="147"&gt;Condition input:&lt;/td&gt;        &lt;td valign="top" width="253"&gt;{HTTP_HOST}&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="147"&gt;Check if input string:&lt;/td&gt;        &lt;td valign="top" width="253"&gt;Matches the Pattern&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="147"&gt;Pattern:&lt;/td&gt;        &lt;td valign="top" width="253"&gt;domain.com          &lt;br /&gt;(for regex, enter ^domain.com$)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="147"&gt;Ignore case:&lt;/td&gt;        &lt;td valign="top" width="253"&gt;checked&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/owscott/image_633043B4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/owscott/image_thumb_0C57DBF3.png" width="531" height="522" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click OK.&lt;/p&gt;  &lt;p&gt;Finally, its time to set the Action.&lt;/p&gt;  &lt;p&gt;In the Action section make sure that the Action Type is set to &lt;em&gt;Redirect&lt;/em&gt;.&amp;#160; &lt;/p&gt;  &lt;p&gt;For the Action Properties, enter http://www.domain.com/{R:0}.&amp;#160; The {R:0} retains the existing URL so if someone typed something like &lt;a href="http://domain.com/aboutus"&gt;http://domain.com/aboutus&lt;/a&gt; it would retain the aboutus as it adds the www.&lt;/p&gt;  &lt;p&gt;Be sure that the Append query string remains checked so that the querystring part is also retained. &lt;/p&gt;  &lt;p&gt;Also, be sure that the Redirect Type is set to Permanent (301), which is what the search engines like.&amp;#160; This tells the search engines to do a permanent redirect, use the new location and ignore the previous location.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://weblogs.asp.net/blogs/owscott/image_70D2D9EF.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://weblogs.asp.net/blogs/owscott/image_thumb_7066A6FA.png" width="501" height="221" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Finally, Apply the rule and test!&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Using a Text Editor&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;You can also create this rule manually by adding the following to your sites web.config (or applicationHost.config if you set this at the server level).&lt;/p&gt;  &lt;p&gt;In the &amp;lt;system.webServer&amp;gt; section of your web.config, add the following:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;Wildcards&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;          &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&amp;lt;&lt;/span&gt;rewrite&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &amp;lt;&lt;/span&gt;rules&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &amp;lt;&lt;/span&gt;rule&lt;/span&gt; name&lt;/span&gt;=&amp;quot;Redirect domain.com to www&amp;quot;&lt;/span&gt; patternSyntax&lt;/span&gt;=&amp;quot;Wildcard&amp;quot;&lt;/span&gt; stopProcessing&lt;/span&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;match&lt;/span&gt; url&lt;/span&gt;=&amp;quot;*&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;conditions&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;                &amp;lt;&lt;/span&gt;add&lt;/span&gt; input&lt;/span&gt;=&amp;quot;{HTTP_HOST}&amp;quot;&lt;/span&gt; pattern&lt;/span&gt;=&amp;quot;domain.com&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;/&lt;/span&gt;conditions&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;action&lt;/span&gt; type&lt;/span&gt;=&amp;quot;Redirect&amp;quot;&lt;/span&gt; url&lt;/span&gt;=&amp;quot;http://www.domain.com/{R:0}&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &amp;lt;/&lt;/span&gt;rule&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &amp;lt;/&lt;/span&gt;rules&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&amp;lt;/&lt;/span&gt;rewrite&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Save and you should be set.&lt;/p&gt;&lt;p&gt;Or, if you prefer Regular Expressions, use this instead:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Regular Expressions&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;      &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&amp;lt;&lt;/span&gt;rewrite&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &amp;lt;&lt;/span&gt;rules&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &amp;lt;&lt;/span&gt;rule&lt;/span&gt; name&lt;/span&gt;=&amp;quot;Redirect domain.com to www&amp;quot;&lt;/span&gt; patternSyntax&lt;/span&gt;=&amp;quot;ECMAScript&amp;quot;&lt;/span&gt; stopProcessing&lt;/span&gt;=&amp;quot;true&amp;quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;match&lt;/span&gt; url&lt;/span&gt;=&amp;quot;.*&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;conditions&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;                &amp;lt;&lt;/span&gt;add&lt;/span&gt; input&lt;/span&gt;=&amp;quot;{HTTP_HOST}&amp;quot;&lt;/span&gt; pattern&lt;/span&gt;=&amp;quot;^domain.com$&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;/&lt;/span&gt;conditions&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;            &amp;lt;&lt;/span&gt;action&lt;/span&gt; type&lt;/span&gt;=&amp;quot;Redirect&amp;quot;&lt;/span&gt; url&lt;/span&gt;=&amp;quot;http://www.domain.com/{R:0}&amp;quot;&lt;/span&gt; /&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;        &amp;lt;/&lt;/span&gt;rule&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;    &amp;lt;/&lt;/span&gt;rules&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"&gt;&amp;lt;/&lt;/span&gt;rewrite&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;&lt;p&gt;This is just the start to great SEO, but its a common step and one that I hope you find helpful.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=7266073" width="1" height="1"&gt;</description><author>Scott Forsyths WebLog</author><pubDate>Sat, 28 Nov 2009 00:00:00 GMT</pubDate></item></channel></rss>