<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Tutto .NET</title><link>http://weblogs.asp.net/alessandro/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>Conserving Resources When Writing BLOB Values to SQL Server and Streaming BLOB Values back to the Client</title><link>http://weblogs.asp.net/alessandro/archive/2008/09/22/conserving-resources-when-writing-blob-values-to-sql-server-and-streaming-blob-values-back-to-the-client.aspx</link><pubDate>Mon, 22 Sep 2008 23:22:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6638302</guid><dc:creator>alessandro</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/alessandro/rsscomments.aspx?PostID=6638302</wfw:commentRss><comments>http://weblogs.asp.net/alessandro/archive/2008/09/22/conserving-resources-when-writing-blob-values-to-sql-server-and-streaming-blob-values-back-to-the-client.aspx#comments</comments><description>
&lt;p&gt;&amp;nbsp;Reading and writing blob data to/from your database can be a resource hog, because it normally involves holding the entire stream in memory. Holding 10kb, 20, 100kb in memory might not be an issue, however as you start allowing larger file uploads, your application starts to feel the stress and easily starts to run out of resources. &lt;br&gt;&lt;br&gt;Particularly, say you had a relatively small file (2mb) your allowing users to upload from your pages. User A uploads, it's only 2mb, you have not exceeded your memory allocation yet. However, as more users try to upload simultaneously, now your allocating more memory slots at a time, eg. if they were 5 simultaneous users, that's 2*5 = 10mb, 100 users, then it's 2*100. &lt;br&gt;&lt;br&gt;This is all too stressful on your webserver, or atleast was until ASP.NET 2.0. Since, things have changed and now asp.net supports setting a diskThreshold that allows you to specify the amount of data buffered in server memory for the request. So, say you wanted to keep the default diskThreshold of 256 bytes, when the file is larger than 256bytes, asp.net begins to write the filestream to disk Versus keeping it in memory. This is just great because i remember back in the day, this was quite annoying. Glad it's fixed. This means we do nothing as far as the upload is concerned from the client to your webserver.&lt;br&gt;&lt;br&gt;Still, if we are storing the stream in SQL Server, now we have a whole new scenario, and the question remains, how do we stream this data to sql server while conserving memory ? Should we stream the entire data as is in one lump ? Wont that allocate memory on our database server before writing to the database field ? This is what i want to address. Basically, what we want to do is save our file stream to sqlserver in smaller chunks, that way our database server will allocate only enough memory for that little chunk before writing it to the database field, in this way conserving memory at the cost of write speed(no free lunch, i'm afraid). &lt;br&gt;&lt;br&gt;However, the price to pay in latency for streaming chunks of data to sql server might be well worth, because the alternative is to tax your database server when memory is available and to crash it (I assume it may crash when it runs out of memory. I have not tried personally. You may try that yourself if your feeling curious. Do not forget to share your findings if you do :P)&lt;br&gt;&lt;br&gt;Take, SQL SERVER Express edition as an example which has the imposed limit of 1gb memory. That's not a whole lot is it ? Streaming the data to sql server in chunks is actually not as taxing as it may seem. True, the write performance is degraded but you can regulate it by increasing/decreasing the size of your chunk to find a compromise.&lt;br&gt;&lt;br&gt;So, how do we do this ? SQL Server 2005 has a new feature that enables it to update a field with .WRITE ; as you stream your chunks it just appends it to the existing field. You can read about it here : &lt;a href="http://msdn.microsoft.com/en-us/library/ms177523.aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms177523.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms177523.aspx&lt;/a&gt;&lt;br&gt;&lt;br&gt;To Quote the documentation from the above link : &lt;br&gt;Because the .WRITE clause cannot be used to modify a NULL column, the column is first populated with temporary data. This data is then replaced with the correct data by using the .WRITE clause&lt;br&gt;&lt;br&gt;Now, that's not cool! We can work around that nicely though. Ineffect, it does not even feel like were working around anything. I've basically followed microsofts own documentation located at : &lt;a href="http://msdn.microsoft.com/en-us/library/aa719771.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa719771.aspx"&gt;http://msdn.microsoft.com/en-us/library/aa719771.aspx&lt;/a&gt;, which had the proper code, however, instead of .Write, it uses an older method that is not compatible with&amp;nbsp; the newer varbinary,varchar(max),nvarchar(max) datatypes supported by SQL Server 2005&amp;nbsp; as opposed to the older not recommeded types -&amp;gt; image, text, and ntext. &lt;br&gt;&lt;br&gt;Following is an extract of the code i use to stream chunks of data to sql server using the .Write method. The purpose of the sample code is to display how you can go about writing your own ofcourse. I have just ripped the piece of code out of my DAL with a few minor adjustments, so just running a copy/paste of the code below will or may not yield much depending on your level of expertise. I am just way too lazy to write a completely contained example so bear with me. As it is, this article has gotten longer than I want it to be.&lt;br&gt;&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InsertFile(&lt;span class="kwrd"&gt;string&lt;/span&gt; applicationName, Stream data,&lt;br&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; mimeType, &lt;span class="kwrd"&gt;string&lt;/span&gt; fileName)&lt;br&gt;{&lt;br&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; fileId = -1;&lt;br&gt;    &lt;span class="kwrd"&gt;using&lt;/span&gt; (SqlConnection myConnection = GetSqlConnection())&lt;br&gt;    {&lt;br&gt;        myConnection.Open();&lt;br&gt;        SqlCommand cmd = &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlCommand(DbOwner + &lt;br&gt;    &lt;span class="str"&gt;".DataFile_Insert"&lt;/span&gt;, myConnection);&lt;br&gt;        cmd.CommandType = CommandType.StoredProcedure;&lt;br&gt;        cmd.Parameters.Add(&lt;span class="str"&gt;"@applicationName"&lt;/span&gt;, &lt;br&gt;SqlDbType.NVarChar, 256).Value = applicationName;&lt;br&gt;        cmd.Parameters.Add(&lt;span class="str"&gt;"@mimeType"&lt;/span&gt;, &lt;br&gt;    SqlDbType.NVarChar, 50).Value = mimeType;&lt;br&gt;        cmd.Parameters.Add(&lt;span class="str"&gt;"@length"&lt;/span&gt;, &lt;br&gt;    SqlDbType.Int, 4).Value = data.Length;&lt;br&gt;        cmd.Parameters.Add(&lt;span class="str"&gt;"@fileName"&lt;/span&gt;, &lt;br&gt;    SqlDbType.NVarChar, 256).Value = fileName;&lt;br&gt;        SqlParameter fileIdParam = &lt;br&gt;cmd.Parameters.Add(&lt;span class="str"&gt;"@fileId"&lt;/span&gt;, SqlDbType.Int, 4);&lt;br&gt;        fileIdParam.Direction = ParameterDirection.Output;&lt;br&gt;        cmd.ExecuteNonQuery();&lt;br&gt;        &lt;span class="rem"&gt;// now insert in chunks&lt;/span&gt;&lt;br&gt;        fileId = (&lt;span class="kwrd"&gt;int&lt;/span&gt;)fileIdParam.Value;&lt;br&gt;    }&lt;br&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (fileId &amp;gt; -1)&lt;br&gt;    {&lt;br&gt;        &lt;span class="rem"&gt;//The size of the "chunks" &lt;/span&gt;&lt;br&gt;&lt;span class="rem"&gt;// 128 bytes, regulate at will&lt;/span&gt;&lt;br&gt;        InsertFileByChunks(fileId, data, 128);&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;note how we are calling InsertFileByChunks from our insert method above ? &lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; InsertFileByChunks(&lt;span class="kwrd"&gt;int&lt;/span&gt; fileId, Stream data, &lt;span class="kwrd"&gt;int&lt;/span&gt; bufferLen)&lt;br&gt;{&lt;br&gt;    &lt;span class="kwrd"&gt;using&lt;/span&gt; (SqlConnection myConnection = GetSqlConnection())&lt;br&gt;    {&lt;br&gt;        myConnection.Open();&lt;br&gt;        SqlCommand cmd = &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlCommand(DbOwner + &lt;br&gt;&lt;span class="str"&gt;".DataFile_InsertChunk"&lt;/span&gt;, myConnection);&lt;br&gt;        cmd.CommandType = CommandType.StoredProcedure;&lt;br&gt;        cmd.Parameters.Add(&lt;span class="str"&gt;"@fileId"&lt;/span&gt;, &lt;br&gt;SqlDbType.Int, 4).Value = fileId;&lt;br&gt;        SqlParameter paramData = cmd.Parameters.Add(&lt;span class="str"&gt;"@data"&lt;/span&gt;, &lt;br&gt;    SqlDbType.VarBinary, 128);&lt;br&gt;        SqlParameter paramOffset = cmd.Parameters.Add(&lt;span class="str"&gt;"@offset"&lt;/span&gt;, &lt;br&gt;                SqlDbType.BigInt);&lt;br&gt;        cmd.Parameters.Add(&lt;span class="str"&gt;"@length"&lt;/span&gt;, &lt;br&gt;    SqlDbType.Int, 4).Value = bufferLen;&lt;br&gt;        &lt;span class="kwrd"&gt;using&lt;/span&gt; (BinaryReader br = &lt;span class="kwrd"&gt;new&lt;/span&gt; BinaryReader(data))&lt;br&gt;        {&lt;br&gt;            &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] buffer = br.ReadBytes(bufferLen);&lt;br&gt;            &lt;span class="kwrd"&gt;int&lt;/span&gt; offset = 0;&lt;br&gt;            &lt;span class="kwrd"&gt;while&lt;/span&gt; (buffer.Length &amp;gt; 0)&lt;br&gt;            {&lt;br&gt;                paramData.Value = buffer;&lt;br&gt;                paramOffset.Value = offset;&lt;br&gt;                cmd.ExecuteNonQuery();&lt;br&gt;                offset += bufferLen;&lt;br&gt;                buffer = br.ReadBytes(bufferLen);&lt;br&gt;            }&lt;br&gt;        }&lt;br&gt;        data.Close();&lt;br&gt;    }&lt;br&gt;}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;As you can see the above method just writes chunks of data at a time(the accompanying stored procedure DataFile_InsertChunk uses .Write to update the field with the new chunks as they come in).&lt;br&gt;&lt;br&gt;And now the accompanying stored procedures DataFile_Insert and DataFile_InsertChunk : &lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;PROCEDURE&lt;/span&gt; [dbo].[DataFile_Insert]&lt;br&gt;    @applicationName nvarchar(256),&lt;br&gt;    @mimeType nvarchar(50), &lt;br&gt;    @length &lt;span class="kwrd"&gt;int&lt;/span&gt;, &lt;br&gt;    @fileName nvarchar(256),&lt;br&gt;    @fileId &lt;span class="kwrd"&gt;int&lt;/span&gt; &lt;span class="kwrd"&gt;output&lt;/span&gt;&lt;br&gt;&lt;span class="kwrd"&gt;AS&lt;/span&gt;&lt;br&gt;&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;DECLARE&lt;/span&gt; @applicationId UNIQUEIDENTIFIER&lt;br&gt;    &lt;span class="kwrd"&gt;SELECT&lt;/span&gt;  @ApplicationId = ApplicationId &lt;span class="kwrd"&gt;FROM&lt;/span&gt; dbo.aspnet_Applications &lt;br&gt;    &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; &lt;span class="kwrd"&gt;LOWER&lt;/span&gt;(@ApplicationName) = LoweredApplicationName&lt;br&gt;        &lt;span class="kwrd"&gt;INSERT&lt;/span&gt; &lt;span class="kwrd"&gt;INTO&lt;/span&gt; &lt;br&gt;             dataFile (applicationId, &lt;span class="kwrd"&gt;data&lt;/span&gt;, mimeType, [length],  &lt;br&gt;            [fileName], dateCreated, lastDateModified)&lt;br&gt;        &lt;span class="kwrd"&gt;VALUES&lt;/span&gt; (@applicationId, 0x0, @mimeType, @length, @fileName,  &lt;br&gt;        GETDATE(), GETDATE())&lt;br&gt;        &lt;span class="kwrd"&gt;SET&lt;/span&gt; @fileId = SCOPE_IDENTITY()    &lt;br&gt;&lt;span class="kwrd"&gt;END&lt;/span&gt; &lt;/pre&gt;
&lt;p&gt;&amp;nbsp;Note above how we introduce the value 0x0 (null) as per the article on MSDN into the data field ? "data" is the name of the field that will be holding our data stream and is a varbinary type. The reason we introduce the value 0x0 is because .Write cannot write into a NULL field.&amp;nbsp; This is the workaround i was talking about earlier and it does not effect the appended chunks in anyway.&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;CREATE&lt;/span&gt; &lt;span class="kwrd"&gt;PROCEDURE&lt;/span&gt; [dbo].[DataFile_InsertChunk]&lt;br&gt;    @&lt;span class="kwrd"&gt;data&lt;/span&gt; varbinary(&lt;span class="kwrd"&gt;MAX&lt;/span&gt;), &lt;br&gt;    @length &lt;span class="kwrd"&gt;int&lt;/span&gt;, &lt;br&gt;    @fileId &lt;span class="kwrd"&gt;int&lt;/span&gt; &lt;span class="kwrd"&gt;output&lt;/span&gt;,&lt;br&gt;    @offset bigint&lt;br&gt;&lt;span class="kwrd"&gt;AS&lt;/span&gt;&lt;br&gt;&lt;span class="kwrd"&gt;BEGIN&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;UPDATE&lt;/span&gt; dataFile &lt;span class="kwrd"&gt;SET&lt;/span&gt; &lt;span class="kwrd"&gt;data&lt;/span&gt;.&lt;span class="kwrd"&gt;WRITE&lt;/span&gt;(@&lt;span class="kwrd"&gt;data&lt;/span&gt;, @offset, &lt;br&gt;@length) &lt;span class="kwrd"&gt;WHERE&lt;/span&gt; fileId = @fileId    &lt;br&gt;END&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;As you can see, it all boils down to this. Quite simple indeed. the .WRITE method takes as argument your chunk, the offset and the length. Not much for me to add here. Oh one thing you may also want to note is that .WRITE is called via the field to which it needs to write to. so the syntax takes the form of -&amp;gt; fieldName.WRITE(...) ; in my case the field name is "data" as you can note from the code in the stored proc above.&lt;br&gt;&lt;br&gt;We have now successfully stored our file stream in chunks. Next we want to see how to retrieve our filestream in a similar manner, that way we do not hog resources on our webserver when binary content is requested, requiring us to stream it out from the database server to the webserver where our code streams it out again to the client. Firstly, I hope you are already familiar with an HttpHandler, if not you can look it up on google. &lt;/p&gt;

&lt;p&gt;An HttpHandler/Module is general knowledge so i'm not going to get into it. I've mapped somefile.ashx to my HttpHandler, that way, every request that comes in will be handled by my custom handler, where i request the file stream from the database and then stream it out again in chunks to the client. My HttpHandler looks like this : &lt;br&gt;&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; BinaryDataHandler : IHttpHandler&lt;br&gt;{&lt;br&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; ProcessRequest(HttpContext context)&lt;br&gt;{&lt;br&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; fileId;&lt;br&gt;    &lt;span class="kwrd"&gt;bool&lt;/span&gt; success = &lt;span class="kwrd"&gt;int&lt;/span&gt;.TryParse(&lt;br&gt;        context.Request.QueryString[&lt;span class="str"&gt;"fileId"&lt;/span&gt;], &lt;br&gt;            &lt;span class="kwrd"&gt;out&lt;/span&gt; fileId);&lt;br&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (success)&lt;br&gt;    {&lt;br&gt;        IDataReader r = FileManager.GetFileById(fileId);&lt;br&gt;        StreamData(r, context);&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; StreamData(IDataReader r, HttpContext context)&lt;br&gt;{&lt;br&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (r.Read())&lt;br&gt;    {&lt;br&gt;        DataFileItem dfi = &lt;span class="kwrd"&gt;new&lt;/span&gt; DataFileItem();&lt;br&gt;        dfi.Length = (r[&lt;span class="str"&gt;"length"&lt;/span&gt;] &lt;span class="kwrd"&gt;is&lt;/span&gt; DBNull) ? &lt;br&gt;                    -1 : (&lt;span class="kwrd"&gt;int&lt;/span&gt;)r[&lt;span class="str"&gt;"length"&lt;/span&gt;];&lt;br&gt;        dfi.MimeType = (r[&lt;span class="str"&gt;"mimeType"&lt;/span&gt;] &lt;span class="kwrd"&gt;is&lt;/span&gt; DBNull) ? &lt;br&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : (&lt;span class="kwrd"&gt;string&lt;/span&gt;)r[&lt;span class="str"&gt;"mimeType"&lt;/span&gt;];&lt;br&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (dfi.MimeType != &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty)&lt;br&gt;            context.Response.ContentType = dfi.MimeType;&lt;br&gt;        dfi.FileName = (r[&lt;span class="str"&gt;"fileName"&lt;/span&gt;] &lt;span class="kwrd"&gt;is&lt;/span&gt; DBNull) ? &lt;br&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : (&lt;span class="kwrd"&gt;string&lt;/span&gt;)r[&lt;span class="str"&gt;"fileName"&lt;/span&gt;];&lt;br&gt;        dfi.Extention = (r[&lt;span class="str"&gt;"extention"&lt;/span&gt;] &lt;span class="kwrd"&gt;is&lt;/span&gt; DBNull) ? &lt;br&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt;.Empty : (&lt;span class="kwrd"&gt;string&lt;/span&gt;)r[&lt;span class="str"&gt;"extention"&lt;/span&gt;];&lt;br&gt;        context.Response.AddHeader(&lt;span class="str"&gt;"Content-Disposition"&lt;/span&gt;, &lt;br&gt;    &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"inline;filename={0}{1}"&lt;/span&gt;, &lt;br&gt;        dfi.FileName, dfi.Extention));&lt;br&gt;        context.Response.AddHeader(&lt;span class="str"&gt;"Content-Length"&lt;/span&gt;, &lt;br&gt;        dfi.Length.ToString());&lt;br&gt;        &lt;span class="kwrd"&gt;int&lt;/span&gt; dataOrdinal = r.GetOrdinal(&lt;span class="str"&gt;"data"&lt;/span&gt;);&lt;br&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!(r[dataOrdinal] &lt;span class="kwrd"&gt;is&lt;/span&gt; DBNull))&lt;br&gt;            StreamByteArrayInChunks(r, dataOrdinal, context);&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; StreamByteArrayInChunks(IDataReader r, &lt;span class="kwrd"&gt;int&lt;/span&gt; ordinal, &lt;br&gt;        HttpContext context)&lt;br&gt;{&lt;br&gt;&lt;span class="rem"&gt;//102400 is 100kb at a time buffer&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] buffer = &lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;byte&lt;/span&gt;[102400];&lt;br&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; index = 0;&lt;br&gt;    &lt;span class="kwrd"&gt;while&lt;/span&gt; (&lt;span class="kwrd"&gt;true&lt;/span&gt;)&lt;br&gt;    {&lt;br&gt;        &lt;span class="kwrd"&gt;long&lt;/span&gt; count = r.GetBytes(ordinal,&lt;br&gt;           index, buffer, 0, buffer.Length);&lt;br&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (count == 0)&lt;br&gt;        {&lt;br&gt;            &lt;span class="kwrd"&gt;break&lt;/span&gt;;&lt;br&gt;        }&lt;br&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br&gt;        {&lt;br&gt;            index = index + (&lt;span class="kwrd"&gt;int&lt;/span&gt;)count;&lt;br&gt;            context.Response.BinaryWrite(buffer);&lt;br&gt;            context.Response.Flush();&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;    &lt;span class="rem"&gt;//closes datareader + underlying db connection&lt;/span&gt;&lt;br&gt;    r.Close();&lt;br&gt;}&lt;br&gt;&lt;span class="rem"&gt;// Override the IsReusable property.&lt;/span&gt;&lt;br&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; IsReusable&lt;br&gt;{&lt;br&gt;    get { &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;; }&lt;br&gt;}&lt;br&gt;}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;A few things i will explain quickly from the above code is how we retrieve an IDataReader from our DAL instead of retrieving a stream. The reason is i want to retrieve the filestream in chunks from the DataReader and every chunk i read from the database, i want to write it out to the client, as i receive the chunks without storing them in memory on my webserver where my application resides. &lt;br&gt;&lt;br&gt;Another thing you may want to notice is the usage of the Http Header Content-Disposition and Content-Length ; basically, it was important for me to flush out the file with the original filename when the user choses to save the file and Content-Disposition helped there. Whereas Content-Length helped ensure the filesize on the receiving end (the client) since without it i was getting errors unzipping a file for example where winzip complained that the file was corrupt :-)&lt;br&gt;&lt;br&gt;So that's pretty much it. And oh, the method in my DAL that returns the IDataReader follows : &lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; IDataReader GetFileById(&lt;span class="kwrd"&gt;int&lt;/span&gt; fileId)&lt;br&gt;{&lt;br&gt;    SqlConnection myConnection = GetSqlConnection();&lt;br&gt;    myConnection.Open();&lt;br&gt;    SqlCommand cmd = &lt;span class="kwrd"&gt;new&lt;/span&gt; SqlCommand(DbOwner + &lt;br&gt;            &lt;span class="str"&gt;".DataFile_GetFileById"&lt;/span&gt;, myConnection);&lt;br&gt;    cmd.CommandType = CommandType.StoredProcedure;&lt;br&gt;    cmd.Parameters.Add(&lt;span class="str"&gt;"@fileId"&lt;/span&gt;, &lt;br&gt;            SqlDbType.Int, 4).Value = fileId;&lt;br&gt;    SqlDataReader r = cmd.ExecuteReader(&lt;br&gt;                    CommandBehavior.CloseConnection);&lt;br&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; r;&lt;br&gt;}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;With that i think we have succeeded in conserving resources on both our database server and our Web server. One last thing, when you got this all working, experiment by changing the buffer size and regulate it to the write speed that is acceptable as per your standards. Basically from my tests on my dev machine, i was getting a download speed of 500KB - 517KB/sec with a buffer size of 100kb (102400 bytes). While setting the same buffer size to 10kb (10240bytes), i was getting a download speed of 50KB - 60KB/sec ; &lt;br&gt;&lt;br&gt;These tests are ofcourse based on what i see as i request a file handled through my custom httphandler above. These values are more or less the same i reckon when streaming the same data to sql server in chunks or a good approximation, so use that as a starting point to regulate the desired speed/latency required by your app based on how much resources your webserver/database server has. Normally, uploads are usually restricted to a certain amount by most ISP's so it means you can set a much smaller chunk size when streaming from your application to sql server. And increase the chunk size when streaming from your webserver to the client (since your requesting clients download speeds are significantly high). It will also depend on the bandwidth availability of your webserver and other factors ofcourse, but that's off topic.&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&lt;span style="color: red; font-weight: bold;"&gt;Update 23&amp;nbsp; september&amp;nbsp; 2008 :&lt;/span&gt; &lt;br&gt;
One last thing i forgot to mention but my friend &lt;a href="http://www.filip.duyck.org/"&gt;filip duyck&lt;/a&gt; brought up is that now since we are sending the data in chunks to sql server (whilst reusing the same connection), it's still additional hits to our database server. So consider that too while you evaluate how big you want your chunks to be.
&lt;/p&gt;
&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6638302" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/alessandro/archive/tags/BLOB/default.aspx">BLOB</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/SQL+SERVER/default.aspx">SQL SERVER</category></item><item><title>Automatically reload reCAPTCHA when postingback via a partial refresh (UpdatePanel)</title><link>http://weblogs.asp.net/alessandro/archive/2008/09/09/automatically-reload-recaptcha-when-postingback-via-a-partial-refresh-updatepanel.aspx</link><pubDate>Tue, 09 Sep 2008 13:03:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6612983</guid><dc:creator>alessandro</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/alessandro/rsscomments.aspx?PostID=6612983</wfw:commentRss><comments>http://weblogs.asp.net/alessandro/archive/2008/09/09/automatically-reload-recaptcha-when-postingback-via-a-partial-refresh-updatepanel.aspx#comments</comments><description>
&lt;p&gt;So, today, i wanted to use reCAPTCHA. Since this is an online service I was a bit skeptical at first with regard to downtime. However their faq states the following :&lt;/p&gt;

&lt;blockquote&gt;reCAPTCHA has distributed locations and multiple servers.&lt;br&gt;&lt;/blockquote&gt;

&lt;p&gt;&amp;nbsp;With that, we know that the service should be available pretty much all the time. And honestly, if it's good enough to service facebook's massive user base, it's good enough for me. Fact is, many people are already familiar with the service and know what to expect and how to proceed. However, the deciding factor was the noble cause of this project. Basically for every captcha that is deciphered, you are actually helping decode a word in a book that was digitized for the public domain by volunteers using OCR(optical character reconigition). Sometimes there are a few words that an OCR cannot read and these are the words presented in the catpcha. So while fighting spam, you are actually helping digitize books. Brilliant! I was sold :P:P&lt;br&gt;&lt;br&gt;If your looking to using this captcha service, then, after signing up to the service on their site &lt;a href="http://www.reCaptcha.com" title="stop spam - read books" mce_href="http://www.reCaptcha.com"&gt;ReCAPTCHA&lt;/a&gt; , you shall be provided with a public/private key to access the service. And this is all you need, since they already have a custom web control that you can insert into your asp.net pages to communicate with their service and consume the captcha. You can inform yourself more about how to consume it from your webform pages here : &lt;a href="http://recaptcha.net/plugins/aspnet/" title="stop spam - read books" mce_href="http://recaptcha.net/plugins/aspnet/"&gt;reCAPTCHA AND ASP.NET&lt;/a&gt;&lt;br&gt;&lt;br&gt;Now, while this is all working nicely, getting it to play nice with the UpdatePanel might be difficult for some. I say that because i have read a few articles online with workarounds, when there was no need. So the goal here is to have the captcha automatically refresh itself, if the captcha words submitted were wrong. So lets see how to do just that : &lt;br&gt;&lt;br&gt;First, what you want to do is make sure that the UpdateMode for the updatepanel is set to conditional. This means, you are responsible for calling update on the updatepanel manually. We want to make this manual because if the captcha is invalid, then you do not want the updatepanel containing the captcha to refresh(this will only make recaptcha dissappear). Instead, we add a second updatepanel. Code speaks a thousand words, so lets take a look at functional code : &lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt; &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptManager&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="ScriptManager1"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptManager&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:UpdatePanel&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="UpdatePanel1"&lt;/span&gt; &lt;span class="attr"&gt;ChildrenAsTriggers&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;br&gt;&lt;span class="attr"&gt;UpdateMode&lt;/span&gt;&lt;span class="kwrd"&gt;="Conditional"&lt;/span&gt;&lt;br&gt;        &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ContentTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:TextBox&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="TextBoxComment"&lt;/span&gt; &lt;span class="attr"&gt;TextMode&lt;/span&gt;&lt;span class="kwrd"&gt;="MultiLine"&lt;/span&gt; &lt;span class="attr"&gt;Rows&lt;/span&gt;&lt;span class="kwrd"&gt;="5"&lt;/span&gt;&lt;br&gt; &lt;span class="attr"&gt;Columns&lt;/span&gt;&lt;span class="kwrd"&gt;="35"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:TextBox&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;recaptcha:RecaptchaControl&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="recaptcha1"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;br&gt;&lt;span class="attr"&gt;Theme&lt;/span&gt;&lt;span class="kwrd"&gt;="red"&lt;/span&gt; &lt;span class="attr"&gt;PublicKey&lt;/span&gt;&lt;span class="kwrd"&gt;="6LcBAAAAAAAAAKtzVYRsIgOAAvCFge3iiMtf6hI9"&lt;/span&gt;&lt;br&gt;                &lt;span class="attr"&gt;PrivateKey&lt;/span&gt;&lt;span class="kwrd"&gt;="6LcBAAAAAAAAACQnFb_BI5tX7OxqC-C5RtROzx-S"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br&gt;            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:UpdatePanel&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="UpdatePanel2"&lt;/span&gt; &lt;br&gt;&lt;span class="attr"&gt;ChildrenAsTriggers&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;span class="attr"&gt;UpdateMode&lt;/span&gt;&lt;span class="kwrd"&gt;="Conditional"&lt;/span&gt;&lt;br&gt;                &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ContentTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;                    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Label&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="labelError"&lt;/span&gt; &lt;br&gt;&lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;EnableViewState&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br&gt;                &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ContentTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:UpdatePanel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Button&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="btnSubmit"&lt;/span&gt; &lt;span class="attr"&gt;ValidationGroup&lt;/span&gt;&lt;span class="kwrd"&gt;="GroupName"&lt;/span&gt; &lt;br&gt;&lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="Submit"&lt;/span&gt; &lt;span class="attr"&gt;OnClick&lt;/span&gt;&lt;span class="kwrd"&gt;="btnSubmit_Click"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ContentTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:UpdatePanel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;As you can note from the code above, we have two updatepanels. The second updatepanel contains a label to tell the user that the text they submitted is wrong. This is the only updatepanel we want to refresh when the captcha submitted is invalid. &lt;br&gt;&lt;br&gt;Now the minimum c# code to do our bidding :&amp;nbsp;&lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; btnSubmit_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs args)&lt;br&gt;    {&lt;br&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!recaptcha1.IsValid)&lt;br&gt;        {&lt;br&gt;            labelError.Text = &lt;span class="str"&gt;"Incorrect, try again!"&lt;/span&gt;;&lt;br&gt;            labelError.ForeColor = System.Drawing.Color.Red;&lt;br&gt;            &lt;span class="rem"&gt;//Reload recaptcha&lt;/span&gt;&lt;br&gt;            ScriptManager.RegisterClientScriptBlock(&lt;span class="kwrd"&gt;this&lt;/span&gt;.Page, &lt;br&gt;        &lt;span class="kwrd"&gt;this&lt;/span&gt;.Page.GetType(),  &lt;span class="str"&gt;"whatever1"&lt;/span&gt;, &lt;br&gt;            &lt;span class="str"&gt;"Recaptcha.reload();"&lt;/span&gt;, &lt;span class="kwrd"&gt;true&lt;/span&gt;);&lt;br&gt;            UpdatePanel2.Update();&lt;br&gt;        }&lt;br&gt;    }&lt;/pre&gt;
&lt;p&gt;As you can note from above, the main code of interest here is the code we are registering via the ScriptManager, specifically -&amp;gt; "Recaptcha.reload(); what this will do is reload the captcha on the clientside when the second updatepanel refreshes whilst display an error message to our clients telling them to retry the captcha. I would love to make this article longer than it already is, however that's about it :-)&lt;/p&gt;

&lt;p&gt;Screen shots of what it looks like before we submit and what it looks like after below :&lt;br&gt;&lt;/p&gt;

&lt;p&gt;&amp;nbsp;&lt;img src="http://weblogs.asp.net/blogs/alessandro/recaptcha-before.gif" mce_src="http://weblogs.asp.net/blogs/alessandro/recaptcha-before.gif"&gt;&lt;/p&gt;

&lt;p&gt;After : note how the captcha is successfully reloaded via a partial postback. &lt;/p&gt;

&lt;p&gt;&lt;img src="http://weblogs.asp.net/blogs/alessandro/recaptcha-after.gif" mce_src="http://weblogs.asp.net/blogs/alessandro/recaptcha-after.gif"&gt;&lt;/p&gt;

&lt;p style="color: red; font-weight: bold;"&gt;Update 26-september-2008 : The full source to the example code i have used throughout this posting : &lt;/p&gt;
&lt;!-- code formatted by http://manoli.net/csharpformat/ --&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: Consolas, "Courier New", Courier, Monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
&lt;/style&gt;
&lt;pre class="csharpcode"&gt;&lt;span class="asp"&gt;&amp;lt;%@ Page Language="C#" %&amp;gt;&lt;/span&gt;
&lt;span class="asp"&gt;&amp;lt;%@ Register TagPrefix="recaptcha" 
Namespace="Recaptcha" Assembly="Recaptcha" %&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;!&lt;/span&gt;&lt;span class="html"&gt;DOCTYPE&lt;/span&gt; &lt;span class="attr"&gt;html&lt;/span&gt; &lt;span class="attr"&gt;PUBLIC&lt;/span&gt; &lt;span class="kwrd"&gt;"-//W3C//DTD XHTML 1.0 Transitional//EN"&lt;/span&gt; 
&lt;span class="kwrd"&gt;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;void&lt;/span&gt; btnSubmit_Click(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs args)
{
    &lt;span class="kwrd"&gt;if&lt;/span&gt; (!recaptcha1.IsValid)
    {
        labelError.Text = &lt;span class="str"&gt;"Incorrect, try again!"&lt;/span&gt;;
        labelError.ForeColor = System.Drawing.Color.Red;
        &lt;span class="rem"&gt;//Reload recaptcha&lt;/span&gt;
        ScriptManager.RegisterClientScriptBlock(&lt;span class="kwrd"&gt;this&lt;/span&gt;.Page,
    &lt;span class="kwrd"&gt;this&lt;/span&gt;.Page.GetType(), &lt;span class="str"&gt;"whatever1"&lt;/span&gt;,
        &lt;span class="str"&gt;"Recaptcha.reload();"&lt;/span&gt;, &lt;span class="kwrd"&gt;true&lt;/span&gt;);
        UpdatePanel2.Update();
    }
}
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;script&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt; &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;="http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Untitled Page&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;title&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;head&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="Form1"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptManager&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="ScriptManager1"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:ScriptManager&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:UpdatePanel&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="UpdatePanel1"&lt;/span&gt; &lt;span class="attr"&gt;ChildrenAsTriggers&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; 
&lt;span class="attr"&gt;UpdateMode&lt;/span&gt;&lt;span class="kwrd"&gt;="Conditional"&lt;/span&gt;
    &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ContentTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:TextBox&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="TextBoxComment"&lt;/span&gt; &lt;span class="attr"&gt;TextMode&lt;/span&gt;&lt;span class="kwrd"&gt;="MultiLine"&lt;/span&gt; &lt;span class="attr"&gt;Rows&lt;/span&gt;&lt;span class="kwrd"&gt;="5"&lt;/span&gt;
&lt;span class="attr"&gt;Columns&lt;/span&gt;&lt;span class="kwrd"&gt;="35"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:TextBox&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;recaptcha:RecaptchaControl&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="recaptcha1"&lt;/span&gt; &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; 
&lt;span class="attr"&gt;Theme&lt;/span&gt;&lt;span class="kwrd"&gt;="red"&lt;/span&gt; &lt;span class="attr"&gt;PublicKey&lt;/span&gt;&lt;span class="kwrd"&gt;="6LcBAAAAAAAAAKtzVYRsIgOAAvCFge3iiMtf6hI9"&lt;/span&gt;
            &lt;span class="attr"&gt;PrivateKey&lt;/span&gt;&lt;span class="kwrd"&gt;="6LcBAAAAAAAAACQnFb_BI5tX7OxqC-C5RtROzx-S"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:UpdatePanel&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="UpdatePanel2"&lt;/span&gt; 
&lt;span class="attr"&gt;ChildrenAsTriggers&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;span class="attr"&gt;UpdateMode&lt;/span&gt;&lt;span class="kwrd"&gt;="Conditional"&lt;/span&gt;
            &lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;ContentTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Label&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="labelError"&lt;/span&gt; 
&lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;EnableViewState&lt;/span&gt;&lt;span class="kwrd"&gt;="false"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ContentTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:UpdatePanel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;asp:Button&lt;/span&gt; &lt;span class="attr"&gt;ID&lt;/span&gt;&lt;span class="kwrd"&gt;="btnSubmit"&lt;/span&gt; &lt;span class="attr"&gt;ValidationGroup&lt;/span&gt;&lt;span class="kwrd"&gt;="GroupName"&lt;/span&gt; 
&lt;span class="attr"&gt;runat&lt;/span&gt;&lt;span class="kwrd"&gt;="server"&lt;/span&gt; &lt;span class="attr"&gt;Text&lt;/span&gt;&lt;span class="kwrd"&gt;="Submit"&lt;/span&gt; &lt;span class="attr"&gt;OnClick&lt;/span&gt;&lt;span class="kwrd"&gt;="btnSubmit_Click"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;ContentTemplate&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;asp:UpdatePanel&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;form&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;body&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;html&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6612983" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/alessandro/archive/tags/UpdatePanel/default.aspx">UpdatePanel</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/Ajax/default.aspx">Ajax</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/reCaptcha/default.aspx">reCaptcha</category></item><item><title>Part 2 : Building and binding hierarchical data from the database to the ASP.NET Navigation Controls </title><link>http://weblogs.asp.net/alessandro/archive/2008/03/01/part-2-building-and-binding-hierarchical-data-from-the-database-to-the-asp-net-navigation-controls.aspx</link><pubDate>Sat, 01 Mar 2008 16:14:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:5896556</guid><dc:creator>alessandro</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/alessandro/rsscomments.aspx?PostID=5896556</wfw:commentRss><comments>http://weblogs.asp.net/alessandro/archive/2008/03/01/part-2-building-and-binding-hierarchical-data-from-the-database-to-the-asp-net-navigation-controls.aspx#comments</comments><description>&lt;P mce_keep="true"&gt;&lt;A class="" href="http://weblogs.asp.net/alessandro/archive/2008/02/20/building-and-binding-hierarchical-data-from-the-database-to-the-asp-net-navigation-controls.aspx" mce_href="http://weblogs.asp.net/alessandro/archive/2008/02/20/building-and-binding-hierarchical-data-from-the-database-to-the-asp-net-navigation-controls.aspx"&gt;Around last week&lt;/A&gt;, I wrote about how we can make use of, some of the databinding capabilities of controls, that can bind to hierarchical data like the TreeView. While I covered pretty much everything, the data i was binding to was not deeply nested. Instead the data we were consuming was just 3 levels deep and that was that. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Today, we will be binding to a hierarchical datasource whose nesting structure is not known and can go as deep as it wants. Here, also SQL servers&amp;nbsp;XML capabilities seem to come short since it does not support recursions. so&amp;nbsp;if our data had this kind of deep nesting, SQL Servers FOR XML queries are not helping out much and we'd need to combine XSLT to our FOR XML Query. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Because of that, and since we end up using XSL for the transformation anyway, i'm going to be using the Dataset/XSLT approach I discussed in my previous post.&lt;/P&gt;
&lt;P mce_keep="true"&gt;First, lets create a "pages" table in Sql server with the following schema as you can see in the screen shot below :&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://weblogs.asp.net/blogs/alessandro/table-schema.gif" mce_src="http://weblogs.asp.net/blogs/alessandro/table-schema.gif"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;As you can note from above, we have a parentId field which is a self related field, related to the pageId in the same table. I personally prefer to move this field out to a junction table but each approach has it's pro's and con's, and this is simpler and serves our purpose :-)&lt;/P&gt;
&lt;P mce_keep="true"&gt;Now, let's fill it with sample data, as you can note in the screenshot below :&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://weblogs.asp.net/blogs/alessandro/Menu-Data.gif" mce_src="http://weblogs.asp.net/blogs/alessandro/Menu-Data.gif"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;ohh perfect. Now it's time to put together some c# code : &lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;protected&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; Page_Load(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;object&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; sender, EventArgs e)
    {
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;!&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;IsPostBack)
            XmlDataSource1.Data &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; GetHierarchicalData();
    }
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; GetHierarchicalData()
    {
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; queryString &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;SELECT pageId, pageDisplayName, parentId FROM pages;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;
        DataSet ds &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; DataSet(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;Pages&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;);
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; connectionString &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; ConfigurationManager.
        ConnectionStrings[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;LocalSqlServer&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;].ConnectionString;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (SqlConnection connection &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; SqlConnection(
                   connectionString))
        {
            SqlDataAdapter adapter &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; SqlDataAdapter();
            adapter.SelectCommand &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; SqlCommand(
                queryString, connection);
            adapter.Fill(ds);

            ds.Tables[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;0&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;].TableName &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;PageItem&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;//&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt; relate our tables&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;            DataRelation dr &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; DataRelation(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;FK_pageId_parentId&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, 
            ds.Tables[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;PageItem&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;].Columns[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;pageId&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;],
                        ds.Tables[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;PageItem&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;].Columns[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;parentId&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;]);
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;//&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt; we'd like the page items nested within 
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;//&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt; each node for every child page.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;            dr.Nested &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;true&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;
            ds.Relations.Add(dr);
        }
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; ds.GetXml();
    }&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;The xml returned by our dataset looks like this : &lt;A class="" href="http://weblogs.asp.net/blogs/alessandro/menuxml.txt" mce_href="http://weblogs.asp.net/blogs/alessandro/menuxml.txt"&gt;Dataset generated XML&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Notice how every pageId that had a corresponding parentId was nested within it's parent, forming a hiearchical set of data. This is just perfect, all thanks to the dataset's DataRelation capabilities and our setting Nested=true on the DataRelation. This kind of recusive nesting didn't seem supported by SQL Servers FOR XML queries, and if it was, then it's probably trival. I did find a few implicit hints in the documentation that recursive nesting was not supported on SQL Server FOR XML Queries, however i could be wrong (so please do your homework). &lt;/P&gt;
&lt;P mce_keep="true"&gt;Now our XSL file that does the recursion, but it's easier to make the transformation&amp;nbsp;now, because the data is already structured out nicely with the proper hierarchical structure. Only thing missing and why we need to perform transformation is as i explained in the previous post, we need the fields as attributes and not as xml elements. So here is our recursive xslt that does just that : &lt;BR&gt;&lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;?&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff00ff"&gt;xml version="1.0" encoding="utf-8"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;?&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;

&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:stylesheet &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;version&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="1.0"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;
    xmlns:xsl&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="http://www.w3.org/1999/XSL/Transform"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
  &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:output &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;method&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="xml"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
  &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:template &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Menu"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; match&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="/"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Pages"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
      &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:for-each &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Pages/PageItem"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:variable &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="parentId"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="parentId/text()"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;

        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="PageItem"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="pageId"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:value-of &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="pageId/text()"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="pageDisplayName"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:value-of &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="pageDisplayName/text()"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;

          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:call-template &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="processChildren"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
  
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
      &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:for-each&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
   &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
  &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:template&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;&amp;lt;!--&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt; recursive template &lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;--&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
  &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:template &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="processChildren"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:for-each &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="PageItem"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="PageItem"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="pageId"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:value-of &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="pageId/text()"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="pageDisplayName"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:value-of &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="pageDisplayName/text()"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:call-template &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="processChildren"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:for-each&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
  &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:template&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:stylesheet&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;And here is the output of this miraculous transformation : &lt;A class="" href="http://weblogs.asp.net/blogs/alessandro/menuxslt.txt" target=_blank mce_href="http://weblogs.asp.net/blogs/alessandro/menuxslt.txt"&gt;XSL Transformed XML&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Ohhh what beauty :-) and to complete, here is&amp;nbsp;the declarative code to bind our asp.net menu to the XmlDataSource control that consumes this data :&lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;form &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;id&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="form1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="server"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;div&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:Menu &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;ID&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Menu1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; MaximumDynamicDisplayLevels&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="1000"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; 
        Orientation&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Horizontal"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;
         DataSourceID&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="XmlDataSource1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="server"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;DataBindings&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:MenuItemBinding &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;DataMember&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="PageItem"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; 
            TextField&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="pageDisplayName"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; ValueField&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="pageId"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;DataBindings&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:Menu&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:XmlDataSource &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;ID&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="XmlDataSource1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; XPath&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Pages/PageItem"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;
         TransformFile&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="~/MenuTransform.xsl"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="server"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:XmlDataSource&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;div&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;form&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;One gotcha you want to&amp;nbsp;watch out for is the root node showing in the menu. Since we do not want to show the starting node, we&amp;nbsp;explain this to the XmlDataSource nicely&amp;nbsp;by setting an XPath expression : XPath="Pages/PageItem". &lt;/P&gt;
&lt;P mce_keep="true"&gt;And below is our menu, when previewed in the browser. Time to congratulate ourselves on a job well done :-)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://weblogs.asp.net/blogs/alessandro/Menu-Final-Product.gif" mce_src="http://weblogs.asp.net/blogs/alessandro/Menu-Final-Product.gif"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;H1 style="COLOR: red"&gt;Update 21 May 2008&lt;/H1&gt;&lt;SPAN style="COLOR: red"&gt;A note i forgot to mention is that the XmlDataSource control has caching turned on by default. So in case you made a change in your xslt file and didn't see the change occuring, then you know it's using a cached copy. So make sure you disable caching during development.&lt;/SPAN&gt; &lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5896556" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/alessandro/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/XML/default.aspx">XML</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/XSLT/default.aspx">XSLT</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/Hierarchical+data/default.aspx">Hierarchical data</category></item><item><title>Building and binding hierarchical data from the database to the ASP.NET Navigation Controls</title><link>http://weblogs.asp.net/alessandro/archive/2008/02/20/building-and-binding-hierarchical-data-from-the-database-to-the-asp-net-navigation-controls.aspx</link><pubDate>Wed, 20 Feb 2008 21:30:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:5830683</guid><dc:creator>alessandro</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/alessandro/rsscomments.aspx?PostID=5830683</wfw:commentRss><comments>http://weblogs.asp.net/alessandro/archive/2008/02/20/building-and-binding-hierarchical-data-from-the-database-to-the-asp-net-navigation-controls.aspx#comments</comments><description>&lt;P mce_keep="true"&gt;If we need to bind our navigations controls to hierarchical data we define manually ourselves in an xml file, this is easy as pie. However, things can get rather complicated or not so obvious when we need to generate this data from a database. First off, what can we use that is already provided to us for binding hierarchical data to our navigation controls in ASP.NET ? &lt;/P&gt;
&lt;P mce_keep="true"&gt;The already out of the box approach and ideal solution is to use the XmlDataSource control. This is quite a flexible datasource control since it not only enables us to define the path to our xml file containing the structure we need but also it allows us to define xml data to it via it's "Data" property. As you may have already guessed, because our data is going to be retrieved from our database, this is the property we shall be using :-)&lt;/P&gt;
&lt;P mce_keep="true"&gt;But first let's look at a sample data structure we may have in our database. I'm using the classic Northwind database. Let's imagine we want to display products grouped by category. So in short, for every category node, we want to show products under it. Following is a screenshot of the categories and products table and how they relate : &lt;BR&gt;&lt;/P&gt;
&lt;P&gt;&lt;IMG style="WIDTH: 300px; HEIGHT: 487px" height=487 src="http://weblogs.asp.net/blogs/alessandro/categories_products.gif" width=300 mce_src="http://weblogs.asp.net/blogs/alessandro/categories_products.gif"&gt; &lt;/P&gt;
&lt;P&gt;The most common thing i see done is to manually loop through the records returned, create TreeNodes again manually and keep adding till you've build the TreeView or Menu, etc. Nothing wrong with this approach, since it works, however it is quite lengthy in code and time consuming too. &lt;/P&gt;
&lt;P&gt;But that's not the main reason why I'm writing this article. The main reason is that all these navigation controls in ASP.NET know how to consume hierarchical data. Once they have this, they know how to render themselves without you needing to do anything special. This is indeed some powerful databinding support that we miss out on when we go the manual approach. Here i am going to list two different approaches :&lt;/P&gt;
&lt;P mce_keep="true"&gt;1) DataSet and XSL Transformations, which while being clean and gives a more declarative model to work with (XSLT) versus the manual c# code approach. &lt;/P&gt;
&lt;P mce_keep="true"&gt;2)The second approach uses SqlServer's XML generating capabilities which allows us to skip XSLT and the dataset all together :-) &lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;H1&gt;DataSet and XSL Transformation approach:&lt;/H1&gt;
&lt;P&gt;---------------------------------------------------&lt;BR&gt;Note below how our select statements retrieves all categories, while the second statement retrieves all products. We then relate both these tables using a key field they have in common "CategoryID". We also use a dataset since it's providing us a lot of functionality like relating the tables after data retrieval and representing the data in xml.&lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; GetHierarchicalData()
    {
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; queryString &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;SELECT CategoryID, CategoryName, Description FROM Categories AS Category;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;
        queryString &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;+=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;SELECT ProductID, CategoryID, ProductName FROM Products AS Product&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;
        DataSet ds &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; DataSet(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;TreeView&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;);
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; connectionString &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; ConfigurationManager
.ConnectionStrings[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;LocalSqlServer&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;].ConnectionString;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (SqlConnection connection &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; SqlConnection(
                   connectionString))
        {
            SqlDataAdapter adapter &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; SqlDataAdapter();
            adapter.SelectCommand &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; SqlCommand(
                queryString, connection);
            adapter.Fill(ds);

            ds.Tables[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;0&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;].TableName &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;Category&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;
            ds.Tables[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;1&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;].TableName &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;Product&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;//&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt; relate our tables&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;            DataRelation dr &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; DataRelation(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;FK_Products_Categories&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;,
ds.Tables[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;Category&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;].Columns[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;categoryId&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;],
                                ds.Tables[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;Product&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;].Columns[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;categoryId&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;]);
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;//&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt; we'd like the products nested within 
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;//&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt; each Category Node. Thank you :-)&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;            dr.Nested &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;true&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;
            ds.Relations.Add(dr);
        }
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; ds.GetXml();
    }&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;A small sample output of the generated xml we get by calling dataset's GetXml() method is here -&amp;gt;&amp;nbsp; &lt;A href="http://weblogs.asp.net/blogs/alessandro/DataSetGenerated.txt"&gt;DataSet Generated XML&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;As you can see, we have our rootnode "TreeView", then a childNode "Category", which in turn will contain every product node within it that belongs to this category. This nesting was established when we created a relationship btw the Categories table and the Products table using a DataRelation, where we set Nested = true; on it. Enabling the Nested property did just what the name says. It nested all our products within it's specific Category node. &lt;/P&gt;
