<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7078755</id><updated>2011-04-21T11:58:53.260-07:00</updated><title type='text'>Infinities Loop</title><subtitle type='html'>.NET from a new perspective</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>15</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7078755.post-115459340193057237</id><published>2006-08-03T01:19:00.000-07:00</published><updated>2006-11-09T11:06:25.440-08:00</updated><title type='text'>If you can't beat 'em, work for 'em!</title><content type='html'>Right. I'm happy to say, I've had the privledge of joining the ASP.NET team with Microsoft! As you may imagine, that has kept me busy lately. I have a few comments from readers that I haven't answered yet, but I will get to them, I promise :)&lt;br /&gt;&lt;br /&gt;&lt;p style="color:red"&gt;&lt;br /&gt;This means I'm moving my blog! Please redirect your bookmarks and RSS readers to:&lt;br /&gt;&lt;br /&gt;&lt;a style="color:red" href="http://weblogs.asp.net/infinitiesloop/"&gt;http://weblogs.asp.net/infinitiesloop/&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;I transfered over the ViewState article since it's the most popular. I'll transfer over the rest... eventually.&lt;br /&gt;&lt;br /&gt;I'll maintain this blog for a while. At least until the content is transfered. See you later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-115459340193057237?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://weblogs.asp.net/infinitiesloop/' title='If you can&apos;t beat &apos;em, work for &apos;em!'/><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/115459340193057237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=115459340193057237' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/115459340193057237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/115459340193057237'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2006/08/if-you-cant-beat-em-work-for-em.html' title='If you can&apos;t beat &apos;em, work for &apos;em!'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-115390022666178910</id><published>2006-07-26T00:45:00.000-07:00</published><updated>2006-07-26T00:50:26.663-07:00</updated><title type='text'>TRULY Understanding Viewstate (again)</title><content type='html'>It has come to my attention that many visitors here have found me via a google search related to ViewState or something similar. For example, &lt;a href="http://www.google.com/search?q=understanding+viewstate"&gt;here's a google ranking&lt;/a&gt; one could be proud of! Unfortunately, not all the search results link directly to the article they seek, and it is buried 6 posts back so they don't always find it. If you're interested in my article on understanding the viewstate process, &lt;a href="http://infinitiesloop.blogspot.com/2006/03/truly-understanding-viewstate.html"&gt;this post is for you&lt;/a&gt;. It's received a lot of interesting comments lately, so I think it deserves a little /bump anyway :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-115390022666178910?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://infinitiesloop.blogspot.com/2006/03/truly-understanding-viewstate.html' title='TRULY Understanding Viewstate (again)'/><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/115390022666178910/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=115390022666178910' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/115390022666178910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/115390022666178910'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2006/07/truly-understanding-viewstate-again.html' title='TRULY Understanding Viewstate (again)'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-115194529635396585</id><published>2006-07-03T09:37:00.000-07:00</published><updated>2006-07-04T14:48:57.223-07:00</updated><title type='text'>Bringing ViewState into the Light</title><content type='html'>&lt;a href="http://files.filefront.com/VisibleFieldPageStatePersisterzip/;5215866;;/fileinfo.html" target="_blank"&gt;Download the source&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;YAVA (Yet another ViewState Article). For years now ViewState has remained hidden in the turbulent html source of our documents and applications. ASP.NET puts it there because, well, it isn't pretty. It's pretty ugly really.&lt;br /&gt;&lt;br /&gt;Many &lt;a href="http://www.google.com/search?q=viewstate+viewer" target="_blank"&gt;ViewState Viewers&lt;/a&gt; are available that let you put on Base64 encoded glasses and see what's really in there. But sometimes I just want to have a good idea of what the size of my ViewState is on the various pages of my applications. If its too big, then I'll start &lt;a href="http://infinitiesloop.blogspot.com/2006/03/truly-understanding-viewstate.html?vfpsp" target="_blank"&gt;thinking about optimizing it&lt;/a&gt;, which is when a decoder may come in handy. But to just get a feel for what its size is throughout my application, all I need is to look at the encoded string. But doing a "view source" every time is a pain.&lt;br /&gt;&lt;br /&gt;ASP.NET 2.0 makes it easy to customize how ViewState is persisted. It even comes with two persisters of its own: HiddenFieldPageStatePersister and SessionPageStatePersister. Why not have a &lt;u&gt;Visible&lt;/u&gt;FieldPageStatePersister?&lt;br /&gt;&lt;br /&gt;&lt;div align=center&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/VisibleViewState1.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/400/VisibleViewState1.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br&gt;&lt;i&gt;ViewState in all its glory&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The cool thing about this simple persister is that it isn't just showing you what the ViewState is. The textarea is the field that the ViewState actually lives in. That means it's easy to change the ViewState for the page. Imagine you have a complex page with dozens of input fields on them, and you are trying to test a step in a process that is several steps behind those fields. It would be a pain to have to enter all those fields every time you wanted to debug. With this, you could copy the ViewState of the form at the point you'd like to return back to, and then assuming there were no server-side actions that you depend on having actually occurred, and ViewState is enabled on all the controls you need it for, you will instantly be back in that state.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;B&gt;WARNING:&lt;/B&gt; Do not let this make you think that ViewState is responsible for maintaining the state of posted input fields like TextBoxes and CheckBoxes. It isn't. Well it is, too. ViewState lets TextBoxes and such remember their state even when their value isn't &lt;u&gt;naturally&lt;/u&gt; posted (such as when it's invisible, or people like us cheat the system as in this example). But normally TextBoxes and such remember their state simply because they are input forms, and even without ViewState their value is posted to the server. ViewState just makes it that much smarter at it (and enables things like TextChanged and CheckChanged events). So... if you have ViewState disabled on a TextBox, for example, this little trick won't restore it's state.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Here's an example. On this page, the "Click here!" button changes the label of the page, like so:&lt;br /&gt;&lt;br /&gt;&lt;div align=center&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/VisibleViewState3.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/400/VisibleViewState3.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br&gt;&lt;i&gt;ViewState jumps by 128 bytes here&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;If we copy the text from the "previous" field into the "current" field, a postback occurs automagically, and the form returns to it's previous state.&lt;br /&gt;&lt;br /&gt;&lt;div align=center&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/VisibleViewState2.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/400/VisibleViewState2.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br&gt;&lt;i&gt;Voila!&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;How useful this really is, I'm not sure. There's plenty of room for improvement. For example, it could be extended to track the viewstate on every postback, allowing you to "go back" and "go forward", swapping the state along the way as appropriate. It could also have a built-in ViewState visualizer, that'd be handy. I haven't tested it in all scenarios... like when ViewState encryption is enabled. It definitely won't work if you &lt;a href="http://geekswithblogs.net/azamsharp/archive/2006/06/09/81367.aspx" target="_blank"&gt;limit the size of the ViewState field&lt;/a&gt;. Also, since it's using an actual TextBox control that it adds to the forms control collection, it's possible that code elsewhere on your pages could accidentally manipulate or otherwise disable the control. &lt;br /&gt;&lt;br /&gt;The simplest way to use it is to make your page inherit from the included VisibleViewStatePage class (instead of just Page).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://files.filefront.com/VisibleFieldPageStatePersisterzip/;5215866;;/fileinfo.html" target="_blank"&gt;Download the source (C#) here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Happy coding! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-115194529635396585?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/115194529635396585/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=115194529635396585' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/115194529635396585'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/115194529635396585'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2006/07/bringing-viewstate-into-light.html' title='Bringing ViewState into the Light'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-115087242144492953</id><published>2006-06-20T23:43:00.000-07:00</published><updated>2006-06-30T17:02:17.426-07:00</updated><title type='text'>A drink from the fire hose</title><content type='html'>Just wanted to give thanks to the team behind &lt;a href="http://asp.net" target="_blank"&gt;http://asp.net&lt;/a&gt;. A thanks for selecting my &lt;a href="http://infinitiesloop.blogspot.com/2006/05/atlas-smart-auto-completion.html" target="_blank"&gt;Atlas: Smart Auto Completion&lt;/a&gt; article as an &lt;u&gt;Article of the Day&lt;/u&gt;!&lt;br /&gt;&lt;br /&gt;Just to give you a clue of what that was like from &lt;i&gt;this side of the screen&lt;/i&gt;...&lt;br /&gt;&lt;br /&gt;&lt;div align=center&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/WhatAWeek.0.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/400/WhatAWeek.0.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;Guess when it started?&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Yes, the asp.net site is a veritable fire hose of traffic, and I got to take a small, brief, drink. Alas, by now my article has fallen off the list of articles of the week. And so this is also a thanks to those of you who may be sticking around (you guys are represented by the blue bars) :) It's all the nice comments I've gotten from readers that keeps me going. So definitely stop by often, because I can guarantee you there is more content to come.&lt;br /&gt;&lt;br /&gt;Perhaps plug into my &lt;a href="http://infinitiesloop.blogspot.com/atom.xml" target="_blank"&gt;atom feed&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;See ya soon!&lt;br /&gt;Dave&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-115087242144492953?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/115087242144492953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=115087242144492953' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/115087242144492953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/115087242144492953'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2006/06/drink-from-fire-hose_20.html' title='A drink from the fire hose'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-115026519565384407</id><published>2006-06-13T21:56:00.000-07:00</published><updated>2006-08-06T01:16:45.613-07:00</updated><title type='text'>Join the Dark Side of Visual Studio</title><content type='html'>&lt;span style="color:red"&gt;&lt;b&gt;UPDATE: THIS POST HAS BEEN MOVED TO MY NEW BLOG! Please redirect your bookmarks here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://weblogs.asp.net/infinitiesloop/archive/2006/08/06/Join-the-Dark-Side-of-Visual-Studio.aspx"&gt;http://weblogs.asp.net/infinitiesloop/archive/2006/08/06/Join-the-Dark-Side-of-Visual-Studio.aspx&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Visual Studio is without a doubt a powerful tool. With every iteration, it continues to improve upon itself. But as you happily hack away at all your applications, you are blistfully unaware of it's evil dark side that has been there since the beginning. It's true.&lt;br /&gt;&lt;br /&gt;There are those of us who embrace the dark side. But we are out numbered...&lt;br /&gt;&lt;br /&gt;You see, the dark side isn't how it comes by default. No... it comes all happy and bright and cheery by default, and like good little jedi programmers you accept those defaults. But the dark side is there, hidden away deep within the environment settings, reaching out and corrupting those programmers who are corruptible. Why some are corruptible and some are not is a mystery that may never be solved, but each and every programmer must give pause and consider the benefits it provides.&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/TheDarkSide.0.gif"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/8140/417/400/TheDarkSide.0.png" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I know what you may be thinking. It's hard to read. Are you so sure about that? Lets compare it with the happy cheery default color scheme:&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/TheStatusQuo.gif"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/8140/417/400/TheStatusQuo.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The key difference of course is the pervasive black background color. This is the environment I and many others work in every day. For me, it started way back when I used a Borland C++ IDE that had preset environment color schemes. One was called Twilight, and it looked similar to this. That color scheme was even my inspiration for this blog template (albeit it is only a variation on a standard blogspot theme, I'm ashamed to say).&lt;br /&gt;&lt;br /&gt;Most people who see it for the first time are offended by it... but if you think about it, it really makes sense. It brings balance to the force.&lt;br /&gt;&lt;br /&gt;The default scheme sports a bright white background color with dark text over it. But monitors these days are brighter than ever. You're presumably a programmer, so you've no doubt had those late but productive coding nights, nights that are lit by only the glow of your monitor. The glow is bright enough to light up the room and cast shadows. Not unlike... a light bulb.&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/LightBulb.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/8140/417/400/LightBulb.jpg" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;So there you are, staring straight into a strong light source, looking for the few pixels on it which are &lt;b&gt;&lt;i&gt;not&lt;/i&gt;&lt;/b&gt; illuminated. Can you read the wattage and manufacturer letters on the head a light bulb while it's turned on? Ahhh... but what if the bulb were black, and only the letters on it were illuminated?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellspacing="4"&gt;&lt;tr&gt;&lt;br /&gt;&lt;td align="right"&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/LightBulb.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/8140/417/400/LightBulb.jpg" border="0" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td align="left"&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/LightBulb-Invert.jpg"&gt;&lt;img style="CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/8140/417/400/LightBulb-Invert.jpg" border="0" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;This bulb has no markings, but you'd bet they'd show up nice and bright and easy to read in the right image.&lt;br /&gt;&lt;br /&gt;It seems to me the only reason a black-on-white background is so standard is because the GUI was invented to be an analogy to pen and paper. Paper is white. Your screen doesn't have to be.&lt;br /&gt;&lt;br /&gt;Want to join the dark side? &lt;a href="http://files.filefront.com/TheDarkSidevssettings/;5156342;;/fileinfo.html" target="_blank"&gt;Click here&lt;/a&gt; to download my VS2005 environment settings. Just import them via the Tools-&gt;Import and Export Settings menu. Don't worry. If it doesn't suit you, just revert :)&lt;br /&gt;&lt;br /&gt;If anyone is interested I can export VS2003 settings as well, but it requires an add-in since VS2003 doesn't have an import/export feature built in.&lt;br /&gt;&lt;br /&gt;Happy coding!&lt;br /&gt;&lt;br /&gt;&lt;B&gt;UPDATE 06/19/2006&lt;/B&gt;&lt;br /&gt;&lt;br /&gt;As requested... To enable exporting/importing styles in VS2003 you need an add-in called VSStyler, which you can download here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.gotdotnet.com/workspaces/workspace.aspx?id=722d7817-b935-4faf-9bf7-fe3e84d463af"&gt;VSStyler Add-In for VS2003&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Once you have the add-in, download the dark side style export here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://files.filefront.com/TheDarkSidestyc/;5165885;;/fileinfo.html"&gt;The Dark Side for VS2003&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-115026519565384407?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/115026519565384407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=115026519565384407' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/115026519565384407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/115026519565384407'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2006/06/join-dark-side-of-visual-studio.html' title='Join the Dark Side of Visual Studio'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-114852317110898121</id><published>2006-05-25T18:50:00.000-07:00</published><updated>2006-11-15T17:02:53.953-08:00</updated><title type='text'>Atlas: Smart Auto Completion</title><content type='html'>&lt;h4&gt;&lt;i&gt;Auto Completion without a Web Service&lt;/i&gt;&lt;br&gt;&lt;br /&gt;&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;To get the latest version that works with Beta 2, please visit my new blog:&lt;br /&gt;&lt;a href="http://weblogs.asp.net/infinitiesloop/"&gt;http://weblogs.asp.net/infinitiesloop/&lt;/a&gt;&lt;br /&gt;&lt;/h3&gt;&lt;br /&gt;&lt;br /&gt;If you haven't heard of the &lt;a href="http://atlas.asp.net/Default.aspx" target="_blank"&gt;Atlas&lt;/a&gt; project yet, this article may not be for you. But even then, reading this may give you a clue as to the capabilities of Atlas. To quote the Atlas site,&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;"Atlas" is a free framework for building a new generation of richer, more interactive, highly personalized standards based Web applications.&lt;/blockquote&gt;&lt;br /&gt;One of the innovations Atlas brings to the table is its level of integration with the server side. It is because of this integration that makes it possible for you to take advantage of Atlas' advanced client side features without leaving the comforts of the server side of the world.&lt;br /&gt;&lt;br /&gt;But despite this client/server integration, Atlas is still a truly client side framework, one that can be integrated with any server side back end, not just ASP.NET. Its design must take that into consideration, because everything it does must (and should) be a purely client side game. But if you are definitely using Atlas with ASP.NET, it would be nice if you could rely on deeper integration into the rich asp.net server side world. And that is what this article is all about.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Using the Auto Complete Extender&lt;/h3&gt;&lt;br /&gt;First, lets go over how the built-in stuff works. The built-in Atlas AutoCompleteExtender adds intelligent auto completion behavior to a textbox. Here's how you set one up:&lt;br /&gt;&lt;br /&gt;First thing you need is a script manager:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;atlas:ScriptManager ID="ScriptManager1" runat="server" /&gt;&lt;/pre&gt;&lt;/code&gt;And then place a textbox and attach an AutoCompleteExtender to it:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;asp:TextBox id="txt1" runat="server"/&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;atlas:AutoCompleteExtender id="ext1" runat="server"&gt;&lt;br /&gt;   &amp;lt;atlas:AutoCompleteExtenderProperties Enabled="true"&lt;br /&gt;      ServicePath="SuggestionService.asmx"&lt;br /&gt;      ServiceMethod="GetSuggestions" TargetControlID="txt1" /&gt;&lt;br /&gt;&amp;lt;/atlas:AutoCompleteExtender&gt;&lt;/code&gt;&lt;/pre&gt;The behavior uses the given ServicePath and ServiceMethod properties to call the specified Web Service whenever suggestions are needed. The web service, written by you, can query a database or do whatever it needs to do in order to calculate the suggestions. Here is an example of a web service that provides the necessary method signature:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;[WebService(Namespace = "http://tempuri.org/")]&lt;br /&gt;[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]&lt;br /&gt;public class SuggestionService : System.Web.Services.WebService&lt;br /&gt;{&lt;br /&gt;    public SuggestionService()&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;    [WebMethod]&lt;br /&gt;    public string[] GetSuggestions(string prefixText, int count)&lt;br /&gt;    {&lt;br /&gt;        return new string[] { "abc", "def", "ghi" };&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;The prefixText parameter is the text the user has entered thus far, and the count parameter is the maximum number of suggestions you should return. And just like that, we have auto-completion!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/AutoCompleteViaWebService.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/400/AutoCompleteViaWebService.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;br&gt;&lt;i&gt;Auto Completion via a Web Service&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Going one step further&lt;/h3&gt;&lt;br /&gt;It's the greatest thing since the variable geometry nacelle. But, there are some limitations to this approach. Because it must call a web service, the logic for determining the suggestions is isolated from the page that contains the textbox. That means you do not have access to any state information that is available on the page. In many cases that may not be an issue. It may even be good design to isolate that logic into a web service. But because you lack that state information, you are forced to configure the web service via global means such as the web.config. For example, a connection string. What if a developer wants auto completion for different database than the one the rest of the application is using? What if the suggestions that you want to show depend on the value of another control on the page, such as a date range that should limit the search results of the query? Or maybe you have a "product category" dropdown and the textbox should only suggest results for products that are in that category? What if you are a control developer (like me) and you want to create a custom textbox control that has auto completion built into it -- how will you effectively package together your custom control and the web service? Why should I have to create a web service to provide auto completion at all? &lt;br /&gt;&lt;br /&gt;Why can't I wield the power of auto-completion all within the page itself? &lt;br /&gt;&lt;br /&gt;Yes... Let's do that. Presenting the SmartAutoCompleteExtender and the SmartTextBox. In creating these two controls I had a strategy in mind:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Create an Auto Complete extender that uses a &lt;i&gt;CALLBACK&lt;/i&gt; rather than a web service. This will allow all the logic to calculate the suggestions to live on the same page.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Support a Web Service too, for flexibility.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Utilize the existing auto complete behavior script, so I don't have to write complex JavaScript.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Raise an Event in the Extender control when suggestions are needed. The event model will allow users of the extender to provide suggestions easily within the page and multiple listeners could potentially work together to create suggestions from different sources.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Create a TextBox with a built-in Auto Complete extender, so users of that control can provide auto completion without even knowing what Atlas is&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;This being my first custom extender for Atlas, I did run into a few problems. But in less than a day I was able to piece these controls together. If I had to do it again, already having learned all the lessons that I did, I could probably do it on the order of a few hours. This is a testament to the extensibility of Atlas. More on that later.&lt;br /&gt;&lt;br /&gt;First, let us look at the SmartAutoCompleteExtender. To use it I must register my custom control assembly and namespace with the obligatory Register directive at the top:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;%@ Register Assembly="Infinity.Web" Namespace="Infinity.Web.UI.WebControls" TagPrefix="i88" %&gt;&lt;/code&gt;&lt;/pre&gt;i88 is a nice tag prefix I like to use. Now lets replace the built in atlas extender with the smart one:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;i88:SmartAutoCompleteExtender Enabled="true" id="ext1" runat="server"&gt;&lt;br /&gt; &amp;lt;i88:SmartAutoCompleteProperties&lt;br /&gt;            TargetControlID="txt1" /&gt;&lt;br /&gt;&amp;lt;/i88:SmartAutoCompleteExtender&gt;&lt;/code&gt;&lt;/pre&gt;Notice there's no ServicePath or ServiceMethod specified. This extender uses an event on the server side instead. But if you wanted to use a web service, it supports that too:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;i88:SmartAutoCompleteExtender Enabled="true" id="ext1" runat="server"&gt;&lt;br /&gt; &amp;lt;i88:SmartAutoCompleteProperties&lt;br /&gt;            TargetControlID="txt1"&lt;br /&gt;            &lt;b&gt;Mode="WebService"&lt;/b&gt;&lt;br /&gt;            ServicePath="SuggestionService.asmx"&lt;br /&gt;            ServiceMethod="GetSuggestions" /&gt;&lt;br /&gt;&amp;lt;/i88:SmartAutoCompleteExtender&gt;&lt;/code&gt;&lt;/pre&gt;But, we're more interested in the event. Just to keep these code lines shorter (screen real estate is prime on this blog .. I need a better medium!), create a namespace alias in your code behind:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;using I88=Infinity.Web.UI.WebControls;&lt;/code&gt;&lt;/pre&gt;Then you can hook into the event on the extender like so:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;protected override void OnInit(EventArgs e)&lt;br /&gt;{&lt;br /&gt; this.ext1.AutoCompleteCallback += new I88.EventHandler&lt;I88.AutoCompleteEventArgs&gt;(ext1_AutoCompleteCallback);&lt;br /&gt; base.OnInit(e);&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;AutoCompleteCallback is the event that fires when the client side needs suggestions. Now for the event handler itself:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;void ext1_AutoCompleteCallback(object sender, I88.AutoCompleteEventArgs args)&lt;br /&gt;{&lt;br /&gt; int count = args.Count;&lt;br /&gt; string prefix = args.Prefix;&lt;br /&gt;&lt;br /&gt; args.CompletionItems = new string[] { prefix + "A", prefix + "B", prefix + "C" };&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;The event argument passed to the event handler contains three properties:&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Count - The maximum number of suggestions that should be returned&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Prefix - The characters entered so far into the textbox&lt;/li&gt;&lt;br /&gt;&lt;li&gt;CompletionItems - a string array of suggestions to be set by you.&lt;br /&gt;&lt;/ol&gt;Just for demonstration and to prove it is working, we take the prefix and create three suggestions by adding "A", "B" and "C" to it. Here we go:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/AutoCompleteViaCallback.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/400/AutoCompleteViaCallback.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;br&gt;&lt;i&gt;Look ma, no web service!&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Excellent. The beauty of this is that it really was not very hard to do. I was able to reuse the existing javascript behavior that is defined for the built-in AutoCompleteExtender. The custom behavior javascript simply creates an instance of the built in behavior and lets it do all the dirty work. All that was required is to hook into the timer object it uses by replacing its event handler with my own, and replacing existing methods with your own is easy to do with javascript. To do the actual callback, it uses asp.net's built-in javascript function for that, too: WebForm_DoCallback. By passing it the ID of the extender control, and implementing ICallbackEventHandler in the extender control, its easy to raise the auto complete event.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Going one step further, again&lt;/h3&gt;&lt;br /&gt;Indeed why stop there... wouldn't it be nice if you didn't even need to create an extender? Why can't auto complete be a built-in feature of the textbox itself? Man you sure are demanding. Fine...&lt;br /&gt;&lt;br /&gt;Get rid of the extender declaration. Then replace the TextBox with, well... the i88:SmartTextBox:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;i88:SmartTextBox ID="txt1" runat="server" EnableAutoComplete="true" /&gt;&lt;/code&gt;&lt;/pre&gt;Don't forget the EnableAutoComplete="true" attribute, because by default it is disabled. You might wonder why I didn't call this control "AutoCompleteTextBox" instead. Well because I don't believe in naming controls (or classes) after their features. The SmartTextBox might one day be extended to support many other advanced features, of which Auto Completion would be just one. Just planning ahead a little. "Smart" may not be the best name either, but its the best I could come up with ok? :)&lt;br /&gt;&lt;br /&gt;Internally, the SmartTextBox creates a SmartAutoComplete extender for you. It also surfaces a property that allows you to have access to all the same properties the extender does. So once again you can use a web service or a callback, whatever floats your boat:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;i88:SmartTextBox ID="txt1" runat="server" EnableAutoComplete="true"&lt;br /&gt; AutoComplete-Mode="WebService"&lt;br /&gt; AutoComplete-ServicePath="SuggestionService.asmx"&lt;br /&gt; AutoComplete-ServiceMethod="GetSuggestions" /&gt;&lt;/code&gt;&lt;/pre&gt;But as before, we're only interested in the callback mode for this article. The SmartTextBox also surfaces the event itself -- so if all you knew about was the SmartTextBox control, you could quickly and easily add custom auto completion to it, without ever hearing the word "Atlas" muttered. Change the event handler like so:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;protected override void OnInit(EventArgs e)&lt;br /&gt;{&lt;br /&gt; this.txt1.AutoCompleteCallback += new I88.EventHandler&lt;I88.AutoCompleteEventArgs&gt;(txt1_AutoCompleteCallback);&lt;br /&gt; base.OnInit(e);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void txt1_AutoCompleteCallback(object sender, I88.AutoCompleteEventArgs args)&lt;br /&gt;{&lt;br /&gt; int count = args.Count;&lt;br /&gt; string prefix = args.Prefix;&lt;br /&gt;&lt;br /&gt; args.CompletionItems = new string[] { prefix + "A", prefix + "B", prefix + "C" };&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;And put it into action... remember to type at least 3 characters, because the default minimum length is 3. That is a property you can change if you like.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/AutoCompleteViaCallback.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/400/AutoCompleteViaCallback.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;br&gt;&lt;i&gt;Look ma, no web service AND no Extender!&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Yes I cheated -- this screenshot is exactly the same one as before. But that's because it looks exactly the same anyway. Even the 'view source' on the page looks exactly the same. The only difference is the declaration in the form.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.infinity88.com/downloads/SmartControlsProject.zip" target="_blank"&gt;Download the source code here!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I should also mention that the project type is the Web Application project option introduced by Microsoft, described in detail and &lt;a href="http://webproject.scottgu.com" target="_blank"&gt;available for download here&lt;/a&gt;. If you don't have it already, you should. It will be baked in on the first service pack for VS2005 anyway. If you'd rather not, then you'll have to rebuild the project file, or perhaps you can change the project type guid so it's a class library project instead. Sorry for the confusion.&lt;br /&gt;&lt;br /&gt;Use the source however you like... change it, trash it, claim it as your own, I don't mind :) All I ask is you send some friends over to this tiny corner of the internet. I enjoy having readers. :)&lt;br /&gt;&lt;br /&gt;Happy coding!&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;UPDATE 06/08/2006:&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Someone pointed out a bug with the project on the asp.net forums. &lt;a href="http://forums.asp.net/thread/1309204.aspx" target="_blank"&gt;Click here&lt;/a&gt; to read the post. I have re-uploaded a new project with the fix.&lt;br /&gt;&lt;br /&gt;I also added a new property to the extender: EnableCache (boolean). You see, the built in behavior has a nice little performance feature built into it. Once it requests suggestions for prefix "abc", it remembers them in a cache variable on the client. So if you type in "abcd", wait for the auto complete to occur again, then delete the "d", the behavior is able to recall the suggestions it already calculated without calling the webservice or performing another callback. But this presents a problem in callback mode if you try to use this custom extender in the ways it is advertised, where the suggestions may depend on the state of other controls on the page. The state of those controls may change, and the cache of suggestions will be wrong. And so it was simple to add the EnableCache property. Normally you should leave this option alone. Only disable the cache if you know you might give different suggestions for the same prefix text, because the values are dependant on other controls.&lt;br /&gt;&lt;br /&gt;And finally, I have also included a sample web application that uses the SmartTextBox in callback mode. It also contains a RadioButtonList, and the suggestion items vary based on the selected value of the list.&lt;br /&gt;&lt;br /&gt;Thanks to ethos42 for the bug report!&lt;br /&gt;&lt;a href="http://www.infinity88.com/downloads/SmartControlsProject.zip" target="_blank"&gt;Download the Source Code here!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;UPDATE 06/10/2006:&lt;/strong&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately for me but fortunate for you guys, jjradke pointed out another bug. The event will fail to fire if you place the textbox within a naming container (for example within a template column of a datagrid, among other things). The bug was due to it using the ClientID instead of the UniqueID... which has been fixed!! If you already downloaded the source you can easily patch your copy by changing this line (approximately line 90 in the SmartAutoCompleteExtender.cs file)&lt;br /&gt; &lt;br /&gt;writer.WriteAttributeString("id", this.ClientID);&lt;br /&gt; &lt;br /&gt;To this:&lt;br /&gt; &lt;br /&gt;writer.WriteAttributeString("id", this.UniqueID);&lt;br /&gt; &lt;br /&gt;Thanks for the bug report!&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;strong&gt;UPDATE: 08/24/2006:&lt;/em&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;I'm sorry to have put you guys through downloading from FilePlanet. The link eventually broke, but thankfully I've found a more suitable home for the source code. The download links should work once again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-114852317110898121?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/114852317110898121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=114852317110898121' title='92 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/114852317110898121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/114852317110898121'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2006/05/atlas-smart-auto-completion.html' title='Atlas: Smart Auto Completion'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>92</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-114601551115307624</id><published>2006-04-25T17:57:00.000-07:00</published><updated>2006-09-07T19:36:43.403-07:00</updated><title type='text'>The CodeExpressionBuilder</title><content type='html'>&lt;span style="color:red"&gt;&lt;b&gt;UPDATE: THIS POST HAS BEEN MOVED TO MY NEW BLOG! Please redirect your bookmarks here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://weblogs.asp.net/infinitiesloop/archive/2006/08/09/The-CodeExpressionBuilder.aspx"&gt;http://weblogs.asp.net/infinitiesloop/archive/2006/08/09/The-CodeExpressionBuilder.aspx&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A very exciting new feature in ASP.NET 2.0 is &lt;B&gt;Expression Builders&lt;/B&gt;. Expression builders allow for some pretty interesting interaction with the ASP.NET compilation model.&lt;br /&gt;&lt;br /&gt;For example, new to ASP.NET 2.0 is the ability to reference appSettings declaratively. Lets say you wanted the text of a button to be based on a value in the appSettings section of your web.config. Piece of cake:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&amp;lt;asp:Button id="cmdSubmit" runat="server"&lt;br /&gt; Text="&amp;lt;%$ appSettings: ButtonText %&gt;" /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;This is made possible by the built in AppSettingsExpressionBuilder. Lets say you wanted to display a localizable string, which is stored as a resource. In ASP.NET 1.1 it was sort of a pain. No longer:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&amp;lt;%$ resources: ResourceKey %&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;That's the ResourcesExpressionBuilder hard at work. Nice!&lt;br /&gt;&lt;br /&gt;There's also a &lt;B&gt;ConnectionStringsExpressionBuilder&lt;/B&gt; so you can refer to Connection Strings defined in the new connection strings section in the web.config. That is extremely helpful when working with the new declarative data controls:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&amp;lt;asp:SqlDataSource id="data1" runat="server"&lt;br /&gt;   ConnectionString="&amp;lt;%$ ConnectionStrings: MyConnectionString %&gt;"/&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Wow.&lt;br /&gt;&lt;br /&gt;Now lets take it one step further. Have you ever seen this exception?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/CheckBoxFailing.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/320/CheckBoxFailing.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;The dreaded "Server tags cannot contain &lt;% ... %&gt; constructs" exception.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;That's because you probably tried to do something like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&amp;lt;asp:Label id="lbl1" runat="server" Text=&amp;lt;%= CurrentUserName %&gt; /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Perhaps you tried to fix it by putting it in quotes:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&amp;lt;asp:Label id="lbl1" runat="server" Text="&amp;lt;%= CurrentUserName %&gt;" /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;... Only to be thwarted once again, as the literal text, including the &amp;lt;%= %&gt; construct, ended up in the page:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/CheckBoxDoesntListen.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/320/CheckBoxDoesntListen.gif" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;Putting &amp;lt%= %&gt; in quotes doesn't help much.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;If all you want to do is show the result of this code as a string, you could quite simply just get rid of the label:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&amp;lt;%= CurrentUserName %&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;That would work. But for purposes of this example, lets assume that doesn't work for you. Perhaps you need the label server control for some other reason, or perhaps you need to set a string property of some other type of server control in this way.&lt;br /&gt;&lt;br /&gt;The problem is you have incorrectly, although intuitively, tried to assign the property of a server control using the &amp;lt;%= %&gt; construct. Unfortunately that is simply not supported by ASP.NET, 1.1 nor 2.0. If you ask around about your problem, someone may tell you that you will have to convert to using the &amp;lt;%# %&gt; databinding construct instead. That is advice that I have given myself, I even eluded to it in my previous blog post. That will work. But it requires that you are calling DataBind() on the control, AND, it will cause you to &lt;B&gt;BLOAT VIEWSTATE&lt;/B&gt;... and you KNOW how much &lt;a href="http://infinitiesloop.blogspot.com/2006/03/truly-understanding-viewstate.html" target="_blank"&gt;I hate bloating viewstate&lt;/a&gt;!&lt;br /&gt;&lt;br /&gt;It seems like it should be a common need... all you want is to assign the default value for a control to something a little dynamic. Something that can't be represented with a literal. Something with some logic behind it. You can just go ahead and assign the value in your code-behind, say.. in the OnInit method.. but that too will &lt;a href="http://infinitiesloop.blogspot.com/2006/03/truly-understanding-viewstate.html" target="_blank"&gt;bloat viewstate&lt;/a&gt;. I'm afraid there's no super simple solution unless you don't mind disabling viewstate on that control. That may work in some scenarios, but sometimes you really need the ViewState enabled! What's a web developer to do?&lt;br /&gt;&lt;br /&gt;Here's a better example. You want, for some reason, the text value of a CheckBox to be the current date and time. For whatever reason, you can't disable viewstate on the CheckBox (say, because you need the CheckChanged event, which doesn't work without viewstate). It doesn't matter why exactly. How on Earth are you going to get the current date and time into the Text property on the CheckBox, &lt;B&gt;WITHOUT BLOATING VIEWSTATE&lt;/B&gt;? By "Bloating ViewState", I mean causing data to become serialized in the __VIEWSTATE hidden form field when it isn't necessary to begin with. There's no reason to put the current Date and Time into serialized viewstate, is there? It's going to be reassigned on the next request. You'd just be making ASP.NET serialize it, then making the user's browser suck the serialized string down the pipe, then making them push it back down the pipe to the server on a postback, then making ASP.NET deserialize the value -- ONLY FOR IT TO BE REASSIGNED? How rude! How wasteful and inefficient. For a single control its not a big deal, what's a few bytes? But that is not a path you want to start down my friend... with that kind of mantra, your web forms will quickly grow a viewstate tumor the &lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/ViewStateMadness.jpg" target="_blank"&gt;size of a Borg cube&lt;/a&gt;! Ideally, you want the functional equivalence of this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&amp;lt;asp:CheckBox id="chk1" runat="server" Text="&amp;lt;%= DateTime.Now %&gt;"/&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;That is ideal, because the ViewState StateBag is not tracking changes when ASP.NET assigns declared attributes, so our beloved ViewState remains optimized. And, we didn't even have to disable ViewState. AND we can do it declaratively! Woohoo! Right. Well, good luck getting that to work. It won't.&lt;br /&gt;&lt;br /&gt;The CodeExpressionBuilder comes to the rescue! Another great thing about ExpressionBuilders is that you can create your own. So, I created a &lt;U&gt;&lt;B&gt;Code&lt;/B&gt;&lt;/U&gt;ExpressionBuilder, one that allows you to use raw code to assign values to control properties. Using the CodeExpressionBuilder you can do this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;asp:CheckBox id="chk1" runat="server" Text="&amp;lt;%$ Code: DateTime.Now %&gt;"/&gt;&lt;/pre&gt;&lt;br /&gt;Now that is nice. And to think the darn thing is only a few lines of code. It seems like such a useful thing to have, I don't know why it isn't included as a built in feature.&lt;br /&gt;&lt;br /&gt;The trick is to use the CodeDom's CodeSnippetExpression to convert the given string into a CodeExpression. Here's the entire class:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;[ExpressionPrefix("Code")]&lt;br /&gt;class CodeExpressionBuilder : ExpressionBuilder&lt;br /&gt;{&lt;br /&gt; public override object ParseExpression(string expression,&lt;br /&gt;  Type propertyType, ExpressionBuilderContext context)&lt;br /&gt; {&lt;br /&gt;  return expression;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public override CodeExpression GetCodeExpression(BoundPropertyEntry entry,&lt;br /&gt;  object parsedData, ExpressionBuilderContext context)&lt;br /&gt; {&lt;br /&gt;  return new CodeSnippetExpression(parsedData.ToString());&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;To use it, or any custom ExpressionBuilder for that matter, you must register it in the web.config expressionBuilders section. Now... how you do this part sort of depends on how your project is setup. If you have a standard ASP.NET Web Site project, then you will be defining the CodeExpressionBuilder class in the app_code directory, and the "type" will just be "CodeExpressionBuilder". However, if you are creating a Web Application Project (read about it &lt;a href="http://webproject.scottgu.com/" target="_blank"&gt;here&lt;/a&gt;), then the CodeExpressionBuilder is just another class in your project, with its own namespace. For that you will need to define the whole type string (or, if you define it in a reusable library, you'll need the fully qualified type and assembly name). In my case that is "Infinity.Web.Compilation.CodeExpressionBuilder". Here it is:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&amp;lt;compilation debug="true"&gt;&lt;br /&gt; &amp;lt;expressionBuilders&gt;&lt;br /&gt;  &amp;lt;add expressionPrefix="Code"&lt;br /&gt;  Type="Infinity.Web.Compilation.CodeExpressionBuilder"/&gt;&lt;br /&gt; &amp;lt;/expressionBuilders&gt;&lt;br /&gt;&amp;lt;/compilation&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;And to see it in action:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&amp;lt;asp:CheckBox id="chk1" runat="server"&lt;br /&gt; Text="&amp;lt%$ Code: DateTime.Now %&gt;" /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/CheckBoxInAction.gif"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/320/CheckBoxInAction.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;i&gt;ExpressionBuilders are truly a thing of beauty! Use any expression you want!&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;You can use any code expression want:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&amp;lt%$ Code: DateTime.Now.AddDays(1) %&gt;&lt;br /&gt;&amp;lt%$ Code: "Hello World, " + CurrentUserName %&gt;&lt;br /&gt;&amp;lt%$ Code: CurrentUserName.ToUpper() %&gt;&lt;br /&gt;&amp;lt%$ Code: "Page compiled as: " + this.GetType().AssemblyQualifiedName %&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Just be careful what combination of quotes you use. If you have literal strings in your code expression like in two of the above examples, you will need to use single quotes (') to surround the entire &amp;lt;%$ %&gt; expression if it is within a server control declaration. If you don't you will get the "Server tag is not well formed" error.&lt;br /&gt;&lt;br /&gt;In the beginning I said ExpressionBuilders were an interesting way to plug into the ASP.NET compilation model. Well this really illustrates that... put a break point in the expression builder, and debug the page. You will hit the break point once, and only once, even after you refresh the page several times. The Date and Time will continue to update, but the expression builder breakpoint will only activate the first time you hit the page. The reason is because the ExpressionBuilder is used when ASP.NET compiles the page. Once the page is compiled, that's it. That's the reason why ExpressionBuilder returns a CodeExpression, and not an actual object. In essence, the builder tells ASP.NET what code it needs to run to get the value, instead of giving it the actual value. It's the old adage, teach a man to fish, and he eats forever. How geeky is that? Too cool.&lt;br /&gt;&lt;br /&gt;PS: The one thing this ExpressionBuilder doesn't do... it won't work in "No-Compile" pages. Seems like a reasonable limitation.&lt;br /&gt;&lt;br /&gt;Questions? Comments? I just figured out this thing tonight and I'm all happy about it. I'm curious why this isn't a built in expression builder, its so simple yet so useful. Perhaps there's a good reason I haven't thought of. It would be awesome if an asp.net team member could provide their insight :) One of these days I hope to lure one of them into this site...&lt;br /&gt;&lt;br /&gt;HAPPY CODING.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-114601551115307624?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/114601551115307624/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=114601551115307624' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/114601551115307624'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/114601551115307624'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2006/04/codeexpressionbuilder.html' title='The CodeExpressionBuilder'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-114222067251250329</id><published>2006-03-12T19:11:00.000-08:00</published><updated>2006-12-06T01:11:16.333-08:00</updated><title type='text'>TRULY Understanding Viewstate</title><content type='html'>&lt;span style="color:red"&gt;&lt;b&gt;UPDATE: THIS POST HAS BEEN MOVED TO MY NEW BLOG! Please redirect your bookmarks here:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx"&gt;http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you read this blog at all, by now you've got to be sick of me talking about ViewState. I'm sorry, but its becoming increasingly clear to me that ViewState is a very misunderstood animal. I would like to help put an end to the madness by attempting to explain exactly how the ViewState mechanism works, from beginning to end, and from many different use cases, such as declared controls vs. dynamic controls.&lt;br /&gt;&lt;br /&gt;There are a lot of great articles out there that try to dispel the myths about ViewState. You might say this is like beating a dead horse (where ViewState is the horse, and the internet is the assailant). But this horse isn't dead, let me tell you. No, he's very much alive and he's stampeding through your living room. We need to beat him down once again. No horses were harmed during the authoring of this article.&lt;br /&gt;&lt;br /&gt;It's not that there's no good information out there about ViewState, it's just all of them seem to be lacking something, and that is contributing to the community's overall confusion about ViewState. For example, one of the key features that is important to understand about ViewState is how it &lt;i&gt;tracks dirtiness&lt;/i&gt;. Yet, &lt;a href="http://www.aspnetresources.com/articles/ViewState.aspx" target="_blank"&gt;here&lt;/a&gt; is a very good, in-depth article on ViewState that doesn't even mention it! Then there's this &lt;a href="http://www.w3schools.com/aspnet/aspnet_viewstate.asp" target="_blank"&gt;W3Schools&lt;/a&gt; article on ViewState that seems to indicate that posted form values are maintained via ViewState, but that's not true. Don't believe me? Disable ViewState on that textbox in their example and run it again). And it's the &lt;a href="http://www.google.com/search?sourceid=navclient&amp;ie=UTF-8&amp;rls=GGLG,GGLG:2005-49,GGLG:en&amp;q=asp%2Enet+viewstate" target="_blank"&gt;#1 Google Search Result&lt;/a&gt; for "ASP.NET ViewState". Can you believe that? Ok so these are all third party sites. Microsoft articles wouldn't be wrong, would they? No. But, they aren't extremely in depth either. For example, here is &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconmantainingstateincontrol.asp" target="_blank"&gt;ASP.NET Documentation on MSDN&lt;/a&gt; that describes how Controls maintain state across postbacks. The documentation isn't &lt;i&gt;wrong&lt;/i&gt; per say, but it makes a statement that isn't entirely correct:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;u&gt;"If a control uses ViewState for property data instead of a private field, that property automatically will be persisted across round trips to the client.&lt;/u&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;That seems to imply that anything you shove into the ViewState StateBag will be round-tripped in the client's browser. NOT TRUE!&lt;br /&gt;&lt;br /&gt;So it's really no wonder there is so much confusion on ViewState. There is no where I've found on the internet that has a 100% complete and accurate explanation of how it works! The best article I have ever found is &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/viewstate.asp" target="_blank"&gt;this one by Scott Mitchell&lt;/a&gt;. There's nothing that is wrong or even ambiguous in that article, however, it is incomplete. It does not explain the relationship of controls and their child controls when it comes to initialization and ViewState Tracking, and it is this point alone that causes a bulk of the mishandlings of ViewState, at least in the experiences I've had.&lt;br /&gt;&lt;br /&gt;So the point of this article will be to first give a complete understanding of how ViewState basically functions, from beginning to end, hopefully filling in the holes that many other articles have, but without going into a lot of technical detail on things like LosFormatting, for example, because there are plenty of sites out there that do an awesome job of that already. After a complete explanation of the entire ViewState process, I will go into some examples of how developers typically misuse ViewState, usually without even realizing it, and how to fix it.&lt;br /&gt;&lt;br /&gt;First let me explain why understanding ViewState &lt;i&gt;to it's core&lt;/i&gt; is so important:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;b&gt;MISUNDERSTANDING OF VIEWSTATE WILL LEAD TO...&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Leakage of sensitive data&lt;br /&gt;&lt;li&gt;ViewState Attacks - &lt;i&gt;aka the Jedi Mind Trick -- *waves hand* that plasma tv is for sale for $1.00&lt;/i&gt;&lt;br /&gt;&lt;li&gt;Poor performance - &lt;i&gt;even to the point of NO PERFORMANCE&lt;/i&gt;&lt;br /&gt;&lt;li&gt;Poor scalability - &lt;i&gt;how many users can you handle if each is posting 50k of data every request?&lt;/i&gt;&lt;br /&gt;&lt;li&gt;Overall poor design&lt;br /&gt;&lt;li&gt;Headache, nausea, dizziness, and irreversible frilling of the eyebrows.&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;If you develop an ASP.NET Application and you don't take ViewState seriously, this could happen to you: &lt;table width=100% align="center" cellpadding="4" cellspacing="4"&gt;&lt;tr&gt;&lt;td valign="bottom"&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/ViewStateMadness.jpg" target="_blank"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/320/ViewStateMadness.jpg" border="0" alt="ViewState Madness!!!" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td valign="bottom"&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/EnterpriseDvsBorg.0.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/400/EnterpriseDvsBorg.0.jpg" border="0" alt="Drop your red bull and surrender your cpu cycles. You will be frustrated. Performance is futile." /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;i&gt;The ViewState form field on a prominent asp.net community site.&lt;/i&gt;&lt;/td&gt;&lt;td&gt;&lt;i&gt;ViewState will add your web app's distinctiveness to it's own. Performance is futile.&lt;/i&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;I could go on but that is the gist of it. Now lets move on by starting back from the beginning:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;b&gt;WHAT DOES VIEWSTATE DO?&lt;/b&gt;&lt;br /&gt;&lt;i&gt;This is a list of ViewState's main jobs. Each of these jobs serves a very distinct purpose. Next we'll learn exactly how it fulfills those jobs.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Stores values per control by key name, like a hashtable&lt;br /&gt;&lt;li&gt;Tracks changes to a ViewState value's initial state&lt;br /&gt;&lt;li&gt;Serializes and Deserializes saved data into a hidden form field on the client&lt;br /&gt;&lt;li&gt;Automatically restores data on postbacks&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Even more important than understanding what it does, is understanding what it does NOT do:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;b&gt;WHAT DOESN'T VIEWSTATE DO?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Automatically retain state of class variables (private, protected, or public)&lt;br /&gt;&lt;li&gt;Remember any state information across page loads (only postbacks) (that is unless you customize how the data is persisted)&lt;br /&gt;&lt;li&gt;Remove the need to repopulate data on every request&lt;br /&gt;&lt;li&gt;ViewState is not responsible for the population of values that are posted such as by TextBox controls (although it does play an important role)&lt;br /&gt;&lt;li&gt;Make you coffee&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;While ViewState does have one overall purpose in the ASP.NET Framework, it's four main roles in the page lifecycle are quite distinct from each other. Logically, we can separate them and try to understand them individually. It is often the mishmash of information on ViewState that confuses people. Hopefully this breaks it down into more bite size nuggets. Mmmm... ViewState Nuggets.&lt;br /&gt;&lt;br /&gt;&lt;div align=center&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/ViewstateNuggets.jpg" target="_blank"&gt;&lt;img src="http://photos1.blogger.com/blogger/8140/417/320/ViewstateNuggets.jpg" border="0" alt="ViewState Nuggets" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. VIEWSTATE STORES VALUES&lt;/b&gt;&lt;br /&gt;If you've ever used a hashtable, then you've got it. There's no rocket science here. ViewState has an indexer on it that accepts a string as the key and any object as the value. For example:&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;ViewState["Key1"] = 123.45M; // store a decimal value&lt;br /&gt;ViewState["Key2"] = "abc"; // store a string&lt;br /&gt;ViewState["Key3"] = DateTime.Now; // store a DateTime&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;Actually, "ViewState" is just a name. ViewState is a protected property defined on the System.Web.UI.Control class, from which all server controls, user controls, and pages, derive from. The type of the property is &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebuistatebagclasstopic.asp" target="_blank"&gt;System.Web.UI.StateBag&lt;/a&gt;. Strictly speaking, the StateBag class has nothing to do with ASP.NET. It happens to be defined in the System.Web assembly, but other than it's dependency on the LosFormatter, also defined in System.Web.UI, there's no reason why the StateBag class couldn't live along side ArrayList in the System.Collections namespace. In fact, I've often wondered why Microsoft did not do just that since the StateBag has many useful features that the other collections are lacking.&lt;br /&gt;&lt;br /&gt;In practice, Server Controls utilize ViewState as the backing store for most, if not all their properties. This is true of almost all Microsoft's built in controls (ie, label, textbox, button). &lt;b&gt;This is important!&lt;/b&gt; You must understand this about controls you are using. Read that sentance again. I mean it... here it is a 3rd time: &lt;B&gt;SERVER CONTROLS UTILIZE VIEWSTATE AS THE BACKING STORE FOR MOST, IF NOT ALL THEIR PROPERTIES&lt;/B&gt;. Depending on your background, when you think of a traditional property, you might imagine something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;public string Text&lt;br /&gt;{&lt;br /&gt;  get { return _text; }&lt;br /&gt;  set { _text = value; }&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;What is important to know here is that this is NOT what most properties on ASP.NET controls look like. Instead, they use the ViewState StateBag, not a private instance variable, as their backing store:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;public string Text&lt;br /&gt;{&lt;br /&gt;  get { return (string) ViewState["Text"]; }&lt;br /&gt;  set { ViewState["Text"] = value; }&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;And I can't stress it enough -- this is true of almost ALL PROPERTIES, even STYLES (actually, Styles do it by implementing IStateManager, but essentially they do it the same way). When writing your own controls it would usually be a good idea to follow this pattern, but thought should first be put into what should and shouldn't be allowed to be dynamically changed on postbacks. But I digress -- that's a different subject.&lt;br /&gt;&lt;br /&gt;It is also important to understand how &lt;B&gt;DEFAULT VALUES&lt;/B&gt; are implemented using this technique. When you think of a property that has a default value, in the traditional sense, you might imagine something like the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;public class MyClass&lt;br /&gt;{&lt;br /&gt;  private string _text = "Default Value!";&lt;br /&gt;&lt;br /&gt;  public string Text&lt;br /&gt;  {&lt;br /&gt;    get { return _text; }&lt;br /&gt;    set { _text = value; }&lt;br /&gt;  }&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;The default value is the default because it is what is returned by the property if no one ever sets it. How can we accomplish this when ViewState is being used as the private backing? Like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;public string Text&lt;br /&gt;{&lt;br /&gt;  get&lt;br /&gt;  {&lt;br /&gt;    return ViewState["Text"] == null ?&lt;br /&gt;         "Default Value!" :&lt;br /&gt;          (string) ViewState["Text"];&lt;br /&gt;  }&lt;br /&gt;  set { ViewState["Text"] = value; }&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;Like a hashtable, the StateBag will return null as the value behind a key if it simply doesn't contain an entry with that key. So if the value is null, it has not been set, so return the default value, otherwise return whatever the value is. For you die-hards out there -- you may have detected a difference in these two implementations. In the case of ViewState backing, setting the property to NULL will result in resetting the property back to it's default value. With a "regular" property, setting it to null means it will simply be null. Well, that is just one reason why ASP.NET always tends to use String.Empty ("") instead of null. It's also not very important to the built in controls because basically all of their properties that can be null already are null by default. All I can say is keep this in mind if you write your own controls.&lt;br /&gt;&lt;br /&gt;And finally, as a footnote really, while this property-backing usage of the ViewState StateBag is how the StateBag is typically used, it isn't limited to just that. As a control or page, you can access you're own ViewState StateBag at any time for any reason, not just in a property. It is sometimes useful to do so in order to remember certain pieces of data across postbacks, but that too is another subject.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. VIEWSTATE TRACKS CHANGES&lt;/b&gt;&lt;br /&gt;Have you ever set a property on a control and then somehow felt... dirty? I sure have. In fact, after a twelve-hour day of setting properties in the office, I become so filthy my wife refuses to kiss me unless I'm holding flowers to mask the stench. I swear!&lt;br /&gt;&lt;br /&gt;Ok so setting properties doesn't really make you dirty. But it does make the entry in the StateBag dirty! The StateBag isn't just a dumb collection of keys and values like a Hashtable (please don't tell Hashtable I said that, he's scarey). In addition to storing values by key name, the StateBag has a TRACKING ability. Tracking is either on, or off. Tracking can be turned on by calling TrackViewState(), but once on, it cannot be turned off. When tracking is ON, and ONLY when tracking is ON, any changes to any of the StateBag's values will cause that item to be marked as "Dirty". StateBag even has a method you can use to detect if an item is dirty, aptly named IsItemDirty(string key). You can also manually cause an item to be considered dirty by calling SetItemDirty(string key). To illustrate, lets assume we have a StateBag that is not currently tracking:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;stateBag.IsItemDirty("key"); // returns false&lt;br /&gt;stateBag["key"] = "abc";&lt;br /&gt;stateBag.IsItemDirty("key"); // still returns false&lt;br /&gt;&lt;br /&gt;stateBag["key"] = "def";&lt;br /&gt;stateBag.IsItemDirty("key"); // STILL returns false&lt;br /&gt;&lt;br /&gt;stateBag.TrackViewState();&lt;br /&gt;stateBag.IsItemDirty("key"); // yup still returns false&lt;br /&gt;&lt;br /&gt;stateBag["key"] = "ghi";&lt;br /&gt;stateBag.IsItemDirty("key"); // TRUE!&lt;br /&gt;&lt;br /&gt;stateBag.SetItemDirty("key", false);&lt;br /&gt;stateBag.IsItemDirty("key"); // FALSE!&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;Basically, tracking allows the StateBag to keep &lt;i&gt;track&lt;/i&gt; of which of it's values have been changed since TrackViewState() has been called. Values that are assigned before tracking is enabled are not tracked (StateBag turns a blind eye). It is important to know that any assignment will mark the item as dirty -- even if the value given matches the value it already has!&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;stateBag["key"] = "abc";&lt;br /&gt;stateBag.IsItemDirty("key"); // returns false&lt;br /&gt;stateBag.TrackViewState();&lt;br /&gt;stateBag["key"] = "abc";&lt;br /&gt;stateBag.IsItemDirty("key"); // returns true&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;ViewState &lt;i&gt;could&lt;/i&gt; have been written to compare the new and old values before deciding if the item should be dirty. But recall that ViewState allows any object to be the value, so you aren't talking about a simple string comparison, and the object doesn't have to implement IComparable so you're not talking about a simple CompareTo either. Alas, because serialization and deserialization will be occuring, an instance you put into ViewState won't be the same instance any longer after a postback. Microsoft decided rightfully so that this kind of comparison is not  important for ViewState to do it's job.&lt;br /&gt;&lt;br /&gt;So that's tracking in a nutshell. But you might wonder why StateBag would need this ability in the first place. Why on earth would anyone need to know only changes since TrackViewState() is called? Why wouldn't they just utilize the entire collection of items?&lt;br /&gt;&lt;br /&gt;This one point seems to be at the core of all the confusion on ViewState. I have interviewed countless professionals, sometimes with years and years of ASP.NET experience logged in their resumes, who have failed miserably to prove to me that they understand this point. Actually, I have yet to interview a single candidate who has. And let me just say, if I interviewed you and you did get it right, and it was entirely up to me, your odds of being hired would go through the roof.&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;a href="http://photos1.blogger.com/blogger/8140/417/1600/ViewStateChances.jpg" target="_blank"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://photos1.blogger.com/blogger/8140/417/400/ViewStateChances.jpg" border="0" alt="Your Odds" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;First, to truly understand why Tracking is needed, you will need to understand a little bit about how ASP.NET sets up declarative controls. Declarative controls are controls that are defined in your ASPX or ASCX form. Here: &lt;pre&gt;&lt;blockquote&gt;&amp;lt;asp:Label id="lbl1" runat="server" Text="Hello World" /&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;I do declare that this label is declared on your form. The next thing we need to make sure you understand is ASP.NET's ability to wire up declared attributes to control properties. When ASP.NET parses the form, and finds a tag with runat=server, it creates an instance of the specified control. The variable name it assigns the instance to is based on the ID you assigned it (by the way, many don't realize that you don't have to give a control an ID at all, ASP.NET will use an automatically generated ID. Not specifying an ID has advantages, but that is a different subject). But that's not all it does. The control's tag may contain a bunch of attributes on it. In our label example up above, we have a "Text" attribute, and it's value is "Hello World". Using reflection, ASP.NET is able to detect whether the control has property by that name, and if so, &lt;b&gt;sets&lt;/b&gt; its value to the declared value. Obviously the attribute is declared as a string (hey, its stored in a text file after all), so if the property it maps to isn't of type string, it must figure out how to convert the given string into the correct type, before calling the property setter. How it does that my friend is also an entirely different topic (it involves TypeConverters and static Parse methods). Suffice it to say it figures it out, and calls the property setter with the converted value.&lt;br /&gt;&lt;br /&gt;Recall that all-important statement from the first role of the StateBag. Here it is again: Server Controls utilize ViewState as the backing store for most, if not all their properties. That means when you declare an attribute on a server control, that value is usually ultimately stored as an entry in that control's ViewState StateBag. Now recall how tracking works. Remember that if the StateBag is "tracking", then setting a value to it will mark that item as dirty. If it isn't tracking, it won't be marked dirty. So the question is -- when ASP.NET calls the SET on the PROPERTY that corresponds to the ATTRIBUTE that is DECLARED on the control, is the StateBag TRACKING or isn't it? The answer is no it is not tracking, because tracking doesn't begin until someone calls TrackViewState() on the StateBag, and ASP.NET does that during the OnInit phase of the page/control lifecycle.&lt;br /&gt;&lt;br /&gt;This little trick ASP.NET uses to populate properties allows it to easily detect the difference between a declaratively set value and dynamically set value. If you don't yet realize why that is important, please keep reading.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. SERIALIZATION AND DESERIALIZATION&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Aside from how ASP.NET creates declarative controls, the first two capabilities of ViewState we've discussed so far have been strictly related to the StateBag class (how it's similar to a hashtable, and how it tracks dirty values). Here is where things get bigger. Now we will have to start talking about how ASP.NET uses the ViewState StateBag's features to make the (black) magic of ViewState happen.&lt;br /&gt;&lt;br /&gt;If you've ever done a "View Source" on an ASP.NET page, you've no doubt encountered the serialization of ViewState. You probably already knew that ViewState is stored in a hidden form field aptly named _VIEWSTATE as a base64 encoded string, because when anyone explains how ViewState works, that's usually the first thing they mention.&lt;br /&gt;&lt;br /&gt;A brief aside -- before we understand how ASP.NET comes up with this single encoded string, we must understand the hierarchy of controls on the page. Many developers with years of experience still don't realize that a page consists of a tree of controls, because all they work on are ASPX pages, and all they need to worry about are controls that are directly declared on those pages... but controls can contain child controls, which can contain their own child controls, etc. This forms a tree of controls, where the ASPX page itself is the root of that tree. The 2nd level is all the controls declared at the top level in the ASPX page (usually that consists of just 3 controls -- a literal control to represent the content before the form tag, a HtmlForm control to represent the form and all its child controls, and another literal control to represent all the content after the close form tag). On the 3rd level are all the controls contained within those controls (ie, controls that are declared within the form tag), and so on and so forth.&lt;br /&gt;&lt;br /&gt;Each one of the controls in the tree has it's very own ViewState -- it's very own instance of a StateBag. There's a protected method defined on the System.Web.UI.Control class called SaveViewState. It returns type 'object'. The implementation for Control.SaveViewState is to simply pass the call along to the Control's StateBag (it too has a SaveViewState() method). By calling this method recursively on every control in the control tree, ASP.NET is able to build another tree that is structured not unlike the control tree itself, except instead of a tree of controls, it is a tree of data. The data at this point is not yet converted into the string you see in the hidden form field, it's just an object tree of the data to be saved.&lt;br /&gt;&lt;br /&gt;Here is where it finally comes together... are you ready?&lt;br /&gt;&lt;br /&gt;When the StateBag is asked to save and return it's state (StateBag.SaveViewState()), it only does so for the items contained within it that are marked as Dirty. That is why StateBag has the tracking feature. That is the only reason why it has it. And oh what a good reason it is -- StateBag could just process every single item stored within it, but why should data that has not been changed from it's natural, declarative state be persisted? There's no reason for it to be -- it will be restored on the next request when ASP.NET reparses the page anyway (actually it only parses it once, building a compiled class that does the work from then on).&lt;br /&gt;&lt;br /&gt;Despite this smart optimization employed by ASP.NET, unnecessary data is still persisted into ViewState all the time due to misuse. I will get into examples that demonstrate these types of mistakes later on.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;B&gt;POP QUIZ&lt;/B&gt;&lt;br /&gt;&lt;br /&gt;If you've read this far, congratulations, I am rewarding you with a pop quiz. Aren't I nice? Here it is:&lt;br /&gt;&lt;br /&gt;Let's say you have two nearly identical ASPX forms: Page1.aspx and Page2.aspx. Contained within each page is just a form tag and a label, like so:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;form id="form1" runat="server"&amp;gt;&lt;br /&gt;&amp;lt;asp:Label id="label1" runat="server" Text="" /&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;They are identical except for one minor difference. In Page1.aspx, we shall declare the label's text to be "abc":&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;asp:Label id="label1" runat="server" Text="abc" /&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;...And on Page2.aspx, we shall declare the label's text to be something much longer (the preamble to the Constitution of the United States of America):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;asp:Label id="label1" runat="server" Text="We the people of the&lt;br /&gt;United States, in order to form a more perfect union,&lt;br /&gt;establish justice, insure domestic tranquility, provide&lt;br /&gt;for the common defense, promote the general welfare,&lt;br /&gt;and secure the blessings of liberty to ourselves and&lt;br /&gt;our posterity, do ordain and establish this Constitution&lt;br /&gt;for the United States of America." /&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;Imagine you browse to Page1.aspx, you will see "abc" and nothing more. Then you use your browser to view the HTML source of the page. You will see the infamous hidden _VIEWSTATE hidden field with encoded data in it. Note the size of that string. Now you browse to Page2.aspx, and you see the preamble. You use your browser to view the HTML source once again, and you note the size of the encoded _VIEWSTATE field.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;u&gt;The question is: Are the two sizes you noted the same, or are they different?&lt;/u&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Before we get to the answer, lets make it a little bit more involved. Lets say you also put a button next to the label (on each page):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;asp:Button id="button1" runat="server" Text="Postback" /&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There is no code in the click event handler for this button, so clicking on it doesn't do anything except make the page flicker. With this new button in place, you repeat the experiment, except this time when browsing to each page, you click the Postback button before looking at the HTML source. So the question is once again...&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;u&gt;Are the encoded ViewState values the same, or different?&lt;/u&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The correct answer to the first part the question is &lt;i&gt;&lt;u&gt;THEY ARE THE SAME&lt;/u&gt;&lt;/i&gt;! They are the same because in neither of the two viewstate strings are any data related to the label at all. If you understand ViewState, this is obvious. The Text property of the label is set to the declared value before it's ViewState is being tracked. That means if you were to check the dirty flag of the Text item in the StateBag, it would not be marked dirty. StateBag ignores items that aren't dirty when SaveViewState() is called, and it is the object it returns that is serialized into the hidden _VIEWSTATE field. Therefore, the text property is not serialized. Since the Text is not serialized in either case, and the forms are identical in every other way, the sizes of the encoded viewstates on each page must be the same. In fact, no matter how large or small of a string you stuff into that text attribute, the size will remain the same.&lt;br /&gt;&lt;br /&gt;The correct answer to the second part is again, &lt;i&gt;&lt;u&gt;THEY ARE THE SAME&lt;/u&gt;&lt;/i&gt;! In order for data to be serialized, it must be marked as dirty. In order to be marked as dirty, it's value must be set after TrackViewState() is called. But even when we perform a postback, ASP.NET recreates and populates the server controls in the same way. The Text property is still set to it's declared value just like it was in the first request. No other code is setting the text property, so there's no way the StateBag item could become dirty, even on a postback. Therefore, the sizes of the encoded viewstates on each page after a postback must be the same.&lt;br /&gt;&lt;br /&gt;So now we understand how ASP.NET determines what data needs to be serialized. But we don't know how it is serialized. That topic is outside the scope of this article (are you missing an assembly reference?), so if you're really interested in how it works, read up on the &lt;a href="http://www.google.com/search?q=losformatter" target="_blank"&gt;LosFormatter&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Finally on this topic is DESERIALIZATION. Obviously all this fancy dirty tracking and serialization wouldn't do any good if we couldn't get the data back again. That too is outside the scope of this article, but suffice it to say the process is just the reverse. ASP.NET rebuilds the object tree it serialized by reading the posted _VIEWSTATE form value and deserializing it with the LosFormatter.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;B&gt;4. AUTOMATICALLY RESTORES DATA&lt;/B&gt;&lt;br /&gt;&lt;br /&gt;This is last on our list of ViewState features. It is tempting to tie this feature in with Deserialization above, but it is not really part of that process. ASP.NET deserializes the ViewState data, and THEN it repopulates the controls with that data. Many articles out there confuse these two processes. Defined on System.Web.UI.Control (again, the class that every control, user control, and page derive from) is a LoadViewState() method which accepts an object as parameter. This is the opposite of the SaveViewState() method we already discussed, which returns an object. Like SaveViewState(), LoadViewState() simple forwards the call on to it's StateBag object, calling LoadViewState on it. The StateBag then simply repopulates it's key/object collection with the data in the object. In case you are wondering, the object it is given is a System.Web.UI.Pair class, which is just a simple type with a First and Second field on it. The "First" field is an ArrayList of key names, and the "Second" field is an ArrayList of values. So StateBag just iterates over the lists, calling this.Add(key, value) for each item. The important thing to realize here is that the data it was given via LoadViewState() are only items that where marked dirty on the &lt;i&gt;previous request&lt;/i&gt;. Prior to loading the ViewState items, the StateBag may already have values in it. Those values may be from declarative properties like we discussed, but they may also be values that were explicitly set by the developer prior to the LoadViewState call. If one of the items passed into LoadViewState already exists in the StateBag for some reason, it will be overwritten. That right there is the magic of automatic state management. When the page first begins to load during a postback (even prior to initialization), all the properties are set to their declared natural defaults. Then OnInit occurs. During the OnInit phase, ASP.NET calls TrackViewState() on all the StateBags. Then LoadViewState() is called with the deserialized data that was dirty from the previous request. The StateBag calls Add(key, value) for each of those items. Since the StateBag is tracking at this point, the value is marked dirty, so that it may be persisted once again for the &lt;i&gt;next&lt;/i&gt; postback. Brilliant!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Whew. Now you are an expert on ViewState management.&lt;br /&gt;&lt;br /&gt;&lt;B&gt;IMPROPER USE OF VIEWSTATE&lt;/B&gt;&lt;br /&gt;&lt;br /&gt;Now that we know exactly how ViewState works, we can finally begin to understand the problems that arise when it is used improperly. In this section I will describe cases that illustrate how a lot of ASP.NET developers misuse ViewState. But these aren't just obvious mistakes. Some of these will illustrate nuances about ViewState that will give you an even deeper understanding of how it all fits together.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;b&gt;CASES OF MISUSE&lt;/b&gt;&lt;br /&gt;&lt;li&gt;Forcing a Default&lt;br /&gt;&lt;li&gt;Persisting static data&lt;br /&gt;&lt;li&gt;Persisting cheap data&lt;br /&gt;&lt;li&gt;Initializing child controls programmatically&lt;br /&gt;&lt;li&gt;Initializing dynamically created controls programmatically&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;&lt;B&gt;1. Forcing a Default&lt;/B&gt;&lt;br /&gt;&lt;br /&gt;This is one of the most common misuses, and it is also the easiest to fix. The fixed code is also usually more compact than the wrong code. Yes, doing things the right way can lead to less code. Imagine that.&lt;br /&gt;&lt;br /&gt;This usually occurs when a control developer wants a particular property to have a particular default value, and does not understand the dirty tracking mechanism, or doesn't care. For example, lets say the Text property a control is supposed to be some value that comes from a Session variable. Developer Joe writes the following code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;public class JoesControl : WebControl&lt;br /&gt;{&lt;br /&gt;  public string Text&lt;br /&gt;  {&lt;br /&gt;    get { return this.ViewState["Text"] as string; }&lt;br /&gt;    set { this.ViewState["Text"] = value; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  protected override void OnLoad(EventArgs args)&lt;br /&gt;  {&lt;br /&gt;     if(!this.IsPostback)&lt;br /&gt;     {&lt;br /&gt;        this.Text = Session["SomeSessionKey"] as string;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     base.OnLoad(e);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This developer has committed a ViewState crime, call the ViewState police! There's two big problems with this approach. First of all, since Joe is developing a control, and he has taken the time to create a public Text property, it stands to reason that Joe may want developers that use his control to be able to set the Text property to something else. Jane is a page developer that is attempting to do just that, like so:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;abc:JoesControl id="joe1" runat="server" Text="ViewState rocks!"/&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Jane is going to have a bad day. No matter what Jane puts into that Text attribute, Joe's control will refuse to listen to her. Poor Jane. She's using this control just like you use every other ASP.NET control, but this one works differently. Joe's control is overwriting Jane's Text value! Worse than that, since Joe sets it during the OnLoad phase, it is marked dirty in ViewState. So to add insult to injury, Jane is now incurring an increase in her page's serialized ViewState size for doing nothing more than putting Joe's Control on her page. I guess Joe doesn't like Jane very much. Maybe Joe's just trying to get back at Jane for something.&lt;br /&gt;&lt;br /&gt;Well, since we all know which sex rules this world, we can assume Jane ends up getting Joe to fix his control. Much to Jane's delight, this is what Joe comes up with:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;public class JoesControl : WebControl&lt;br /&gt;{&lt;br /&gt;  public string Text&lt;br /&gt;  {&lt;br /&gt;    get&lt;br /&gt;    {&lt;br /&gt;      return this.ViewState["Text"] == null ?&lt;br /&gt;         Session["SomeSessionKey"] :&lt;br /&gt;         this.ViewState["Text"] as string;&lt;br /&gt;    }&lt;br /&gt;    set { this.ViewState["Text"] = value; }&lt;br /&gt;  }&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Look at how much less code we have here. Joe doesn't even have to override OnLoad. Because the StateBag returns null if the given key does not exist, Joe can detect whether his Text property has been set already by checking for null. If it is, he can safely return his would-be default value. If it's not null, he happily returns whatever value it is. Simple as can be. Now when Jane uses Joe's control, not only is her Text attribute honored, she no longer incurs a hit on her ViewState size, either. Better behavior. Better performance. Less code. Everyone wins!&lt;br /&gt;&lt;br /&gt;&lt;B&gt;2. Persisting static data&lt;/B&gt;&lt;br /&gt;&lt;br /&gt;By Static, I mean data that never changes or is not expected to change during the lifetime of a page, or even during the users session. Lets say Joe, our would-be shoddy asp.net developer, has been tasked with adding the current user's name to the top of a page in the company's eCommerce application. It's a nice way of telling the user, "hey, we know who you are!" It makes them feel special and that the site is working. Positive feedback. Lets say this eCommerce application has a business layer API that allows Joe to easily get the name of the currently authenticated user: CurrentUser.Name. Joe completes his task:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;br /&gt;(ShoppingCart.aspx)&lt;br /&gt;&amp;lt;asp:Label id="lblUserName" runat="server"/&amp;gt;&lt;br /&gt;&lt;br /&gt;(ShoppingCart.aspx.cs)&lt;br /&gt;protected override void OnLoad(EventArgs args)&lt;br /&gt;{&lt;br /&gt;   this.lblUserName.Text = CurrentUser.Name;&lt;br /&gt;   base.OnLoad(e);&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Sure enough, the current user's name will show up. Piece of cake, Joe thinks. Of course we know Joe has committed another sin. The label control he is using is tracking it's viewstate when it is assigned the current user's name. That means not only will the Label render the user name, but that user name will be encoded into the viewstate hidden form field. Why make ASP.NET go through all the work of serializing and deserializing the user name, when you are just going to reassign it after all? That's just rude! Even when confronted, Joe shrugs at the problem. It's only a few bytes! But it's a few bytes you can save so easily. There are two solutions to this problem. First... you could just disable viewstate on the label.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;asp:Label id="lblUserName" runat="server"&lt;br /&gt;EnableViewState="false"/&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Problem solved. But there's an even better solution. Label has to be one of the most overused controls there are, bested only by the Panel control. It comes from the mindset of Visual Basic Programmers. To show text on a VB Form you needed a label. Labels are supposed to be the ASP.NET WebForm counterpart, so it's only nature to think you need a label to display a text value that isn't hardcoded in the webform. Fair enough, but that's not true. Label's render a &amp;lt;span&amp;gt; tag around their text content. You must ask yourself whether your really need this span tag at all. Unless you are applying a STYLE to this label, the answer is NO. This would suffice just fine:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;%= CurrentUser.Name %&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Not only do you get to avoid having to declare a label on the form (which means less code, albeit designer-generated code), but you've followed the spirit of the code-behind model: separation of code from design! In fact, if Joe's company had a dedicated designer responsible for the look and feel of the eCommerce site, Joe could have simply passed on the task. "That's the designers job", he could have balked, and rightfully so. There is another reason why you might THINK you need a Label, and that is when something in the code behind may need to programmatically access or manipulate that label. Ok, fair enough. But you must still ask yourself whether you really need a SPAN tag surrounding the text. Introducing the most underused controls in ASP.NET: The LITERAL!&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;asp:Literal id="litUserName" runat="server"&lt;br /&gt;EnableViewState="false"/&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;No span tag here.&lt;br /&gt;&lt;br /&gt;&lt;B&gt;3. Persisting cheap data&lt;/B&gt;&lt;br /&gt;&lt;br /&gt;This one is a superset of #2. Static data is definitely cheap to get. But not all cheap data is static. Sometimes we have data that may change during the lifetime of an application, possibly from moment to moment, but that data is virtually free to retrieve. By free, I mean the performance cost of looking it up is insignificant.&lt;br /&gt;&lt;br /&gt;A common instance of this mistake is when populating a dropdown list of U.S. States. Unless you are writing a web application that you plan on warping back in time to December 7, 1787 (&lt;a href="http://www.enchantedlearning.com/usa/states/statehood.shtml" target="_blank"&gt;here&lt;/a&gt;), the list of US States is not going to change any time soon. However, as a programmer that hates to type, you certainly wouldn't want to have to type these states by hand into your web form. And in the event a state does rebel (we can only dream... you know who you are), you wouldn't want to have to perform a code change to strike it from the list.&lt;br /&gt;&lt;br /&gt;Our proverbial programmer Joe decides he will populate his dropdown list from a USSTATES table in a database. The eCommerce site is already using a database, so its trivial for him to add the table and query it.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;asp:DropdownList id="lstStates" runat="server"&lt;br /&gt;DataTextField="StateName" DataValueField="StateCode"/&amp;gt;&lt;br /&gt;&lt;br /&gt;protected override void OnLoad(EventArgs args)&lt;br /&gt;{&lt;br /&gt;   if(!this.IsPostback)&lt;br /&gt;   {&lt;br /&gt;      this.lstStates.DataSource = QueryDatabase();&lt;br /&gt;      this.lstStates.DataBind();&lt;br /&gt;   }&lt;br /&gt;   base.OnLoad(e);&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As is the nature of databound controls in ASP.NET, the state dropdown will be using ViewState to remember it's databound list of list items. At the time of this ranting, there are a total of 50 US States. Not only does the dropdown list contain a ListItem for each and every state, but each and every one of those states and their state codes are being serialized into the encoded viewstate. That's a lot of data to be stuffing down the pipe every time the page loads, especially over a dialup connection. I often wonder what it would be like if I explained to my grandmother the reason why her internet is so slow is because her computer is telling the server what all the US States are. I don't think she'd understand. She'd probably just start explaining how when she was young, there were only 46 states. Too bad... those extra 4 states are really wearing down your bandwidth. Damn you late comers! You know who you are!&lt;br /&gt;&lt;br /&gt;Like the problem with static data, the general solution to this problem is to just disable viewstate on the control. Unfortunately, that is not always going to work. Whether it does depends on the nature of the control you are binding, and what features of it you are dependant on. In this example, if Joe simply added EnableViewState="false" to the dropdown, and removed the if(!this.IsPostback) condition, he would successfully remove the state data from viewstate, but he would immediately run into a troubling problem. The dropdown will no longer restore it's selected item on postbacks. WAIT!!! This is another source of confusion with ViewState. The reason the dropdown fails to remember it's selected item on postbacks is NOT because you have disabled viewstate on it. Postback controls such as dropdownlist and textbox restore their posted state (the selected item of a dropdown ist 'posted') even when viewstate is disabled, because even with viewstate disabled the control is still able to post its value. It forgets it's selected value because you are rebinding it in OnLoad, which is after the dropdown has already loaded it's posted value. When you databind it again, the first thing it does is throw that into the bit bucket (you know, digital trash). That means if a user selects California from the list, then click on a submit button, the dropdown will stubbornly return the default item (the first item if you don't specify it otherwise). Thankfully, there is an easy solution: Move the DataBind into OnInit:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;asp:DropdownList id="lstStates" runat="server"&lt;br /&gt;DataTextField="StateName" DataValueField="StateCode" EnableViewState="false"/&amp;gt;&lt;br /&gt;&lt;br /&gt;protected override void OnInit(EventArgs args)&lt;br /&gt;{&lt;br /&gt;   this.lstStates.DataSource = QueryDatabase();&lt;br /&gt;   this.lstStates.DataBind();&lt;br /&gt;   base.OnInit(e);&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The short explanation for why this works: You are populating the dropdown list with items before it attempts to load it's posted value. Now the dropdown will behave just like it did when Joe first designed it, only the rather large list of states will NOT be persisted into the viewstate hidden field! Brilliant!&lt;br /&gt;&lt;br /&gt;More importantly, this rule applies to any data that is cheap and easy to get to. You might argue that making a database query on every request is MORE costly than persisting the data through viewstate. In this case I believe you'd be wrong. Modern database systems (say, SQL Server) have sophisticated caching mechanism and are extremely efficient if configured correctly. The state list needs to be repopulated on every request no matter what you're doing. All you've done is change it from being pushed and pulled down a slow, unreliable 56kbps internet connection that may have to travel for thousands of miles, to being pulled over at worse a 10 megabit LAN connection a couple hundred feet between your internet server and database server. AND if you really wanted to improve things, you could cache the results of the database query in the application. You do the math!&lt;br /&gt;&lt;br /&gt;&lt;B&gt;4. Initializing child controls programmatically&lt;/B&gt;&lt;br /&gt;&lt;br /&gt;Let's face it. You can't do everything declaratively. Sometimes you have to get logic involved. That's why we all have jobs, right? The trouble is ASP.NET does not provide an easy way to programmatically initialize properties of child controls correctly. You can override OnLoad and do it there -- but then you're persisting data that probably doesn't need to be persisted into viewstate. You can override OnInit and do it there instead, but that suffers from the same problem. Remember when we learned how ASP.NET calls TrackViewState() during the OnInit phase? It does this recursively on the entire control tree, but it does it from the BOTTOM of the tree UP! In other words, as a control or webform, the OnInit phase of your child controls occurs BEFORE your own. A control will begin tracking viewstate changes in this phase, which means by the time your own OnInit phase begins, your child controls viewstate are all already tracking!&lt;br /&gt;&lt;br /&gt;Lets say Joe would like to display the current date and time in a label declared on the form.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;asp:Label id="lblDate" runat="server" /&amp;gt;&lt;br /&gt;&lt;br /&gt;protected override void OnInit(EventArgs args)&lt;br /&gt;{&lt;br /&gt;   this.lblDate.Text = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss");&lt;br /&gt;   base.OnInit(e);&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Even though Joe is setting the label text in the &lt;b&gt;earliest event possible&lt;/b&gt; on his webform, it's already too late. The label is tracking viewstate changes, and the current date and time will inevitably be persisted into viewstate. This particular example could fall under the cheap data issue above. Joe could simply disable viewstate on the label to solve this problem. But here we are going to solve it a different way in order to illustrate an important concept. What would be nice is if Joe could declaratively set the label text to what he wants, something like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;asp:Label id="lblDate" runat="server" Text="&amp;lt;%= DateTime.Now.ToString() %&amp;gt;" /&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You may have intuitively attempted this before. But ASP.NET will slap you in the face for it. The "&amp;lt;%= %&amp;gt;" syntax can not be used to assign values to properties of server-side controls. Joe could use the "&amp;lt;%# %&amp;gt;" syntax instead, but that isn't very different than the databinding method we've already covered (disabling viewstate and databinding it every request).&lt;br /&gt;&lt;br /&gt;The problem is we would like to be able to assign a value through code, but allow the control to continue to work in exactly the way it normally would. Perhaps some code is going to be manipulating this label, and we want any changes made to it to be persisted through ViewState like they normally would be. For example, maybe Joe wants to give the users a way to remove the date display from the form, replacing it with a blank date instead:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;br /&gt;private void cmdRemoveDate_Click(object sender, EventArgs args)&lt;br /&gt;{&lt;br /&gt;   this.lblDate.Text = "--/--/---- --:--:--";&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If the user clicks this button, the current date and time will vanish. But if we solved our original viewstate problem by disabling viewstate on the label, the date and time will magically reappear again on the next postback that occurs, because the label's viewstate being disabled means it will not automatically be restored. That's not good. What on Earth is Joe supposed to do now?&lt;br /&gt;&lt;br /&gt;What we really want is to declaratively set a value that is based on logic, not static. If it were declared the label could continue to work like it normally does -- the initial state wouldn't be persisted since it is set before viewstate is tracking, and changes do it would be persisted in viewstate. Like I said... ASP.NET does not provide an easy way to accomplish this task.&lt;br /&gt;&lt;br /&gt;For you ASP.NET 2.0 developers out there, you do have the $ sign syntax, which allows you to use expression builders to declare values that actually come from a dynamic source (ie, resources, declared connection strings). But as far as I know, there's no expression builder for "just run this code" so I don't think that helps you either.&lt;br /&gt;&lt;br /&gt;Also for ASP.NET 2.0 developers, there's OnPreInit. That is actually a great place to initialize child control properties programmatically because it occurs before the child control's OnInit (and therefore before it is tracking viewstate) and after the controls are created. However, OnPreInit is not recursive like the other control phase methods are. That means it is only accessible on the PAGE itself. That doesn't help you what-so-ever if you are developing a CONTROL. It's too bad OnPreInit isn't recursive just like OnInit, OnLoad, and OnPreRender are, I don't see a reason for the inconsistency.&lt;br /&gt;&lt;br /&gt;The root of the problem is simply that we need to be able to assign the Text property of the label BEFORE it beings tracking its viewstate. We already know the page's OnInit event (the first event that occurs in the page) is already too late for that. So what if we could somehow hook into the Init event of the label? You can't add an event handler in code for that, because the soonest you can do it is in your OnInit which is after the source event has already occurred. And you can't do it in the constructor for the page, because declared controls are not yet created at that point. There are two possibilities:&lt;br /&gt;&lt;br /&gt;1. Declaratively hook into the Init event:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&amp;lt;asp:Label id="lblDate" runat="server" OnInit="lblDate_Init" /&amp;gt;&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This works because the OnInit attribute is processed before the label's own OnInit event occurs, giving us an opportunity to manipulate it before it beings tracking viewstate changes. Our event handler would set its text.&lt;br /&gt;&lt;br /&gt;2. Create a custom control:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;br /&gt;public class DateTimeLabel : Label&lt;br /&gt;{&lt;br /&gt;  public DateTimeLabel()&lt;br /&gt;  {&lt;br /&gt;    this.Text = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss");&lt;br /&gt;  }&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then instead of a regular label on the form, a DateTimeLabel is used. Since the control is initializing it's own state, it can do so before tracking begins. It does it during the constructor if possible, so that a declared value will be honored.&lt;br /&gt;&lt;br /&gt;&lt;B&gt;5. Initializing dynamically created controls programmatically&lt;/B&gt;&lt;br /&gt;&lt;br /&gt;This is the same problem as before, but since you are in more control of the situation, it is much easier to solve. Lets say Joe has written a custom control that at some point is dynamically creating a Label.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;br /&gt;public class JoesCustomControl : Control&lt;br /&gt;{&lt;br /&gt;  protected override void CreateChildControls()&lt;br /&gt;  {&lt;br /&gt;    Label l = new Label();&lt;br /&gt;&lt;br /&gt;    this.Controls.Add(l);&lt;br /&gt;    l.Text = "Joe's label!";&lt;br /&gt;  }&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Hmmm. When do dynamically created controls begin tracking viewstate? You can create and add dynamically created controls to your controls collection at almost any time during the page lifecycle, but ASP.NET uses the OnInit phase to start viewstate tracking. Won't our dynamic label miss out on that event?&lt;br /&gt;&lt;br /&gt;No. The trick is, Controls.Add() isn't just a simple collection add request. It does much more. As soon as a dynamic control is added to the control collection of a control that is rooted in the page (if you follow its parent controls eventually you get to the page), ASP.NET plays "catch up" with the event sequence in that control and any controls it contains. So let's say you add a control dynamically in the OnPreRender event (although there plenty of reasons why you would not want to do that). At that point, your OnInit, LoadViewState, LoadPostBackData, and OnLoad events have transpired. The second the control enters your control collection, all of these events happen within the control.&lt;br /&gt;&lt;br /&gt;That means my friend the dynamic control is tracking viewstate immediately after you add it. Besides your constructor, the earliest you can add dynamic controls is in OnInit, where child controls are already tracking viewstate. In Joe's control, he's adding them in the CreateChildControls() method, which ASP.NET calls whenever it needs to make sure child controls exist (when it is called can vary based on whether you are an INamingContainer, whether it is a postback, and whether anything else calls EnsureChildControl()). The latest this can happen is OnPreRender, but if it happens any time after or during OnInit, you will be dirtying viewstate again, Joe. The solution is simple but easy to miss:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;br /&gt;public class JoesCustomControl : Control&lt;br /&gt;{&lt;br /&gt;  protected override void CreateChildControls()&lt;br /&gt;  {&lt;br /&gt;    Label l = new Label();&lt;br /&gt;    l.Text = "Joe's label!";&lt;br /&gt;&lt;br /&gt;    this.Controls.Add(l);&lt;br /&gt;  }&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Subtle. Instead of initializing the label's text after adding it to the control collection, Joe initializes it &lt;b&gt;before&lt;/b&gt; it is added. This ensures without a doubt that the Label is not tracking viewstate when it is initialized.&lt;br /&gt;&lt;br /&gt;Actually you can use this trick to do more than just initialize simple properties. You can databind controls even before they are part of the control tree. Remember our US State dropdown list example? If we can create that dropdown list dynamically, we can solve that problem without even disabling its viewstate:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;blockquote&gt;&lt;br /&gt;public class JoesCustomControl : Control&lt;br /&gt;{&lt;br /&gt;  protected override void OnInit(EventArgs args)&lt;br /&gt;  {&lt;br /&gt;     DropDownList states = new DropDownList();&lt;br /&gt;     states.DataSource = this.GetUSStatesFromDatabase();&lt;br /&gt;     states.DataBind();&lt;br /&gt;     &lt;br /&gt;     this.Controls.Add(states);&lt;br /&gt;  }&lt;br /&gt;}&lt;/blockquote&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It works amazingly well. The dropdown list will behave as if the states are simply built-in list items. They are not persisted in ViewState, yet ViewState is still enabled on the control, meaning you can still take advantage of its ViewState dependant features like the OnSelectedIndexChanged event. You can even do this with DataGrids, although that depends on how you are using it (you will run into problems if you are using sorting, paging, or using the SelectedIndex feature).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;BE VIEWSTATE FRIENDLY&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Now that you have a complete understanding of how viewstate does it's magic, and how it interacts with the page lifecycle in asp.net, it should be easy to be ViewState Friendly! That is the key really... ViewState optimization is easy as pie when you understand what is going on, often times resulting in even less code than the non-friendly code.&lt;br /&gt;&lt;br /&gt;Have any suggestions, comments, error reports? Please leave a comment or send me an email!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-114222067251250329?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/114222067251250329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=114222067251250329' title='60 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/114222067251250329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/114222067251250329'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2006/03/truly-understanding-viewstate.html' title='TRULY Understanding Viewstate'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>60</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-113997129263973948</id><published>2006-02-14T18:26:00.000-08:00</published><updated>2006-07-04T10:44:31.803-07:00</updated><title type='text'>Composite Controls made easy</title><content type='html'>Scott Gu has an interesting article in his blog, pointing to another article in MSDN, about creating Composite Controls.&lt;br /&gt;&lt;br /&gt;Its a great read, a must read, even.&lt;br /&gt;&lt;br /&gt;I just have one problem with it. Near the beginning of the article there is some sample code as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;public class LabelTextBox : WebControl, INamingContainer&lt;br /&gt;{&lt;br /&gt;   public string Text {&lt;br /&gt;      get {&lt;br /&gt;         object o = ViewState["Text"];&lt;br /&gt;         if (o == null)&lt;br /&gt;              return String.Empty;&lt;br /&gt;         return (string) o;&lt;br /&gt;      }&lt;br /&gt;      set { ViewState["Text"] = value; }&lt;br /&gt;   }&lt;br /&gt;   public string Title {&lt;br /&gt;      get {&lt;br /&gt;         object o = ViewState["Title"];&lt;br /&gt;         if (o == null)&lt;br /&gt;              return String.Empty;&lt;br /&gt;         return (string) o;&lt;br /&gt;      }&lt;br /&gt;      set { ViewState["Title"] = value; }&lt;br /&gt;   }&lt;br /&gt;   protected override void CreateChildControls()&lt;br /&gt;   {&lt;br /&gt;      Controls.Clear();&lt;br /&gt;      CreateControlHierarchy();&lt;br /&gt;      ClearChildViewState();&lt;br /&gt;   }&lt;br /&gt;   protected virtual void CreateControlHierarchy()&lt;br /&gt;   {&lt;br /&gt;       TextBox t = new TextBox();&lt;br /&gt;       Label l = new Label();&lt;br /&gt;       t.Text = Text;&lt;br /&gt;       l.Text = Title;&lt;br /&gt;       Controls.Add(l);&lt;br /&gt;       Controls.Add(t);&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;This is supposed to be an example of how you can use composite controls to make your life easier. This one allows you to set a label to a textbox, which redners before the textbox. Great use of compositing.&lt;br /&gt;&lt;br /&gt;Except for one little detail...&lt;br /&gt;&lt;br /&gt;Before I explain the problem let me just say... details like this are really frustrating. ASP.NET is very powerful, but with that power comes some responsibility. It is very easy to do things the "wrong" way. It's also very, very easy to do things the right way, but you have to know the difference. And knowing the difference means having a fairly deep understanding of how the framework, well, works. This and my previous post on ViewState are just two examples of these mundane yet crucial details.&lt;br /&gt;&lt;br /&gt;And now on to the juicy stuff...&lt;br /&gt;&lt;br /&gt;My problem with the example code is really a state management thing. When it creates the textbox and label, it "copies" the Title and Text properties, which are ViewState-based properties of the composite control, into them. That raises some red flags to me, because as soon as you are finished copying the values into the child controls, your public properties are now completely &lt;b&gt;disconnected&lt;/b&gt; from them. If someone, somewhere, for some reason, changes your Title or Text property value after this code occurs, it's too late. They will be dumb-founded as to why your control refuses to listen to their instructions (it will still render to 'old' value).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;THE SOLUTION&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The solution is so elegant in my opinion, I'm not sure why this isn't official recommended practice for compositing. I call it "delegating the properties". It means, don't store the state yourself, use the child control itself to store the state. The real problem was we had the value of our properties stored in two locations -- our ViewState, and our child controls' ViewState. Using the child control itself to store the state means it will always be in just one place, a place where we the parent and the child control can agree on. Here's how:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;private TextBox txtFoo;&lt;br /&gt;public MyControl()&lt;br /&gt;{&lt;br /&gt;  this.EnsureChildControls();&lt;br /&gt;}&lt;br /&gt;public string Text&lt;br /&gt;{&lt;br /&gt;  get { return this.txtFoo.Text; }&lt;br /&gt;  set { this.txtFoo.Text = value; }&lt;br /&gt;}&lt;br /&gt;protected override CreateChildControls()&lt;br /&gt;{&lt;br /&gt;  this.txtFoo = new TextBox()&lt;br /&gt;  this.Controls.Add(txtFoo);&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;The Text property does nothing more than access the textbox's Text property. No longer do we need to 'copy' the value into the textbox -- its already there!&lt;br /&gt;&lt;br /&gt;The important thing about this trick is to simply call EnsureChildControls() in your constructor. That's so the textbox will exist should someone try to set the Text property (which is very early on if they set it declaratively). Alternatively, you could call EnsureChildControls() within the get and set like so:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;public string Text&lt;br /&gt;{&lt;br /&gt;  get&lt;br /&gt;  {&lt;br /&gt;   this.EnsureChildControls();&lt;br /&gt;   return this.txtFoo.Text;&lt;br /&gt;  }&lt;br /&gt;  set&lt;br /&gt;  {&lt;br /&gt;   this.EnsureChildControls();&lt;br /&gt;   this.txtFoo.Text = value;&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;However, if you have several properties that do this, its much easier to just do it in the constructor. Less lines of code result.&lt;br /&gt;&lt;br /&gt;Happy control building!!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-113997129263973948?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://weblogs.asp.net/scottgu/archive/2006/02/14/438234.aspx' title='Composite Controls made easy'/><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/113997129263973948/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=113997129263973948' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/113997129263973948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/113997129263973948'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2006/02/composite-controls-made-easy.html' title='Composite Controls made easy'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-113947206381037674</id><published>2006-02-09T00:01:00.000-08:00</published><updated>2006-06-23T10:11:02.753-07:00</updated><title type='text'>ViewState: Misunderstood monster or fluffy sleeping kitten?</title><content type='html'>The former!&lt;br /&gt;&lt;br /&gt;Let me explain something to guys. ViewState is more complicated than you think it is. That's why you all abuse it so much :) Let me demonstrate:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;public class MyControl : Control&lt;br /&gt;{&lt;br /&gt;  public string Text&lt;br /&gt;  {&lt;br /&gt;    get { return (string) this.ViewState["Text"]; }&lt;br /&gt;    set { this.ViewState["Text"] = value; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  protected override void OnLoad(object sender, EventArgs args)&lt;br /&gt;  {&lt;br /&gt;     if(!Page.IsPostBack)&lt;br /&gt;     {&lt;br /&gt;        this.Text = "Hello World!";&lt;br /&gt;     }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public override void Render(HtmlTextWriter writer)&lt;br /&gt;  {&lt;br /&gt;    writer.WriteLine(this.Text);&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;What is &lt;b&gt;WRONG&lt;/b&gt; with this picture?&lt;br /&gt;&lt;br /&gt;Hmmmmmmm???&lt;br /&gt;&lt;br /&gt;No.. that's not it.&lt;br /&gt;&lt;br /&gt;You don't know?&lt;br /&gt;&lt;br /&gt;I told you that's not it.&lt;br /&gt;&lt;br /&gt;Give up?&lt;br /&gt;&lt;br /&gt;That's what I thought. Sorry for my rudeness but it seems like no one on the planet knows why this is wrong. I have to deal with it every day as a lead programmer. But hey, I don't blame you. I've done this sort of thing myself. It looks perfectly harmless. You want the default value of "Text" to be "Hello World!". And why wouldn't you anyway, "Hello World!" has been serving us programmers since 1812. What better way to honor its 194th birthday than to make it the default value on your Text property?&lt;br /&gt;&lt;br /&gt;No problem. Let it shine I say! But that's not what is wrong.&lt;br /&gt;&lt;br /&gt;What's wrong is HOW you make it the default value. You know that HTTP is a connectionless protocol right? Well yeah, that's why Session state and ViewState were invented. To help you maintain data across those stateless requests. Brilliant, it really is! "Hello World" has never been so happy.&lt;br /&gt;&lt;br /&gt;So let me ask you... What is this line of code for?&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;if(!Page.IsPostBack)&lt;/pre&gt;&lt;br /&gt;I know. It's so you don't do unnecessary work, right?&lt;br /&gt;&lt;br /&gt;ViewState will be so kind as to save the value for you. Therefore, you'd be wasting CPU cycles if you had to set it on every request, right? Sure. What's that you say? Oh... You're also worried about overwriting the value in case someone has changed it? I see. Well that's pretty smart... I mean, afterall, ViewState is loaded before OnLoad. We wouldn't want to overwrite any precious changes to that value. Very good! Now wait just a second here...&lt;br /&gt;&lt;br /&gt;You were on the right track, but you failed to understand the REAL problem here. The problem isn't that you would be wasting CPU cycles if you reassigned the value on every request...&lt;br /&gt;&lt;br /&gt;Oh no. The problem is much greater than that.&lt;br /&gt;&lt;br /&gt;The problem is that you are completely unaware of the purpose of ViewState. Did I say that already? Sorry, really I am... &lt;br /&gt;&lt;br /&gt;Here... There's no better way than to show you.&lt;br /&gt;&lt;pre&gt;public class MyControl : Control&lt;br /&gt;{&lt;br /&gt;  public string Text&lt;br /&gt;  {&lt;br /&gt;    get { return this.ViewState["Text"] == null ?&lt;br /&gt;            "Hello World" :&lt;br /&gt;            (string) this.ViewState["Text"]; }&lt;br /&gt;    set { this.ViewState["Text"] = value; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public override void Render(HtmlTextWriter writer)&lt;br /&gt;  {&lt;br /&gt;    writer.WriteLine(this.Text);&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;What have we got here. Hmm... No OnLoad anymore.&lt;br /&gt;"Hello World" has moved up into the property. If the value in ViewState is NULL we return it. That means, dun dun dun! We have a default value! And we didn't have to set it, its just THERE.&lt;br /&gt;&lt;br /&gt;Ok... so big deal. Who cares?&lt;br /&gt;&lt;br /&gt;I'll tell you who cares... and its not a fluffy sleeping kitten.&lt;br /&gt;&lt;br /&gt;In the 2nd control, the value "Hello World!" is not persisted into the hidden form field "_VIEWSTATE". In the first control, it is.&lt;br /&gt;&lt;br /&gt;Its a very... subtle... difference. But its VERY IMPORTANT!!!&lt;br /&gt;&lt;br /&gt;I have seen controls written the "bad" way that contained dozens of properties. The result is, when someone puts this nasty control on a page, even BEFORE THE FIRST POSTBACK, their viewstate is HUGELY BLOATED with crap. If you do it the 2nd way, its just as big as if you had ZERO properties. If some unlucky Joe Programmer uses your control within a DataGrid or repeater, they'll be taking a hit once for every data item they bind.&lt;br /&gt;&lt;br /&gt;VIEWSTATE IS NOT TO BE TAKEN LIGHTLY :)&lt;br /&gt;&lt;br /&gt;Here's the rule of thumb that you must live and die by: VIEWSTATE IS FOR TRACKING &lt;B&gt;CHANGES&lt;/B&gt; TO THE FORM'S STATE. Thats CHANGES. It is NOT meant to store the default values of your properties. Why on earth should it store default values? THEY'RE DEFAULT VALUES for crying out loud. Don't do it! :)&lt;br /&gt;&lt;br /&gt;I feel much better now. Thank you! :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-113947206381037674?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/113947206381037674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=113947206381037674' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/113947206381037674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/113947206381037674'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2006/02/viewstate-misunderstood-monster-or.html' title='ViewState: Misunderstood monster or fluffy sleeping kitten?'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-112373513670464702</id><published>2005-08-10T21:38:00.000-07:00</published><updated>2005-11-20T15:20:37.766-08:00</updated><title type='text'>Blog, how I miss thee</title><content type='html'>I haven't forgotten about you. I've just been busy, that's all. I promise I'll never leave you my dear blog. I have a picture of us that time we went to Vegas on my desk at work. Those were such good times, weren't they? It constantly reminds me of you. You are so reliable... whatever happens I know that you will be there for me, just waiting to hear of my daily struggles. And I know that whatever I tell you will be kept between you and me... for no one in cyberspace knows you exist! Oh blog, what would I do without you? This I do not know.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-112373513670464702?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/112373513670464702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/112373513670464702'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2005/08/blog-how-i-miss-thee.html' title='Blog, how I miss thee'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-108968328804302599</id><published>2004-07-12T17:42:00.000-07:00</published><updated>2004-07-12T18:54:14.536-07:00</updated><title type='text'>Understanding Infinity</title><content type='html'>The vastness of the universe is certainly well beyond human comprehension. Just the size of the city you live in is already stretching the limits of your imagination. Truly, even with a birds eye view, you cannot grasp the scale of distance you see before you. Our minds were only intended to process the immediate surroundings, anything beyond a certain distance and size is simply unimportant. But we do have the desire to understand... and an inkling of an imagination to start with.&lt;br /&gt;&lt;br /&gt;For me, it is this concept alone that drives my artistic side. I'm not talking about arts and crafts, I'm talking about abstract thinking. I love to probe the limits of my imagination in as many different ways as I can. That is really what drives me to create poetry, when I'm motivated anyway... I want to throw together a combination of words that inspire thought. I want to pry open the ceiling of our imagination, into possibilities unknown. It's a difficult task, maybe impossible. Even if I create a work of prose that I can be proud of, that I think just might be good enough to spark a sense of curiosity in someone else's mind, I cannot know whether it is simply my desire to succeed which is fooling me into believing that I have. I am locked within the confines of my mind, utterly incapable of observing it from a suitably subjective distance.&lt;br /&gt;&lt;br /&gt;Writing is indeed one of my main outlets of artistic energy, but that same set of neurons that gives me that outlet is probing for another way out... I've tried creating electronic music. I feel as if I have the capability of creating something worth listening to, something that could vex your mind as much if not more than my words could (however much that is). But my ability to throw together notes has proven to be... uninspiring.&lt;br /&gt;&lt;br /&gt;When I was a pre-teen I spent many summer months probing my more traditional artistic abilities with pencil and paper, even with photography. Tracing was fun, but simply for the fleeting moments in which I could fool myself into believing I had created an original piece of art. I was helpless to create anything but straight-edged perspective drawings. They were easy because you could get away with using only a ruler as a guide -- even a toddler could draw a straight line. I merely had to decide where the lines would go. Its those pesky curves and the shading that are beyond my analytical mind, which is constantly wondering what precise angle and thickness to execute.&lt;br /&gt;&lt;br /&gt;But with computers, you can accomplish more with less skill. Now a toddler can not only draw a straight line, she can draw a perfectly straight line. She can choose from all possible visible colors. She can add shading, gradients, even add perspective. Surely with these powerful tools at hand, I can produce something worth thinking about? Unfortunately, no. Computers provide an infinitely broad set of tools, but it still takes a human mind to create depth with them. Why? Because it is the human mind which will be consuming the artwork, no other reason. And so probing the depths of your mind is a prerequisite to producing art worth thinking about. But probing the depths of your mind isn't enough, either. I can sit here in silence and feel the deepest of emotions about the universe around me, but unless I can harness that energy and push it out through my extremities onto some kind of physical medium, you might just think I'm a really quiet person.&lt;br /&gt;&lt;br /&gt;And it is that ability, that &lt;em&gt;harnessing&lt;/em&gt; that I seem to be lacking completely. Because no matter what prose I create, music I compose, pictures I take, or what images I produce, they seem woefully inadequate, and they are. Not that I'm not semi-talented in at least one of these trades -- the point is I don't feel that I've conveyed the emotion at the scale I intended to. No where near it.&lt;br /&gt;&lt;br /&gt;Anyway... recently I've felt creative again. And although you might look at this image and be impressed, you should know in advance that creating it only required a few clicks here and there. Yes, I did apply subjective randomness to it... I did try to influence its message. But it's still cookie cutter. It's my result of following a starfield photoshop tutorial, courtesy of &lt;a href="http://www.artofgregmartin.com"&gt;Greg Martin&lt;/a&gt;, a very skilled artist.&lt;br /&gt;&lt;br /&gt;This is my attempt to convey the infinite depth I feel inside my mind to you... this is my attempt to try and understand that depth myself. But it doesn't even get close.&lt;br /&gt;&lt;br /&gt;&lt;div align=center&gt;&lt;a href="http://home.socal.rr.com/infinity88/MyMindsHome.gif"&gt;My Mind's Home&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;(view it full screen to avoid blurriness)&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-108968328804302599?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://home.socal.rr.com/infinity88/MyMindsHome.gif' title='Understanding Infinity'/><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/108968328804302599/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=108968328804302599' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/108968328804302599'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/108968328804302599'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2004/07/understanding-infinity.html' title='Understanding Infinity'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-108552702728882133</id><published>2004-05-25T16:03:00.000-07:00</published><updated>2006-02-14T19:34:44.546-08:00</updated><title type='text'>Binding a DataGrid to an arraylist of strings</title><content type='html'>...or any simple value type for that matter.&lt;br /&gt;&lt;br /&gt;A friend of mine asked me this question and of course it sounds simple. All he wanted to do was:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;asp:Datagrid id="grid" runat="server"&gt;&lt;br /&gt; &amp;lt;Columns&gt;&lt;br /&gt;  &amp;lt;asp:BoundColumn DataField="..."/&gt;&lt;br /&gt; &amp;lt;/Columns&gt;&lt;br /&gt;&amp;lt;/asp:Datagrid&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The question was what to put as the DataField, since he's binding an arraylist of strings, as in:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;ArrayList list = new ArrayList();&lt;br /&gt;list.Add("1");&lt;br /&gt;list.Add("2");&lt;br /&gt;list.Add("3");&lt;br /&gt;grid.DataSource = list;&lt;br /&gt;grid.DataBind();&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;What indeed? There's no property on the string data type that returns the string. Doing a little google searching didn't turn up anything satisfactory. One idea was to wrap up the array list into a hashtable (where you can use Key/Value), or to make a custom class and bind that. Yuck, thats a hack! It isn't reusable at all -- and most importantly, it might be a designer messing with the aspx (or ascx) page, and they can't and shouldn't have to write code to accomplish the task. Here's what I would consider the "right" way, which requires zero code changes:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;asp:Datagrid id="grid" runat="server"&gt;&lt;br /&gt; &amp;lt;Columns&gt;&lt;br /&gt;  &amp;lt;asp:TemplateColumn&gt;&lt;br /&gt;   &amp;lt;ItemTemplate&gt;&lt;br /&gt;    &amp;lt;%# Container.DataItem %&gt;&lt;br /&gt;   &amp;lt;/ItemTemplate&gt;&lt;br /&gt;  &amp;lt;asp:TemplateColumn&gt;&lt;br /&gt; &amp;lt;/Columns&gt;&lt;br /&gt;&amp;lt;/asp:Datagrid&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-108552702728882133?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/108552702728882133/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=108552702728882133' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/108552702728882133'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/108552702728882133'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2004/05/binding-datagrid-to-arraylist-of.html' title='Binding a DataGrid to an arraylist of strings'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-108528343640292604</id><published>2004-05-22T20:37:00.000-07:00</published><updated>2004-05-22T20:49:55.656-07:00</updated><title type='text'>Power-napping</title><content type='html'>That mid-day dip in alertness really grabs hold of me sometimes. Sure, staying up researching longhorn until 1:30 the night before doesn't help. Neither does getting up before the sun rises (an evilness in today's world). But that mid-day dip still seems unnaturally strong. The interesting thing is it's always around 2pm at its worst... if I manage to fight through it, by 3pm I'm back up to normal, and as chip as ever. I know what you're thinking -- its the lunch! Yah I've heard that before but I don't believe it. It doesn't matter when or what I have to eat. Even if I eat nothing.&lt;br /&gt;&lt;br /&gt;What's the deal??? Is there something in the air conditioning ducts? It's as if the human body was meant to take a nice little siesta in the middle of the day. &lt;br /&gt;&lt;br /&gt;As far as I can tell via google that's a generally accepted idea, and many studies have shown that a 15-20 minute "powernap" once or twice a day can increase overall alertness. Say what?? Where was this study when some genious invented the 8 hour work day? &amp;lt;yawn&gt;... good night.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-108528343640292604?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/108528343640292604/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=108528343640292604' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/108528343640292604'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/108528343640292604'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2004/05/power-napping.html' title='Power-napping'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7078755.post-108526238115472437</id><published>2004-05-22T14:42:00.000-07:00</published><updated>2004-05-22T20:48:05.570-07:00</updated><title type='text'>Hello World</title><content type='html'>This will be a place for my thoughts. Thoughts about the world, the universe, philosophy, yadda yadda yadda. They'll be wierd, sometimes they won't make any sense, sometimes they will be completely wrong. That's cool though... at least I've got a place to put them. Maybe someone out there will stumble upon my little island of thoughts here, probably through some completely unrelated google search, like "&lt;a href="http://www.google.com/search?hl=en&amp;lr=&amp;ie=UTF-8&amp;q=%22popcorn+and+fish%22"&gt;popcorn and fish&lt;/a&gt;" or "&lt;a href="http://www.google.com/search?sourceid=navclient&amp;ie=UTF-8&amp;oe=UTF-8&amp;q=%22what+is+iodized+salt%22"&gt;what is iodized salt&lt;/a&gt;", or what-have-you.&lt;br /&gt;&lt;br /&gt;If you do happen upon this blog, be sure to drop me a comment or two... I promise I won't delete it.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7078755-108526238115472437?l=infinitiesloop.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://infinitiesloop.blogspot.com/feeds/108526238115472437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7078755&amp;postID=108526238115472437' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/108526238115472437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7078755/posts/default/108526238115472437'/><link rel='alternate' type='text/html' href='http://infinitiesloop.blogspot.com/2004/05/hello-world.html' title='Hello World'/><author><name>Infinity88</name><uri>http://www.blogger.com/profile/03498086707006893731</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://home.socal.rr.com/infinity88/fireflys.gif'/></author><thr:total>0</thr:total></entry></feed>
