<?xml version="1.0" encoding="UTF-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Michael Morozov</title><subtitle type="html">Software bits</subtitle><id>http://blogs.neudesic.com/blogs/michael_morozov/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/michael_morozov/default.aspx" /><link rel="self" type="application/atom+xml" href="http://blogs.neudesic.com/blogs/michael_morozov/atom.aspx" /><generator uri="http://communityserver.org" version="2.0.60217.2664">Community Server</generator><updated>2006-02-07T00:13:00Z</updated><entry><title>Compact Framework serial port object hangs up on finalization</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/michael_morozov/archive/2007/10/02/18100.aspx" /><id>http://blogs.neudesic.com/blogs/michael_morozov/archive/2007/10/02/18100.aspx</id><published>2007-10-02T20:44:00Z</published><updated>2007-10-02T20:44:00Z</updated><content type="html">&lt;DIV&gt;It looks like there is a bug in the Compact Framework 2.0&amp;nbsp;serial port implementation. It actually manifests itself in&amp;nbsp;different ways. In my case it occurred when I tried closing a SQL CE connection, but tracing the problem further revealed the true offender.&lt;/DIV&gt;
&lt;DIV class=ExternalClass876D3A40FDA74BD9A6E210A01466F608&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;When serial port is accessed via System.IO.Ports it is touching some unmanaged resources that require finalization. When the garbage collector kicks in, some finalizer hangs up and never returns effectively freezing your process. The reason it happens consistently when closing the SQL CE connection is because the GC is fired off when the last SQL connection is closed. This leads to a misconception of something being wrong with SQL CE.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;Here is the call stack of the event:&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;
&lt;DIV&gt;&lt;FONT face=Tahoma color=#3366ff size=2&gt;&amp;nbsp;&amp;nbsp;mscorlib.dll!System.PInvoke.EE.GC_WaitForPendingFinalizers()&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;mscorlib.dll!System.GC.WaitForPendingFinalizers() + 0x5 bytes&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;System.Data.SqlServerCe.dll!System.Data.SqlServerCe.SqlCeConnection.ObjectLifeTimeTracker.Close() + 0x169 bytes&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;System.Data.SqlServerCe.dll!System.Data.SqlServerCe.SqlCeConnection.Close(bool silent = false) + 0x27 bytes&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;System.Data.SqlServerCe.dll!System.Data.SqlServerCe.SqlCeConnection.Close() + 0x7 bytes&amp;nbsp;&lt;BR&gt;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face=Tahoma size=2&gt;&lt;FONT face=tahoma color=#3366ff&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/DIV&gt;&lt;/DIV&gt;
&lt;DIV&gt;There is very little information about this on the web. I could only find one post with a similar problem -&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;&lt;A href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=885259&amp;amp;SiteID=1" target=_blank&gt;&lt;FONT color=#0000ff&gt;http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=885259&amp;amp;SiteID=1&lt;/FONT&gt;&lt;/A&gt;&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;This guy is working with the barcode scanner, which ultimately is using the serial port. &lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;
&lt;DIV&gt;I solved the problem&amp;nbsp;by switching to a third-party com-port component called SerialNET by Franson (.com). It works like a charm. There are other similar components out there as well.&lt;/DIV&gt;
&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/DIV&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=18100" width="1" height="1"&gt;</content><author><name>Michael Morozov</name><uri>http://blogs.neudesic.com/members/Michael+Morozov.aspx</uri></author></entry><entry><title>Formatting currency according to the 3-character ISO 4217 code</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/michael_morozov/archive/2007/01/09/2247.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="1020" href="http://blogs.neudesic.com/blogs/michael_morozov/attachment/2247.ashx" /><id>http://blogs.neudesic.com/blogs/michael_morozov/archive/2007/01/09/2247.aspx</id><published>2007-01-09T23:21:00Z</published><updated>2007-01-09T23:21:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Verdana size=2&gt;.NET framework provides us with correct currency formatting based on the CultureInfo.NumberFormat settings. There are two ways to change the display of the currency values: &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;1. Set CurrentCulture on the Thread:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Verdana&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT color=#008080&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Thread&lt;/FONT&gt;.CurrentThread.CurrentCulture = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; &lt;FONT color=#008080&gt;CultureInfo&lt;/FONT&gt;(&lt;FONT color=#800000&gt;"en-US"&lt;/FONT&gt;);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#000000 size=2&gt;This method is used if you need to change currency formatting for all objects on the page. Don't confuse CurrentCulture with CurrentUICulture. CurrentUICulture is set to the culture of Windows installation, i.e. the language&amp;nbsp;of the OS. &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face=Verdana size=2&gt;2. Use ToString() method with FormatProvider&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&amp;nbsp;&amp;nbsp; &lt;FONT size=2&gt;amount.ToString(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"C"&lt;/FONT&gt;&lt;FONT size=2&gt;, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CultureInfo&lt;/FONT&gt;&lt;FONT size=2&gt;(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"en-US"&lt;/FONT&gt;&lt;FONT size=2&gt;).NumberFormat);&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Verdana&gt;
&lt;P&gt;&lt;FONT color=#000000 size=2&gt;NumberFormat member implements IFormatProvider and has properties that define the look of the currency in this particular culture. This method can be used when you need to display amounts in different currency on the same page, e.g. in a multi-currency grid.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;The problem&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;One&amp;nbsp;difficulty that is being discovered&amp;nbsp;by many people is that in order to format currency according&amp;nbsp;to a particular culture, one must know the .NET-centric culture name (en-US) or its numerical LCID to instantiate the CultureInfo object. In reality, currency is often identified by a 3-letter code&amp;nbsp;(ISO 4217) such as USD, GBP, JPY, EUR etc. Suppose you have a table with Amount and Currency columns, such as:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;-------------&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;1234&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;USD&lt;BR&gt;456342&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;JPY&lt;BR&gt;7894&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;USD&lt;BR&gt;-------------&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;You need to display these values in the grid and use the correct currency formatting for each value. Unforunately t&lt;/FONT&gt;&lt;FONT size=2&gt;he .NET framework provides no mechanism to map the 3-letter code to a culture identifier. When looking for a solution I have seen many variations with lookup tables, where the 3-letter code would map to the culture LCID. Other&amp;nbsp;people resorted to writing their own formatters, which was even less appealing. There had to be a better way!&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;The solution&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;There is another class in .NET globalization namespace called&amp;nbsp;&lt;STRONG&gt;RegionInfo&lt;/STRONG&gt;. &lt;/FONT&gt;&lt;FONT size=2&gt;This class has the &lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;ISOCurrencySymbol&lt;STRONG&gt; &lt;/STRONG&gt;property, which is the 3-letter ISO 4217 code we are after. And it is instantiated the same way as the CultureInfo object via culture name or culture ID. If we can find the RegionInfo via the currency ISO code, we can find the corresponding culture ID and create the CultureInfo object for currency formatting.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;There is no method that will return a RegionInfo from a currency ISO code, so we need to enumerate all RegionInfo's in the system to find the right one. Unfortunately there is no easy way to get all RegionInfo's. But there is a way to get all&amp;nbsp;cultures via the CultureInfo.GetCultures() static method.&amp;nbsp;All we need to do now&amp;nbsp;is create the RegionInfo object for each culture and check its ISOCurrencySymbol until we find the one we want. A quick and dirty solution looks like this:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;protected&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CultureInfo&lt;/FONT&gt;&lt;FONT size=2&gt; CultureInfoFromCurrencyISO( &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; isoCode )&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CultureInfo&lt;/FONT&gt;&lt;FONT size=2&gt;[] cultures = &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CultureInfo&lt;/FONT&gt;&lt;FONT size=2&gt;.GetCultures(&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CultureTypes&lt;/FONT&gt;&lt;FONT size=2&gt;.SpecificCultures);&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;foreach&lt;/FONT&gt;&lt;FONT size=2&gt; (&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;CultureInfo&lt;/FONT&gt;&lt;FONT size=2&gt; ci &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;in&lt;/FONT&gt;&lt;FONT size=2&gt; cultures)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;RegionInfo&lt;/FONT&gt;&lt;FONT size=2&gt; ri = &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#008080 size=2&gt;RegionInfo&lt;/FONT&gt;&lt;FONT size=2&gt;(ci.LCID);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;if&lt;/FONT&gt;&lt;FONT size=2&gt; (ri.ISOCurrencySymbol == isoCode)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&lt;/FONT&gt;&lt;FONT size=2&gt; ci;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT size=2&gt;;&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;Note that we are interested only in specific cultures (&lt;FONT color=#008080&gt;CultureTypes&lt;/FONT&gt;&lt;FONT size=2&gt;.SpecificCultures parameter). Neutral cultures cannot produce the RegionInfo. An example of a neutral culture is "en", whereas specific cultures are "en-US" and "en-GB". Currency is defined for a specific culture such as USD for en-US and&amp;nbsp;GBP for en-GB.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;This method will return a CultureInfo from a currency ISO code, which can be used for currency formatting like this:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;amount.ToString(&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;"C"&lt;/FONT&gt;&lt;FONT size=2&gt;, CultureInfoFromCurrencyISO(currency).NumberFormat);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;It will work, but you don't want to use it in any kind of serious production code. It will create&amp;nbsp;up to 130 RegionInfo objects on each call and if you are using it in a long grid (as intended) it will tax the garbage collector significantly.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;STRONG&gt;Improved solution&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;In order to improve the quick solution we will simply use the method described above to populate a lookup dictionary once and use it for all subsequent calls. Implementation is attached. It is a singleton class CurrencyHelper with the following static methods:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT color=#008080 size=2&gt;
&lt;P&gt;CultureInfo&lt;/FONT&gt;&lt;FONT size=2&gt; CultureInfoFromCurrencyISO(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; isoCode)&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; FormatCurrency(&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;decimal&lt;/FONT&gt;&lt;FONT size=2&gt; amount, &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT size=2&gt; currencyISO)&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;First method will&amp;nbsp;return the CultureInfo from an ISO code and the second method will format the decimal amount according to the currency ISO code passed as a second parameter.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;The benefit of this solution are:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;1.&amp;nbsp;No lookup tables and&amp;nbsp;subsequent maintenance&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;2. No custom formatting code&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;3. Pure .NET implementation ensures it will work in future versions&lt;BR&gt;4. Fast lookup via a generic Dictionary class&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT size=2&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=2247" width="1" height="1"&gt;</content><author><name>Michael Morozov</name><uri>http://blogs.neudesic.com/members/Michael+Morozov.aspx</uri></author></entry><entry><title>100% Height in Opera 8.02 or later</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/04/18/96.aspx" /><id>http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/04/18/96.aspx</id><published>2006-04-18T20:50:00Z</published><updated>2006-04-18T20:50:00Z</updated><content type="html">&lt;P&gt;Users of the Opera browser may have been unpleasantly surprised after upgrading to version 8.02 or later. Some web-sites suddenly shrunk up and wouldn't fill the screen anymore. These web-sites used elements with an attribute Height=100% to control the layout. The description of this problem appears all over the Internet, sometimes in rather strong words:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://techpatterns.com/forums/about537.html"&gt;http://techpatterns.com/forums/about537.html&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;It has caused a lot of grief to the developers. Some people claimed they had a solution&amp;nbsp;but it still didn't work for me. There is a way to make it work and the workaround is quite simple. Opera didn't stop supporting 100% height attribute on the tables. It still works. However, it is not 100% of the screen height. It is 100% of the height of the containter element. The outmost container is the page itself and some people were able to fix the problem by setting the Height on the &amp;lt;body&amp;gt; tag to 100%. However in ASP.NET there is also a &amp;lt;form&amp;gt; element, which is usually the outermost HTML element&amp;nbsp;on the page. And Opera has changed the way it treats the size of the &amp;lt;form&amp;gt; element. Since it is not a visual element, it&amp;nbsp;is logical that it doesn't have the Height attribute and doesn't have size. It used to be like that. However it is treated as a visual element with some default height in the new versions of Opera and upcoming version 9.0 available as CTP is no exception. Since it doesn't have the Height attribute, we can use the style attribute to set its height to 100%:&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;form&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;id&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="Form1"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;method&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="post"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="server"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;style&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="height:100%"&amp;gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000 size=3&gt;Now the outermost container on the page will fill the page and the table inside the form will also stretch to 100% of the page.&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=96" width="1" height="1"&gt;</content><author><name>Michael Morozov</name><uri>http://blogs.neudesic.com/members/Michael+Morozov.aspx</uri></author></entry><entry><title>Crystal Reports menus</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/03/20/79.aspx" /><id>http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/03/20/79.aspx</id><published>2006-03-20T18:57:00Z</published><updated>2006-03-20T18:57:00Z</updated><content type="html">&lt;P&gt;In Crystal Reports (I am using version 9), if you right-click on a field embedded into a label, a context menu appears with the following items:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Text Formatting...&lt;BR&gt;Format Text...&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Can you guess what they do? :) The former opens up the "Font" dialog, the latter goes to the "Paragraph" dialog. Oh, joy...&lt;/P&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=79" width="1" height="1"&gt;</content><author><name>Michael Morozov</name><uri>http://blogs.neudesic.com/members/Michael+Morozov.aspx</uri></author></entry><entry><title>Single Sign-On for everyone</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/03/17/72.aspx" /><id>http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/03/17/72.aspx</id><published>2006-03-16T23:17:00Z</published><updated>2006-03-16T23:17:00Z</updated><content type="html">&lt;P&gt;Single Sign-On (SSO) is a hot topic these days. Most clients I worked with have&amp;nbsp;more than one&amp;nbsp;web&amp;nbsp;application running under different versions of .NET framework in different subdomains, or even in different domains and they want to let the user login once and stay logged in when switching to a different web site. Today we will implement SSO and see if we can make it work in different scenarios. We will start with a simple case and gradually build upon it:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;SSO for parent and child application in the virtual sub-directory 
&lt;LI&gt;SSO using different authorization credentials (username mapping) 
&lt;LI&gt;SSO for two applications in two sub-domains of the same domain 
&lt;LI&gt;SSO when applications run under different versions of .NET 
&lt;LI&gt;SSO for two applications in different domains. 
&lt;LI&gt;SSO for mixed-mode authentication (Forms and Windows)&lt;/LI&gt;&lt;/OL&gt;&lt;B&gt;
&lt;P&gt;1. SSO for parent and child application in the virtual sub-directory&lt;BR&gt;&lt;BR&gt;&lt;/B&gt;Lets assume that we have two .NET applications - Foo and Bar, and Bar is running in a virtual sub-directory of Foo (http://foo.com/bar). Both applications implement Forms authentication. Implementation of Forms authentication requires you to&amp;nbsp;override the Application_AuthenticateRequest, where you perform the authentication and upon successful authentication, call FormsAuthentication.RedirectFromLoginPage, passing in the logged-in user name (or any other piece of information that identifies the user in the system) as a parameter. In ASP.NET the logged-in user status is&amp;nbsp;persisted by storing the cookie on the client computer. When you call RedirectFromLoginPage,&amp;nbsp;a cookie is created which contains an encrypted FormsAuthenticationTicket with the name of the logged-in user . There is a section in web.config that defines how the cookie is created:&lt;/P&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;
&lt;P&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;authentication&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;mode&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;Forms&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;forms&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;name&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;.FooAuth&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;protection&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;All&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;timeout&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;60&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;loginUrl&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;login.aspx&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;" &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;authentication&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;authentication&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;mode&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;Forms&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;forms&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;name&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;.BarAuth&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;protection&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;All&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;timeout&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;60&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;loginUrl&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;login.aspx&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; /&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;authentication&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;The important attributes here are &lt;B&gt;name&lt;/B&gt; and &lt;B&gt;protection.&amp;nbsp;&lt;/B&gt;If you&amp;nbsp;make them match for both Foo and Bar applications, they will both write and read the same cookie using the same protection level, effectively providing SSO:&lt;/P&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;
&lt;P&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;authentication&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;mode&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;Forms&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;forms&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;name&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;.SSOAuth&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;protection&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;All&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;timeout&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;60&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;loginUrl&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;login.aspx&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; /&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;authentication&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;When protection attribute is set to "All", both encryption and validation (via hash) is applied to the cookie. The default validation and encryption keys are stored in the machine.config file and can be overridden in the application’s web.config file. The default value is this:&lt;/P&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;
&lt;P&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;machineKey&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;validationKey&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;AutoGenerate,IsolateApps&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;decryptionKey&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; AutoGenerate,IsolateApps&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;validation&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;SHA1&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; /&amp;gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;IsolateApps means that a different key will be generated for every application. We can’t have that. In order for the cookie to be encrypted and decrypted with the same key in all applications either remove the IsolateApps option or better yet, add the same concrete key to the web.config of all applications using SSO:&lt;/P&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;
&lt;P&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;machineKey&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;validationKey&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;decryptionKey&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902F8D923AC&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;validation&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;SHA1&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; /&amp;gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;If you are authenticating against the same users store, this is all it takes – a few changes to the web.config files. &lt;/P&gt;&lt;B&gt;
&lt;P&gt;2. SSO using different authorization credentials (username mapping)&lt;/P&gt;&lt;/B&gt;
&lt;P&gt;But what if&amp;nbsp;the Foo application authenticates against its own database and the Bar application uses Membership API or some other form of authentication? In this case the automatic cookie that is created on the Foo is not going to be any good for the Bar, since it will contain the user name that makes no sense to the Bar. &lt;/P&gt;
&lt;P&gt;To make it work, you will need to create the second authentication cookie especially for the Bar application. You will also need a way to map the Foo user to the Bar user. Lets assume that you have a user "John Doe" logging in to the Foo application and you determined that this user is identified as "johnd" in the Bar application. In the Foo authentication method you will add the following code:&lt;/P&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;
&lt;P&gt;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; fat = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(1, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ffa500 size=2&gt;"johnd"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Now, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Now.AddYears(1), true, "");&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; cookie = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;".BarAuth"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;);&lt;BR&gt;cookie.Value = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthentication&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Encrypt(fat);&lt;BR&gt;cookie.Expires = fat.Expiration;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpContext&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Current.Response.Cookies.Add(cookie);&lt;/P&gt;
&lt;P&gt;FormsAuthentication.RedirectFromLoginPage("&lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff9900 size=2&gt;John Doe&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;");&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;User names are hard-coded for demonstration purposes only. This code snippet creates the FormsAuthenticationTicket for the Bar application and stuffs it with the user name that makes sense in the context of the Bar application. And then it calls RedirectFromLoginPage to create the correct authentication cookie for the Foo application. If you changed the name of forms authentication cookie to be the same for both applications (see our previous example), make sure that they are different now, since we are not using the same cookie for both sites anymore:&lt;/P&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;
&lt;P&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;authentication&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;mode&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;Forms&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;forms&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;name&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;.FooAuth&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;protection&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;All&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;timeout&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;60&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;loginUrl&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;login.aspx&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;slidingExpiration&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;authentication&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;authentication&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;mode&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;Forms&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;forms&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;name&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;.BarAuth&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;protection&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;All&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;timeout&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;60&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;loginUrl&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;login.aspx&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;slidingExpiration&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;authentication&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Now when the user is logged in to Foo, he is mapped to the Bar user and the Bar authentication ticket is created along with the Foo authentication ticket. If you want it to work in the reverse direction, add similar code to the Bar application:&lt;/P&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;
&lt;P&gt;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; fat = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(1, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ffa500 size=2&gt;"John Doe"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Now, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Now.AddYears(1), true, "");&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; cookie = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;".FooAuth"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;);&lt;BR&gt;cookie.Value = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthentication&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Encrypt(fat);&lt;BR&gt;cookie.Expires = fat.Expiration;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpContext&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Current.Response.Cookies.Add(cookie);&lt;/P&gt;
&lt;P&gt;FormsAuthentication.RedirectFromLoginPage("&lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff9900 size=2&gt;johnd&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;");&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Also make sure that you have the &amp;lt;machineKey&amp;gt; element in web.config of both applications with matching validation and encryption keys.&lt;/P&gt;&lt;B&gt;
&lt;P&gt;3. SSO for two applications in two sub-domains of the same domain&lt;/P&gt;&lt;/B&gt;
&lt;P&gt;Now what if Foo and Bar are configured to run under different domains http://foo.com and http://bar.foo.com. The code above will not work because the cookies will be stored in different files and will not be visible to both applications. In order to make it work, we will need to create domain-level cookies that are visible to all sub-domains. We can’t use RedirectFromLoginPage method anymore, since it doesn’t have the flexibility to create a domain-level cookie. So we do it manually:&lt;/P&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;
&lt;P&gt;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; fat = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(1, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ffa500 size=2&gt;"johnd"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Now, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Now.AddYears(1), true, "");&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; cookie = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;".BarAuth"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;);&lt;BR&gt;cookie.Value = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthentication&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Encrypt(fat);&lt;BR&gt;cookie.Expires = fat.Expiration;&lt;BR&gt;&lt;FONT&gt;cookie.Domain = &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;".foo.com";&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpContext&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Current.Response.Cookies.Add(cookie);&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;
&lt;P&gt;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; fat = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(1, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ffa500 size=2&gt;"John Doe"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Now, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Now.AddYears(1), true, "");&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; cookie = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;".FooAuth"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;);&lt;BR&gt;cookie.Value = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthentication&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Encrypt(fat);&lt;BR&gt;cookie.Expires = fat.Expiration;&lt;BR&gt;&lt;FONT&gt;cookie.Domain = &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;".foo.com";&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpContext&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Current.Response.Cookies.Add(cookie);&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Note the highlighted lines. By explicitly setting the cookie domain to ".foo.com" we ensure that this cookie will be visible in both http://foo.com and http://bar.foo.com or any other sub-domain. You can also specifically set the Bar authentication cookie domain to "bar.foo.com". It is more secure, since other sub-domains can’t see it now. Also notice that RFC 2109 requires two periods in the cookie domain value, therefore we add a period in the front – ".foo.com"&lt;/P&gt;
&lt;P&gt;Again, make sure that you have the same &amp;lt;machineKey&amp;gt; element in web.config of both applications. There is only one exception to this rule and it is explained in the next secion.&lt;/P&gt;&lt;B&gt;
&lt;P&gt;4. SSO when applications run under different versions of .NET&lt;/P&gt;&lt;/B&gt;
&lt;P&gt;It is possible that Foo and Bar applications run under different version of .NET. In this case the above examples will not work. It turns out that ASP.NET 2.0 is using a different encryption method for authorization tickets. In ASP.NET 1.1 it was 3DES, in ASP.NET 2.0 it is AES. Fortunately, a new attribute was introduced in ASP.NET 2.0 for backwards compatibility&lt;/P&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;
&lt;P&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;machineKey&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;validationKey&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;decryptionKey&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;F9D1A2D3E1D3E2F7B3D9F90FF3965ABDAC304902F8D923AC&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;validation&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;SHA1&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;decryption&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;3DES&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt; /&amp;gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;Setting &lt;FONT face="Courier New" color=#ff0000&gt;decryption&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff&gt;=&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;"&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff&gt;3DES&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;" &lt;/FONT&gt;will make ASP.NET 2.0 use the old encryption method, making the cookies compatible again. Don’t try to add this attribute to the web.config of the ASP.NET 1.1 application. It will cause an error.&lt;/P&gt;&lt;B&gt;
&lt;P&gt;5. SSO for two applications in different domains.&lt;/P&gt;&lt;/B&gt;
&lt;P&gt;We’ve been quite successful creating shared authentication cookies so far, but what if Foo and Bar are in different domains – http://foo.com and http://bar.com? They cannot possibly share a cookie or create a second cookie for each other. In this case each site will need to create its own cookies, and call the other site to verify if the user is logged in elsewhere. One way to do it is via a series of redirects.&lt;/P&gt;
&lt;P&gt;In order to achieve that, we will create a special page (we’ll call it sso.aspx) on both web sites. The purpose of this page is to check if the cookie exists in its domain and return the logged in user name, so that the other application can create a similar cookie in its own domain. This is the sso.aspx from Bar.com:&lt;/P&gt;&lt;FONT face="Courier New" size=2&gt;
&lt;P&gt;&amp;lt;%&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;@&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;Page&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;Language&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;="C#"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; %&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;
&lt;P&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;script&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;language&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;="C#"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#ff0000 size=2&gt;runat&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;="server"&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;void&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; Page_Load()&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;// this is our caller, we will need to redirect back to it eventually&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;UriBuilder&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; uri = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;UriBuilder&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(Request.UrlReferrer); &lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; c = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpContext&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Current.Request.Cookies[&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;".BarAuth"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;];&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; (c != &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &amp;amp;&amp;amp; c.HasKeys) &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;// the cookie exists!&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;try&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; cookie = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpContext&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Current.Server.UrlDecode(c.Value);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; fat = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthentication&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Decrypt(cookie);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;uri.Query = uri.Query + &lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;"&amp;amp;ssoauth="&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; + fat.Name; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;// add logged-in user name to the query&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;catch&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Response.Redirect(uri.ToString()); &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;// redirect back to the caller&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;} &lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;
&lt;P&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;script&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;This page always redirects back to the caller. If the authentication cookie exists on Bar.com, it is decrypted and the user name is passed back in the query string parameter &lt;I&gt;ssoauth&lt;/I&gt;.&lt;/P&gt;
&lt;P&gt;On the other end (Foo.com), we need to insert some code into the http request processing pipeline. It can be in Application_BeginRequest event or in a custom HttpHandler or HttpModule. The idea is to intercept all page requests to Foo.com as early as possible to verify if authentication cookie exists:&lt;/P&gt;