&lt;P&gt;While this is great, it does not help much with the TreeView control. Notice how every field our select statement returned is now an xml node and the data for the field is contained as inner text in our node. The TreeNodeBinding instead expects the fields to be contained as attributes, and the data as attribute values. Following screenshot is what we get when we run our TreeView bound to XmlDatasource &lt;BR&gt;&lt;IMG src="http://weblogs.asp.net/blogs/alessandro/TreeView-Without-Transforma.gif" mce_src="http://weblogs.asp.net/blogs/alessandro/TreeView-Without-Transforma.gif"&gt;&lt;/P&gt;
&lt;P&gt;Definately, not what we are after. This is because the datasets GetXml method returned :&lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Category&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;CategoryID&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;1&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;CategoryID&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;CategoryName&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;Beverages&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;CategoryName&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Description&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;Soft drinks, coffees, teas, beers, and ales&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Description&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;while, what we need instead for the TreeNodeBinding to work is : &lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Category &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;CategoryID&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; CategoryName&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Beverages"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; Description&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Soft drinks, coffees, teas, beers, and ales"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Had we the above xml structure with the fields defined as attributes we could easily create a TreeNodeBinding like this : &lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:TreeNodeBinding &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;Depth&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="2"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; DataMember&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Category"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; TextField&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="CategoryName"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; ValueField&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="CategoryID"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; ToolTipField&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Description"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;So, our next task is to transform our xml to represent fields as attributes and their data as attribute values. We can accomplish this easily using XSL Transformations. By defining some instructions in our XSL file, we can read our XML(what our dataset GetXml method output) and transform it into what the Navigation Controls expect, outputting a totally new XML document.&lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;?&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff00ff"&gt;xml version="1.0" encoding="utf-8"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;?&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:transform &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;version&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="1.0"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;
      xmlns:xsl&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="http://www.w3.org/1999/XSL/Transform"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
  &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:output &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;method&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="xml"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
  &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:template &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;match&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="/"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="TreeView"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
      &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:for-each &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="TreeView/Category"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Category"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="id"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:value-of &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="CategoryID/text()"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="name"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:value-of &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="CategoryName/text()"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="description"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:value-of &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Description/text()"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:for-each &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Product"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Product"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
              &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="id"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:value-of &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="ProductID/text()"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
              &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
              &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="name"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:value-of &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;select&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="ProductName/text()"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
              &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:attribute&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
          &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:for-each&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
      &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:for-each&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:element&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
  &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:template&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;xsl:transform&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;As you can see from the above XSL, we have defined two for-each loops, one that loops through category nodes and the other that loops through product nodes. Very simple but powerful stuff indeed :-)&lt;/P&gt;