&lt;P&gt;1. If authentication cookie exists on Foo.com, continue processing the request. User is logged in on Foo.com&lt;BR&gt;2. If authentication cookie doesn’t exist, redirect to Bar.com/sso.aspx.&lt;BR&gt;3. If the current request is the redirect back from Bar.com/sso.aspx, analyse the ssoauth parameter and create an authentication cookie if necessary.&lt;/P&gt;
&lt;P&gt;It looks pretty simple, but we have to watch out for infinite loops:&lt;/P&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;
&lt;P&gt;// see if the user is logged in&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; c = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpContext&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Current.Request.Cookies[&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;".FooAuth"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;];&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;
&lt;P&gt;if&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; (c != &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &amp;amp;&amp;amp; c.HasKeys) &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;// the cookie exists!&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;try&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; cookie = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpContext&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Current.Server.UrlDecode(c.Value);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; fat = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthentication&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Decrypt(cookie);&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;// cookie decrypts successfully, continue processing the page&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;catch&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;}&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;
&lt;P&gt;// the authentication cookie doesn't exist - ask Bar.com if the user is logged in there&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;UriBuilder&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; uri = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;UriBuilder&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(Request.UrlReferrer);&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;
&lt;P&gt;if&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; (uri.Host != &lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;"bar.com"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; || uri.Path != &lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;"/sso.aspx"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;) &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;// prevent infinite loop&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Response.Redirect(&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;&lt;A href="http://bar.com/sso.aspx"&gt;http://bar.com/sso.aspx&lt;/A&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;);&lt;BR&gt;}&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;else&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// we are here because the request we are processing is actually a response from bar.com&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; (Request.QueryString[&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;"ssoauth"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;] == &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;null&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Bar.com also didn't have the authentication cookie&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;return&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;// continue normally, this user is not logged-in&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;} &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;else&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// user is logged in to Bar.com and we got his name!&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; userName = (&lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;string&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;)Request.QueryString[&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;"ssoauth"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008000 size=2&gt;// let's create a cookie with the same name&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; fat = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthenticationTicket&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(1, userName, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Now, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;DateTime&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Now.AddYears(1), &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;true&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;, &lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;""&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; cookie = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;new&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpCookie&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;(&lt;/FONT&gt;&lt;FONT face="Courier New" color=#800000 size=2&gt;".FooAuth"&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cookie.Value = &lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;FormsAuthentication&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Encrypt(fat);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cookie.Expires = fat.Expiration;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#008080 size=2&gt;HttpContext&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;.Current.Response.Cookies.Add(cookie);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;}&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;The same code should be placed on both sites, just make sure you are using correct cookie names (.FooAuth vs. .BarAuth) on each site. Since the cookie is not actually shared, the applications can have different &amp;lt;machineKey&amp;gt; elements. It is not necessary to synchronize the encryption and validation keys. &lt;/P&gt;
&lt;P&gt;Some of us may cringe at the security implications of passing the user name in the query string. A couple of things can be done to protect it. First of all we are checking the referrer and we will not accept the ssoauth parameter from any source other then bar.com/sso.aspx (or foo.com/ssp.aspx). Secondly, the name can easily be encrypted with a shared key. If Foo and Bar are using different authentication mechanisms, additional user information (e.g. e-mail address) can be passed along similarly.&lt;/P&gt;&lt;B&gt;
&lt;P&gt;6. SSO for mixed-mode authentication (Forms and Windows)&lt;/P&gt;&lt;/B&gt;
&lt;P&gt;So far we have dealt with Forms authentication only. But what if we want to authenticate Internet users via Forms authentication first and if it fails, check if the Intranet user is authenticated on the NT domain? In theory we can check the following parameter to see if there is a Windows logon associated with the request: &lt;/P&gt;&lt;FONT face="Courier New" size=2&gt;
&lt;P&gt;Request.ServerVariables["LOGON_USER"]&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;However, unless our site has Anonymous Access disabled, this value is always empty. We can disable Anonymous Access and enable Integrate Windows Authentication for our site in the IIS control panel. Now the LOGON_USER value contains the NT domain name of the logged in Intranet user. But all Internet users get challenged for the Windows login name and password. Not cool. We need to be able to let the Internet users login via Forms authentication and if it fails, check their Windows domain credentials.&lt;/P&gt;
&lt;P&gt;One way to solve this problem is to have a special entry page for Intranet users that has Integrate Windows Authentication enabled, validates the domain user, creates a Forms cookie and redirects to the main web site. We can even conceal the fact that Intranet users are hitting a different page by making a Server.Transfer. &lt;/P&gt;
&lt;P&gt;There is also an easier solution. It works because of the way IIS handles the authentication process. If anonymous access is enabled for a web site, IIS is passing requests right through to the ASP.NET runtime. It doesn’t attempt to perform any kind of authentication. However, if the request results in an authentication error (401), IIS will attempt an alternative authentication method specified for this site. You need to enable both Anonymous Access and Integrated Windows Authentication and execute the following code if Forms authentication fails:&lt;/P&gt;&lt;FONT face="Courier New" color=#0000ff size=2&gt;
&lt;P&gt;if&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt; (System.Web.HttpContext.Current.Request.ServerVariables["LOGON_USER"] == "") {&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Web.HttpContext.Current.Response.StatusCode = 401;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Web.HttpContext.Current.Response.End(); &lt;BR&gt;} &lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;else &lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#339966 size=2&gt;// Request.ServerVariables["LOGON_USER"] has a valid domain user now!&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;BR&gt;}&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;When this code executes, it will check the domain user and will get an empty string initially. It will then terminate the current request and return the authentication error (401) to IIS. This will make the IIS use the alternative authentication mechanism, which in our case is Integrated Windows Authentication. If the user is already logged in to the domain, the request will be repeated, now with the NT domain user information filled-in. If the user is not logged in to the domain, he will be challenged for the Windows name/password up to 3 times. If the user cannot login after the third attempt, he will get the 403 error (access denied).&lt;/P&gt;&lt;B&gt;
&lt;P&gt;Conclusion&lt;/P&gt;&lt;/B&gt;
&lt;P&gt;We have examined various scenarios of Single Sign-On for two ASP.NET applications. It is also quite possible to implement SSO for heterogeneous systems spawning across different platforms. Ideas remain the same, but the implementation may require some creative thinking.&lt;/P&gt;&lt;FONT face=Arial size=2&gt;&lt;/FONT&gt;&lt;FONT face=Arial size=2&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=72" width="1" height="1"&gt;</content><author><name>Michael Morozov</name><uri>http://blogs.neudesic.com/members/Michael+Morozov.aspx</uri></author></entry><entry><title>ASP.NET 2.0 two-way binding and calculated fields</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/03/06/67.aspx" /><id>http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/03/06/67.aspx</id><published>2006-03-06T21:54:00Z</published><updated>2006-03-06T21:54:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Arial size=2&gt;Did you get that feeling of excitement, when during the ASP.NET 2.0 presentation the two-way bound data grid was built with a few mouse clicks? It does look impressive. However, when you get home and try to do something a little bit more complicated, you hit the wall and end up scratching your head, looking for a magic&amp;nbsp;property that will suddenly make everything work. While Microsoft provides a great number of magic&amp;nbsp;properties and attributes, sometimes you have to resort to actually using the keyboard and writing some code. I particularly like it what a problem can be solved in exactly one line of code. I even wanted to call my blog the "one line fix", but it sounds too much like a stupid cocaine movie title. But the idea remains. I encounter quite a few problems&amp;nbsp;when programming in .NET and if I find a one-line solution for something I will share it with you.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;1.&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;One such problem I encountered when doing the aforementioned two-way data binding. It has to do with having a calculated column.&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;It's really quite easy to create a two-way bound data grid:&lt;/FONT&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;Drop DetailsView control onto the form&lt;/FONT&gt; &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;Click on the smart-tag and choose "New data source" in the drop-down list.&lt;/FONT&gt; &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;Follow the wizard which will build a SELECT statement for you&lt;/FONT&gt; &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;Click on WHERE button to add a parameter to you SELECT query&lt;/FONT&gt; &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;Click on ADVANCE button and check "Generate INSERT, UPDATE and DELETE statemens". Your table should have a primary key for this&amp;nbsp;option to be enabled. You also must select the primary key column&amp;nbsp;as one of the retrieved columns.&lt;/FONT&gt; &lt;/FONT&gt;
&lt;LI&gt;&lt;FONT face=Arial size=2&gt;Finish the wizard and check "Enable editing" in the smart tag panel&lt;/FONT&gt;&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Your page source will look something like the following listing. Here is your DetailsView element with 5 bound fields - Id, FirstName, LastName, BirthDate and SunSign (zodiac sign).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;DetailsView&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="DetailsView1"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="server"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;AutoGenerateRows&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="False"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;DataKeyNames&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="id" &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#ff0000&gt;DataSourceID&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="SqlDataSource1"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Height&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="50px"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Width&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="125px"&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;Fields&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;BoundField&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;DataField&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="id"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;HeaderText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="id"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;InsertVisible&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="False"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ReadOnly&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="True" &lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#ff0000&gt;SortExpression&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="id"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;BoundField&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;DataField&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="firstname"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;HeaderText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="firstname"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;SortExpression&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="firstname"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;BoundField&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;DataField&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="lastname"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;HeaderText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="lastname"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;SortExpression&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="lastname"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;BoundField&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;DataField&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="birthdate"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;HeaderText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="birthdate"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;SortExpression&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="birthdate"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;DataFormatString&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="{0:d}"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;BoundField&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;DataField&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="sunsign"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;HeaderText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="sunsign"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;SortExpression&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="sunsign"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;CommandField&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ShowEditButton&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="True"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;Fields&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;DetailsView&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff&gt;&lt;FONT color=#000000 size=2&gt;Here is your SqlDataSource with generated&amp;nbsp;SELECT, UPDATE, INSERT and DELETE commands and parameter lists for each command:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;SqlDataSource&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="SqlDataSource1"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="server"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ConnectionString&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="&lt;/FONT&gt;&amp;lt;%$ ConnectionStrings:SocionicsConnectionString %&amp;gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;"&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#ff0000&gt;DeleteCommand&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="DELETE FROM [PEOPLE] WHERE [id] = @id"&lt;/FONT&gt; &lt;BR&gt;&lt;FONT color=#ff0000&gt;InsertCommand&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="INSERT INTO [PEOPLE] ([birthdate], [sunsign], [firstname], [lastname]) VALUES (@birthdate, @sunsign, @firstname, @lastname)"&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#ff0000 size=2&gt;SelectCommand&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SELECT [id], [birthdate], [sunsign], [firstname], [lastname] FROM [PEOPLE] WHERE ([id] = @id)"&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#ff0000&gt;UpdateCommand&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="UPDATE [PEOPLE] SET [birthdate] = @birthdate, [sunsign] = @sunsign, [firstname] = @firstname, [lastname] = @lastname WHERE [id] = @id"&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;DeleteParameters&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Parameter&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="id"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="Int32"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;DeleteParameters&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;UpdateParameters&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Parameter&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="birthdate"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="DateTime"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Parameter&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="sunsign"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="Int32"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Parameter&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="firstname"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="String"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Parameter&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="lastname"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="String"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Parameter&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="id"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="Int32"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;UpdateParameters&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;SelectParameters&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;QueryStringParameter&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;DefaultValue&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="0"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="id"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;QueryStringField&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="id"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="Int32"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;SelectParameters&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;InsertParameters&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Parameter&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="birthdate"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="DateTime"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Parameter&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="sunsign"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="Int32"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Parameter&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="firstname"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="String"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Parameter&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="lastname"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="String"&lt;/FONT&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;InsertParameters&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;SqlDataSource&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Note that a SelectParameter is a QueryStringParameter. It will automatically pull the "id" from the QueryString and pass it to the SELECT statement. It can also be a ControlParameter pulling the value from another control on the form. It works great for building Master-Detail data forms. The INSERT and UPDATE parameters will be populated from BoundField items in the DetailsView automatically. Very simple. &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;2.&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;T&lt;/FONT&gt;&lt;FONT face=Arial&gt;here is one bug I want to mention. Obviously you would want to format the output for the BirthDate column, since the default representation includes hours, minutes and seconds. Fortunately Microsoft provides a magic property &lt;FONT color=#ff0000&gt;DataFormatString&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="{0:d}". &lt;/FONT&gt;Unfortunately it doesn't work. Another magic property can be applied to make the data formatting also work in edit and insert mode - &lt;FONT color=#ff0000&gt;ApplyFormatInEditMode&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="True".&amp;nbsp;&lt;FONT color=#000000&gt;This one does work, but in the view mode the value is still shown as a full date-time string. Ahh, screw this magic, let's convert this column to a TemplateField and see if&amp;nbsp;we can format it manually. Open the columns editor, select the "birthdate" column and click on "Convert this field into a TemplateField". You will see that the BoundField expands into this:&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff&gt;&lt;FONT color=#000000&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;TemplateField&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;HeaderText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="birthdate"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;SortExpression&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;="birthdate"&amp;gt;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;EditItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;TextBox&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="TextBox1"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="server"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Text&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;='&lt;/FONT&gt;&amp;lt;%# Bind("birthdate", "{0:d}") %&amp;gt;&lt;FONT color=#0000ff&gt;'&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;TextBox&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;EditItemTemplate&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;InsertItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;TextBox&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="TextBox1"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="server"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Text&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;='&lt;/FONT&gt;&amp;lt;%# Bind("birthdate", "{0:d}") %&amp;gt;&lt;FONT color=#0000ff&gt;'&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;TextBox&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;InsertItemTemplate&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="Label1"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="server"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Text&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;='&lt;/FONT&gt;&amp;lt;%# Bind("birthdate", "{0:d}") %&amp;gt;&lt;FONT color=#0000ff&gt;'&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemTemplate&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;TemplateField&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff&gt;&lt;FONT color=#000000 size=2&gt;Note that it created a template for each mode. Edit and Insert templates have a TextBox in them. The&amp;nbsp;view item template has a Label. Also notice the Bind() method call in the server-side tag. This is where the magic happens. Bind() is the new feature in ASP.NET 2.0 which does the two-way data binding. It populates the field with the value from the DataSource and carries the value back into the DataSource parameters. The second parameter is the data formatting string and luckily it works here. The birthdate is formatted now. My guess is that the BoundField implementation simply forgets to pass the DataFormatString into the underlying control. Hopefully it will be fixed in the next version of .NET. But for now we can deal with it by simply converting the column to a template column.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;3.&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Everything looks good so far, but let's dig a little deeper. Take a look at the "sunsign" column. It is an integer with numbers 1-12 indicating the zodiac sign corresponding to the birthdate. While we can modify this field via the form, it is not the best idea. It would make more sense to calculate this column based on the birth date and update it automatically. Can we do it easily? We can certainly try. Let's convert that field to a TemplateField, and change the&amp;nbsp;TextBox in the Edit template to the Label:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;TemplateField&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;HeaderText&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="sunsign"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;SortExpression&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;="sunsign"&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;EditItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="TextBox2"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="server"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Text&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;='&lt;/FONT&gt;&amp;lt;%# Bind("sunsign") %&amp;gt;&lt;FONT color=#0000ff&gt;'&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;EditItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;InsertItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="TextBox2"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="server"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Text&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;='&lt;/FONT&gt;&amp;lt;%# Bind("sunsign") %&amp;gt;&lt;FONT color=#0000ff&gt;'&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;InsertItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="Label2"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="server"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Text&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;='&lt;/FONT&gt;&amp;lt;%# Bind("sunsign") %&amp;gt;&lt;FONT color=#0000ff&gt;'&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;ItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;TemplateField&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;CommandField&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ShowEditButton&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="True"&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;/&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Now we have a read-only column. Let's try to change the binding statement. Suppose that we have a CalcSign method that takes a date as a parameter and returns a zodiac sign. Can we do something like this? -&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;EditItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="TextBox2"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="server"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Text&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;='&lt;/FONT&gt;&amp;lt;%# &lt;FONT color=#000000&gt;CalcSign&lt;/FONT&gt;(Bind("sunsign")) %&amp;gt;&lt;FONT color=#0000ff&gt;'&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;EditItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Nope we cannot. The Bind() method is not valid in this context. It cannot appear in the parameter list. Fortunately we also have the Eval() method that can:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;EditItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="TextBox2"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="server"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;Text&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;='&lt;/FONT&gt;&amp;lt;%# &lt;FONT color=#000000&gt;CalcSign&lt;/FONT&gt;(Eval("sunsign")) %&amp;gt;&lt;FONT color=#0000ff&gt;'&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;:&lt;/FONT&gt;&lt;FONT color=#800000&gt;Label&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000&gt;EditItemTemplate&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Unforunately, the Eval() method doesn't provide the luxury of two-way binding. While it will work for displaying the correct value, the parameter that is passed into the UPDATE statement will be NULL. So we arrived at the head-scratching post. I still want my two-way binding and I cannot have a calculated column! &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;4.&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;The easiest way to solve this problem is to write one line of code. Let's implement an event handler for the ItemUpdating event of the DetailsView. It fires right before the UPDATE statement is executed and in its arguments it has two important collections - NewValues and OldValues. And we can do anything we want with these values: &lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;protected&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;void&lt;/FONT&gt; &lt;FONT color=#000000&gt;DetailsView1&lt;/FONT&gt;_ItemUpdating(&lt;FONT color=#0000ff&gt;object&lt;/FONT&gt; sender, &lt;FONT color=#008080&gt;DetailsViewUpdateEventArgs&lt;/FONT&gt; e)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;e.NewValues[&lt;FONT color=#800000&gt;"sunsign"&lt;/FONT&gt;] = CalcSign(&lt;FONT color=#008080&gt;Convert.ToDateTime&lt;/FONT&gt;(e.NewValues[&lt;FONT color=#800000&gt;"birthdate"&lt;/FONT&gt;]));&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;In this case we only want to take the new value of the "birthdate" column, convert it to the zodiac sign and replace the value of the "sunsign" column. We should implement the same event handler for ItemInserting event. So here is the one line solution to a common problem. &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;&lt;STRONG&gt;5.&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Another useful event is ItemUpdated (ItemInserted). What we can do here is catch and process the database exception:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;protected&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;void&lt;/FONT&gt; DetailsView1_ItemUpdated(&lt;FONT color=#0000ff&gt;object&lt;/FONT&gt; sender, &lt;FONT color=#008080&gt;DetailsViewUpdatedEventArgs&lt;/FONT&gt; e)&lt;BR&gt;{&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&lt;/FONT&gt; (e.Exception != &lt;FONT color=#0000ff&gt;null&lt;/FONT&gt;)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#008080&gt;Debug&lt;/FONT&gt;.Write(e.Exception.Message);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;e.ExceptionHandled = &lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;This is really useful, because you don't want the yellow screen with errors to appear and since everything is so "code-less", there is no place to implement a try-catch block if anything goes wrong. This try-catch is implemented for you and is wired to the ItemUpdated event. Make sure you set the ExceptionHandled property to true, otherwise the exception will bubble up to the user.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial size=2&gt;Welcome to the&amp;nbsp;2-way binding!&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT size=2&gt;&lt;FONT face=Arial&gt;&amp;nbsp;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=67" width="1" height="1"&gt;</content><author><name>Michael Morozov</name><uri>http://blogs.neudesic.com/members/Michael+Morozov.aspx</uri></author></entry><entry><title>Google tips</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/03/03/64.aspx" /><id>http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/03/03/64.aspx</id><published>2006-03-03T22:55:00Z</published><updated>2006-03-03T22:55:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Arial&gt;Don't you just hate it when you are trying to search for a product review, all you get is middle-man shopping sites? Surely, you&amp;nbsp;add the&amp;nbsp;words "review", "compare" to the product name and model number, but all these sites have a "review" section (with 0 reviews in it) and a "compare" section where they compare prices. In fact, online shopping has become so intrusive, you get a link to a shopping site no matter what you are searching for. &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;The way I deal with it - I add words to the query that normally don't appear on shopping sites but may be in a review. One such word is "sucks". Google for "xbox 360 sucks" and you will get no shopping sites, only reviews. Very unbiased reviews :) If you want a different kind of reviews, search for word "excited".&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;I think one feature that Google MUST implement, is a filter for shopping sites. It is not in their best interest, since they get a lot of revenue from these links, but hopefully money isn't everything. If it were, there would have been porn sites poping out on every search - an even better source of revenue. But&amp;nbsp;Google implemented a filter for that. Online shopping sites is the next big threat to humanity.&amp;nbsp;Porn&amp;nbsp;is a&amp;nbsp;lesser threat. It takes balls to support&amp;nbsp;a porn site (pun intended). It takes&amp;nbsp;next to nothing&amp;nbsp;to create and support a&amp;nbsp;shopping site&amp;nbsp;clone.&amp;nbsp;These things are multiplying like rabbits on the wave of the powerful promise of secondary income. Well, somebody's secondary income&amp;nbsp;is becoming&amp;nbsp;a primary concern for everyone else. Uninvited soliciting is what it is!&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;In fact I'd prefer to see porn links instead of these countless and&amp;nbsp;nameless&amp;nbsp;online store clones. Google, take note!&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.neudesic.com/aggbug.aspx?PostID=64" width="1" height="1"&gt;</content><author><name>Michael Morozov</name><uri>http://blogs.neudesic.com/members/Michael+Morozov.aspx</uri></author></entry><entry><title>Dependent data-bound controls in ASP.NET 2.0</title><link rel="alternate" type="text/html" href="http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/03/03/63.aspx" /><id>http://blogs.neudesic.com/blogs/michael_morozov/archive/2006/03/03/63.aspx</id><published>2006-03-03T19:59:00Z</published><updated>2006-03-03T19:59:00Z</updated><content type="html">&lt;P&gt;&lt;FONT face=Arial&gt;We all know that in ASP.NET 2.0 we can create data-bound forms without writing any code. You can, for example, create a databound drop-down list using a wizard that takes you through creating a database connection, building the select query and binding it to the control. It will generate something like this:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;DropDownList&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="ddlCountry"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="server"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DataSourceID&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SqlDataSourceCountry" &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DataTextField&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="country"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DataValueField&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="country"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;AutoPostBack&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="True"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;DropDownList&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;SqlDataSource&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SqlDataSourceCountry"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="server"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ConnectionString&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;%$ ConnectionStrings:MyConnectionString %&amp;gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;" &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;SelectCommand&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SELECT [CountryName] FROM [Country] ORDER BY [CountryName]"&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;SqlDataSource&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;As&amp;nbsp;you can see it created an ad-hoc select statement in the UI.&amp;nbsp;The only thing that is worse than sticking your database queries into the&amp;nbsp;presentation tier is emitting&amp;nbsp;presentation HTML from the stored&amp;nbsp;procedures. Whatever happened to n-tier design, Microsoft? ;) Actually the new code-less features of ASP.NET are&amp;nbsp;great for prototyping. And using it as such, I have encountered an interesting phenomenon,&amp;nbsp;which I want to share with you.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;Consider having two drop down lists on the page for Country and City:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;DropDownList&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="ddlCountry"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="server"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DataSourceID&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SqlDataSourceCountry" &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DataTextField&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="country"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DataValueField&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="country"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;AutoPostBack&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="True"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;DropDownList&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;SqlDataSource&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SqlDataSourceCountry"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="server"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ConnectionString&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;%$ ConnectionStrings:MyConnectionString %&amp;gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;" &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;SelectCommand&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SELECT [CountryName] FROM [Country] ORDER BY [CountryName]"&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;SqlDataSource&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;DropDownList&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="ddlCity"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="server"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DataSourceID&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SqlDataSourceCity" &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DataTextField&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="city"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DataValueField&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="city"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;AutoPostBack&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="True"&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;DropDownList&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;SqlDataSource&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SqlDataSourceCity"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="server"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ConnectionString&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;%$ ConnectionStrings:MyConnectionString %&amp;gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;" &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;SelectCommand&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SELECT [CityName] FROM [City] ORDER BY [CityName]"&amp;gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;SqlDataSource&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial&gt;You also want to make these controls interdependent, so&amp;nbsp;when a country is selected, the list of cities is filtered for this country only. To do that you expand the definition of datasource for the City drop-down list:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;SqlDataSource&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ID&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SqlDataSourceCity"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;runat&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="server"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ConnectionString&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="&lt;/FONT&gt;&lt;FONT size=2&gt;&amp;lt;%$ ConnectionStrings:MyConnectionString %&amp;gt;&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;" &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#ff0000 size=2&gt;SelectCommand&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SELECT [CityName] FROM [City] WHERE (@VarCountry = 'all' OR [CountryName] = @VarCountry) ORDER BY [CityName]"&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;SelectParameters&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;ControlParameter&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;ControlID&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="ddlCountry"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;DefaultValue&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="all"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;Name&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="VarCountry"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#ff0000 size=2&gt;PropertyName&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="SelectedValue" &lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#ff0000 size=2&gt;Type&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="String"&lt;/FONT&gt;&lt;FONT size=2&gt; &lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;/&amp;gt;"&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&amp;nbsp;&amp;nbsp; &amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;SelectParameters&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;asp&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;:&lt;/FONT&gt;&lt;FONT color=#800000 size=2&gt;SqlDataSource&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT face=Arial&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000000 size=3&gt;We have added the ControlParameter to the data source definition, which pulls the selected value from our Country drop-down list and uses it as a parameter to the query. Look ma, no hands! I mean no code. It was all created by the data-binding wizard and this is just one of the many&amp;nbsp;ways&amp;nbsp;to parameterize you queries. This was easy enough. Now when we select a Country, the list of Cities changes accordingly. &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Arial color=#000000 size=3&gt;Next thing we want to do is add a default value to the list of Countries that will get us all cities unfiltered. You can see that the query above already has an additional clause&amp;nbsp;&lt;FONT color=#0000ff size=2&gt;@VarCountry = 'all' &lt;FONT color=#000000 size=3&gt;to effectively cancel the filtering by a particular country, when the value of the parameter equals to 'all'. So all we need to do is add this default value to the list of countries as a first element. And ASP.NET 2.0 provides a new way to do just that. You can simply add that value to the list of Items in the designer and set the new property &lt;FONT color=#ff0000 size=2&gt;AppendDataBoundItems&lt;/FONT&gt;&lt;FONT color=#0000ff size=2&gt;="True"&lt;FONT color=#000000 size=3&gt;. In the old days, when a control was data-bound, it's existing list of items was cleared. The OnDataBound event was fired later, so we could add our values to the list after it was populated from the data source. N&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial color=#000000 size=3&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000 size=3&gt;&lt;FONT color=#0000ff size=2&gt;&lt;FONT color=#000000 size=3&gt;ow we can add values to 