&lt;P&gt;The output xml after this transformation is &lt;A href="http://weblogs.asp.net/blogs/alessandro/XSLTransformedXML.txt"&gt;XSL Transformed Xml output&lt;/A&gt;&lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;TreeView&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Category&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
  &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;CategoryName &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;=""&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; id&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;=""&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; description&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;=""&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
  &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Product &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;name&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;=""&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; id&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;=""&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
   ...
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Category&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
...
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;TreeView&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;ohh this is perfect. It was fun using XSL for the transmformation. Now, now, while it was fun, it can be a big pain in the behind if I'd have to do this all over again and again (Fortunately, i don't. Atleast now right now) :P&lt;/P&gt;
&lt;P&gt;So, can we have made this job easier ? Surely. SQL Server and FOR XML Queries to the rescue :-)&lt;/P&gt;
&lt;H1&gt;SQL Server and FOR XML Queries approach :&lt;/H1&gt;--------------------------------------------------- 
&lt;P&gt;Now, what if, instead of having to do all this manual labor, we could get SQL Server to do all the xml generation for us, the way we wanted it ? Very much possible indeed. In effect this does not even need any explainations. Code speaks a thousand words, so here it is, the same xml output but this time we didn't use XSLT, nor did we use a dataset and the code is even more minimized.&lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; GetHierarchicalDataFromSqlServer()
    {
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; xml &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.Empty;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; queryString &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;@"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
                    SELECT Category.categoryName as [name], Category.categoryId as id, 
                                Category.description as description, 
                    Product.productName as name, Product.productId as id
                    FROM categories AS Category 
                    INNER JOIN products AS Product
                    ON Category.categoryId = Product.categoryId
                    ORDER BY Category.categoryId                    
                    FOR XML Auto, ROOT('TreeView')&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;

        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;string&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; connectionString &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; ConfigurationManager.
ConnectionStrings[&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;LocalSqlServer&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;].ConnectionString;

        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;using&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (SqlConnection connection &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; SqlConnection(
                   connectionString))
        {
            SqlCommand SelectCommand &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;new&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; SqlCommand(
                queryString, connection);
            connection.Open();
            XmlReader xr &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; SelectCommand.ExecuteXmlReader();
            xr.MoveToContent();&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;//&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt; move to the root node&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;            xml &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; xr.ReadOuterXml();
        }
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;return&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; xml;
    }
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;The c# code to pass the XML data to our XmlDataSource bound to a treeView : &lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;protected&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; Page_Load(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;object&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; sender, EventArgs e)
    {
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;!&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;IsPostBack)
            XmlDataSource1.Data &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; GetHierarchicalDataFromSqlServer();
    }&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;That's it. No fuss, SQL Server's xml generation capabilities are just outstanding. And here is the declarative code i used to bind this hiearchical data to a treeview&amp;nbsp;: &lt;BR&gt;&lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;form &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;id&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="form1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="server"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;div&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:TreeView &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;ID&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="TreeView1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; DataSourceID&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="XmlDataSource1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="server"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;DataBindings&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
                   &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:TreeNodeBinding &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;Depth&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; DataMember&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Category"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; TextField&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="name"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; ValueField&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="id"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; ToolTipField&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Description"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
                   &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:TreeNodeBinding &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;Depth&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="2"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; DataMember&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="Product"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; TextField&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="name"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; ValueField&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="id"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;/&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;DataBindings&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:TreeView&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;div&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:XmlDataSource &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;ID&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="XmlDataSource1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="server"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:XmlDataSource&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;/&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;form&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;And here below is a screenshot of the treeview rendering itself. Fantastic :-)&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://weblogs.asp.net/blogs/alessandro/TreeView-After-XSLT.gif" mce_src="http://weblogs.asp.net/blogs/alessandro/TreeView-After-XSLT.gif"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;
&lt;H1 style="COLOR: red"&gt;Update 21 May 2008&lt;/H1&gt;&lt;SPAN style="COLOR: red"&gt;A note i forgot to mention is that the XmlDataSource control has caching turned on by default. So in case you made a change in your xslt file and didn't see the change occuring, then you know it's using a cached copy. So make sure you disable caching during development.&lt;/SPAN&gt; &lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5830683" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/alessandro/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/XML/default.aspx">XML</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/XSLT/default.aspx">XSLT</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/Hierarchical+data/default.aspx">Hierarchical data</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/SQL+SERVER+FOR+XML+QUERY/default.aspx">SQL SERVER FOR XML QUERY</category></item><item><title>Customizing the ChangePassword control and removing the required CurrentPassword field</title><link>http://weblogs.asp.net/alessandro/archive/2008/02/15/customizing-the-changepassword-control-and-removing-the-required-currentpassword-field.aspx</link><pubDate>Fri, 15 Feb 2008 15:47:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:5794715</guid><dc:creator>alessandro</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/alessandro/rsscomments.aspx?PostID=5794715</wfw:commentRss><comments>http://weblogs.asp.net/alessandro/archive/2008/02/15/customizing-the-changepassword-control-and-removing-the-required-currentpassword-field.aspx#comments</comments><description>&lt;P mce_keep="true"&gt;It's very rare that what is already provided in asp.net under the Login controls fits my requirements out of the box without some tweaking. Not that any of these controls offer anything specialized, but certainly they are a big time saver if we can re-utilize their functionality. &lt;/P&gt;
&lt;P mce_keep="true"&gt;First some background as to why i personally want to customize the ChangePassword control to suit my needs : &lt;/P&gt;
&lt;P mce_keep="true"&gt;Password recovery is what i was after today, however i have hashed passwords, and recovery is impossible. If the user lost their password, then there is no way for me to know what their password is and send it back in clear text. &lt;/P&gt;
&lt;P mce_keep="true"&gt;The ideal solution is to reset the password, however the autogenerated password is quite ugly and quite hard to remember. What I've decided to do is send the email during password recovery, but as part of the email, instead of telling the user their old password(which i can't) , I'm instead going to ask them to click on a tokenized link that will guarantee to me that they are indeed the ones that requested the password, send them to the page where they can provide a new password, in the background i'd be autogenerating a password first ofcourse, then updating the password with their new password because the MembershipUser.ChangePassword(oldPassword, newPassword) method requires Old password as one of it's two parameters.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;BR&gt;This password change step, i'd like to be done using the ChangePassword control, however to my big surprise CurrentPassword Field is a required field that i cannot remove. This is also a field that I do not want asked for during the password change request(since my user has forgotten their password and are now going to provide their new pasword).&lt;/P&gt;
&lt;P mce_keep="true"&gt;There is ofcourse no property or method in this control that removes the CurrentPassword field requirement, below is a screenshot of the ChangePassword control in designview, as you can note, the highlighted field is the CurrentPassword field i do not want. &lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG src="http://weblogs.asp.net/blogs/alessandro/ChangePassword1.gif" mce_src="http://weblogs.asp.net/blogs/alessandro/ChangePassword1.gif"&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;I've done a quick look on google and in the asp.net/forums and didn't find anybody providing any proper solutions either,&amp;nbsp;mostly vague replies : &lt;A href="http://forums.asp.net/p/1189347/2038354.aspx"&gt;http://forums.asp.net/p/1189347/2038354.aspx&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;As you can read from the posts there, the issue seems to be two things which&amp;nbsp;were also my same issues&amp;nbsp;: &lt;BR&gt;1) Remove the current password label/TextBox &lt;BR&gt;2) Pass the new resetpassword to CurrentPassword Property which by the way is a getter only and not settable (SAD SAD)&lt;/P&gt;
&lt;P mce_keep="true"&gt;Both of these things are not supported in this control. So let's quickly fix requirement 1 and there are a couple of ways to fix this :&amp;nbsp;&amp;nbsp;&lt;BR&gt;a) You have to define a custom&amp;nbsp; &amp;lt;ChangePasswordTemplate&amp;gt;. This can be easily done by taking your ChangePassword control into DesignView in Visual studio, right click on the control and select "Convert to template". You can then switch to HtmlView and set the visibility of CurrentPasswordLabel, CurrentPassword and CurrentPasswordRequired controls.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;BR&gt;b) If you prefer to do this in code, then you can find the Label and TextBox for CurrentPassword and set its visiblity to false. Since a is a nobrainer, i'm including a sample code of method (b) : &lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #000000"&gt;Label l &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (Label)changePassword1.ChangePasswordTemplateContainer.
    FindControl(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;CurrentPasswordLabel&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;);
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (l &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;!=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;null&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;)
    l.Visible &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;false&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;

TextBox tb &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (TextBox)changePassword1.ChangePasswordTemplateContainer.
FindControl(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;CurrentPassword&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;);
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (tb &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;!=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;null&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;)
    tb.Visible &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;false&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;

RequiredFieldValidator rfv &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (RequiredFieldValidator)changePassword1.
ChangePasswordTemplateContainer.FindControl(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;CurrentPasswordRequired&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;);
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (rfv &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;!=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;null&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;)
    rfv.Visible &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;false&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;;&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Now that we have the fields we want disabled, let's head onto fix issue 2 : &lt;BR&gt;We can't pass the Autogenerated password to the CurrentPassword Property because its a getter only, however this getter returns the value from our CurrentPassword TextBox, and this job is done immidiately after ChangingPassword event fires. This is good news for us, so we can resolve issue 2 like this : &lt;/P&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;void&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; changePassword1_ChangingPassword(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;object&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; sender, 
    LoginCancelEventArgs e)
{
    changePassword1.UserName &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; user.UserName;
        TextBox currentPassword &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (TextBox)changePassword1.
         ChangePasswordTemplateContainer.FindControl(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;CurrentPassword&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;);
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;if&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (currentPassword &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;!=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;null&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;)
            currentPassword.Text &lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;=&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; user.ResetPassword();
}&lt;/SPAN&gt;&lt;/PRE&gt;
&lt;P&gt;Note that in the above code, user is a reference to a field of type&amp;nbsp;MembershipUser. Ok, that's it. Now we have what were after, look at the screenshot below :&lt;/P&gt;
&lt;P&gt;&lt;IMG src="http://weblogs.asp.net/blogs/alessandro/ChangePassword2.gif" mce_src="http://weblogs.asp.net/blogs/alessandro/ChangePassword2.gif"&gt;&lt;BR&gt;&lt;/P&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=5794715" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/alessandro/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/Login+Controls/default.aspx">Login Controls</category><category domain="http://weblogs.asp.net/alessandro/archive/tags/ChangePassword/default.aspx">ChangePassword</category></item><item><title>Reducing UpdatePanel bloat by utilizing UpdateMode="Conditional" and ChildrenAsTriggers="false"</title><link>http://weblogs.asp.net/alessandro/archive/2008/01/30/reducing-updatepanel-bloat-by-utilizing-updatemode-quot-conditional-quot-and-childrenastriggers-quot-false-quot.aspx</link><pubDate>Wed, 30 Jan 2008 11:41:00 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:5676039</guid><dc:creator>alessandro</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/alessandro/rsscomments.aspx?PostID=5676039</wfw:commentRss><comments>http://weblogs.asp.net/alessandro/archive/2008/01/30/reducing-updatepanel-bloat-by-utilizing-updatemode-quot-conditional-quot-and-childrenastriggers-quot-false-quot.aspx#comments</comments><description>Just the other day, i was playing around with my DataControls nested inside an updatepanel. While this was working well, since everypostback was being done via an ajax callback, the amount of traffic going back and forth was simply way too bloated. It's easy not to notice at first, because everything is working as expected. however imagine a simple situation as the following pseudo code below. Things could be very complex, depending on how many datacontrols you have and the level of nesting. 
&lt;P mce_keep="true"&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:updatepanel &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;id&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="UpdatePanel1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="server"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;ContentTemplate&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;lt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;asp:GridView &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;ID&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="GridView1"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; AutoGenerateSelectButton&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="true"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; 
        runat&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="server"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt; 
        OnSelectedIndexChanged&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;="GridView1_SelectedIndexChanged"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;&amp;gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt