<?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:blogger='http://schemas.google.com/blogger/2008' 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-1384162512306361231</id><updated>2024-11-01T03:38:11.913-07:00</updated><category term=".Net Developer"/><category term="ASP.NET"/><category term="ASP.NET Pattern"/><category term="ASP.NET Web Matrix"/><category term="Iphone"/><category term="News"/><category term="SQL Server 2008"/><category term="hungarian notation"/><title type='text'>Jeffrey Valeroso</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jfvaleroso.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://jfvaleroso.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jeffrey Valeroso</name><uri>http://www.blogger.com/profile/08001080593078135203</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1384162512306361231.post-1217191895368561662</id><published>2011-10-11T18:16:00.000-07:00</published><updated>2011-10-11T18:17:54.099-07:00</updated><title type='text'>The Joel Test: 12 Steps to Better Code by Joel Spolsky</title><content type='html'>Have you ever heard of &lt;a href=&quot;http://www.sei.cmu.edu/sema/welcome.html&quot;&gt;SEMA&lt;/a&gt;? It&#39;s a fairly esoteric system for measuring how good a software team is. No, &lt;i&gt;wait! Don&#39;t follow that link! &lt;/i&gt;It will take you about six years just to &lt;i&gt;understand&lt;/i&gt; that stuff. So I&#39;ve come up with my own, highly irresponsible, sloppy test to rate the quality of a software team. The great part about it is that it takes about 3 minutes. With all the time you save, you can go to medical school.&lt;br /&gt;
&lt;br /&gt;
&lt;center&gt;&lt;table border=&quot;0&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;align: center; width: 400px;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td colspan=&quot;3&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td background=&quot;/pictures/ShadedPaperBorders/IMG84.gif&quot;&gt;&lt;img height=&quot;14&quot; src=&quot;http://www.blogger.com/pictures/ShadedPaperBorders/IMG81.gif&quot; width=&quot;9&quot; /&gt;&lt;/td&gt;&lt;td bgcolor=&quot;#ffffff&quot; width=&quot;100%&quot;&gt;&lt;table border=&quot;0&quot; cellpadding=&quot;10&quot; cellspacing=&quot;0&quot; style=&quot;width: 379px;&quot;&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left;&quot;&gt;&lt;div align=&quot;center&quot;&gt;
&lt;span style=&quot;color: #333333; font-size: medium;&quot;&gt;The Joel Test&lt;/span&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Do you use source control? &lt;/li&gt;
&lt;li&gt;Can you make a build in one step? &lt;/li&gt;
&lt;li&gt;Do you make daily builds? &lt;/li&gt;
&lt;li&gt;Do you have a bug database? &lt;/li&gt;
&lt;li&gt;Do you fix bugs before writing new code? &lt;/li&gt;
&lt;li&gt;Do you have an up-to-date schedule? &lt;/li&gt;
&lt;li&gt;Do you have a spec? &lt;/li&gt;
&lt;li&gt;Do programmers have quiet working conditions? &lt;/li&gt;
&lt;li&gt;Do you use the best tools money can buy? &lt;/li&gt;
&lt;li&gt;Do you have testers? &lt;/li&gt;
&lt;li&gt;Do new candidates write code during their interview? &lt;/li&gt;
&lt;li&gt;Do you do hallway usability testing? &lt;/li&gt;
&lt;/ol&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/td&gt;&lt;td align=&quot;right&quot; background=&quot;/pictures/ShadedPaperBorders/IMG85.gif&quot; valign=&quot;top&quot; width=&quot;12&quot;&gt;&lt;img height=&quot;11&quot; src=&quot;http://www.blogger.com/pictures/ShadedPaperBorders/IMG82.gif&quot; width=&quot;12&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;3&quot;&gt;&lt;img height=&quot;16&quot; src=&quot;http://www.blogger.com/pictures/ShadedPaperBorders/IMG83.gif&quot; width=&quot;100%&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/center&gt;The neat thing about The Joel Test is that it&#39;s easy to get a quick &lt;b&gt;yes&lt;/b&gt; or &lt;b&gt;no&lt;/b&gt; to each question. You don&#39;t have to figure out lines-of-code-per-day or average-bugs-per-inflection-point. Give your team 1 point for each &quot;yes&quot; answer.&amp;nbsp;The bummer about The Joel Test is that you &lt;i&gt;really shouldn&#39;t &lt;/i&gt;use it to make sure that your nuclear power plant software is safe. &lt;br /&gt;
A score of 12 is perfect, 11 is tolerable, but 10 or lower and you&#39;ve got serious problems. The truth is that most software organizations are running with a score of 2 or 3, and they need &lt;i&gt;serious&lt;/i&gt; help, because companies like Microsoft run at 12 full-time.&lt;br /&gt;
Of course, these are not the only factors that determine success or failure: in particular, if you have a great software team working on a product that nobody wants, well, people aren&#39;t going to want it. And it&#39;s possible to imagine a team of &quot;gunslingers&quot; that doesn&#39;t do any of this stuff that still manages to produce incredible software that changes the world. But, all else being equal, if you get these 12 things right, you&#39;ll have a disciplined team that can consistently deliver.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;1. Do you use source control?&lt;/b&gt;I&#39;ve used commercial source control packages, and I&#39;ve used &lt;a href=&quot;http://www.cvshome.org/&quot;&gt;CVS&lt;/a&gt;, which is free, and let me tell you, CVS is &lt;i&gt;fine&lt;/i&gt;. But if you don&#39;t have source control, you&#39;re going to stress out trying to get programmers to work together. Programmers have no way to know what other people did. Mistakes can&#39;t be rolled back easily. The other neat thing about source control systems is that the source code itself is checked out on every programmer&#39;s hard drive -- I&#39;ve never heard of a project using source control that lost a lot of code.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;2. Can you make a build in one step?&lt;/b&gt;By this I mean: how many steps does it take to make a shipping build from the latest source snapshot? On good teams, there&#39;s a single script you can run that does a full checkout from scratch, rebuilds every line of code, makes the EXEs, in all their various versions, languages, and #ifdef combinations, creates the installation package, and creates the final media -- CDROM layout, download website, whatever.&lt;br /&gt;
If the process takes any more than one step, it is prone to errors. And when you get closer to shipping, you want to have a very fast cycle of fixing the &quot;last&quot; bug, making the final EXEs, etc. If it takes 20 steps to compile the code, run the installation builder, etc., you&#39;re going to go crazy and you&#39;re going to make silly mistakes.&lt;br /&gt;
For this very reason, the last company I worked at switched from WISE to InstallShield: we &lt;i&gt;required&lt;/i&gt; that the installation process be able to run, from a script, automatically, overnight, using the NT scheduler, and WISE couldn&#39;t run from the scheduler overnight, so we threw it out. (The kind folks at WISE assure me that their latest version does support nightly builds.)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;3. Do you make daily builds?&lt;/b&gt;When you&#39;re using source control, sometimes one programmer accidentally checks in something that breaks the build. For example, they&#39;ve added a new source file, and everything compiles fine on their machine, but they forgot to add the source file to the code repository. So they lock their machine and go home, oblivious and happy. But nobody else can work, so they have to go home too, unhappy.&lt;br /&gt;
Breaking the build is so bad (and so common) that it helps to make daily builds, to insure that no breakage goes unnoticed. On large teams, one good way to insure that breakages are fixed right away is to do the daily build every afternoon at, say, lunchtime. Everyone does as many checkins as possible before lunch. When they come back, the build is done. If it worked, great! Everybody checks out the latest version of the source and goes on working. If the build failed, you fix it, but everybody can keep on working with the pre-build, unbroken version of the source.&lt;br /&gt;
On the Excel team we had a rule that whoever broke the build, as their &quot;punishment&quot;, was responsible for babysitting the builds until someone else broke it. This was a good incentive not to break the build, and a good way to rotate everyone through the build process so that everyone learned how it worked.&lt;br /&gt;
Read more about daily builds in my article &lt;a href=&quot;http://www.blogger.com/articles/fog0000000023.html&quot;&gt;Daily Builds are Your Friend&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;4. Do you have a bug database?&lt;/b&gt;I don&#39;t care what you say. If you are developing code, even on a team of one, without an organized database listing all known bugs in the code, you are going to ship low quality code. Lots of programmers think they can hold the bug list in their heads. Nonsense. I can&#39;t remember more than two or three bugs at a time, and the next morning, or in the rush of shipping, they are forgotten. You absolutely have to keep track of bugs formally.&lt;br /&gt;
Bug databases can be complicated or simple. A minimal useful bug database must include the following data for every bug:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;complete steps to reproduce the bug &lt;/li&gt;
&lt;li&gt;expected behavior &lt;/li&gt;
&lt;li&gt;observed (buggy) behavior &lt;/li&gt;
&lt;li&gt;who it&#39;s assigned to &lt;/li&gt;
&lt;li&gt;whether it has been fixed or not &lt;/li&gt;
&lt;/ul&gt;
If the complexity of bug tracking software is the only thing stopping you from tracking your bugs, just make a simple 5 column table with these crucial fields and &lt;i&gt;start using it&lt;/i&gt;.&lt;br /&gt;
For more on bug tracking, read &lt;a href=&quot;http://www.blogger.com/articles/fog0000000029.html&quot;&gt;Painless Bug Tracking&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;5. Do you fix bugs before writing new code?&lt;/b&gt;The very first version of Microsoft Word for Windows was considered a &quot;death march&quot; project. It took forever. It kept slipping. The whole team was working ridiculous hours, the project was delayed again, and again, and again, and the stress was incredible. When the dang thing finally shipped, years late, Microsoft sent the whole team off to Cancun for a vacation, then sat down for some serious soul-searching.&lt;br /&gt;
What they realized was that the project managers had been so insistent on keeping to the &quot;schedule&quot; that programmers simply rushed through the coding process, writing extremely bad code, because the bug fixing phase was not a part of the formal schedule. There was no attempt to keep the bug-count down. Quite the opposite. The story goes that one programmer, who had to write the code to calculate the height of a line of text, simply wrote &quot;return 12;&quot; and waited for the bug report to come in about how his function is not always correct. The schedule was merely a checklist of features waiting to be turned into bugs. In the post-mortem, this was referred to as &quot;infinite defects methodology&quot;.&lt;br /&gt;
To correct the problem, Microsoft universally adopted something called a &quot;zero defects methodology&quot;. Many of the programmers in the company giggled, since it sounded like management thought they could reduce the bug count by executive fiat. Actually, &quot;zero defects&quot; meant that at any given time, the highest priority is to eliminate bugs &lt;i&gt;before&lt;/i&gt; writing any new code. Here&#39;s why.&lt;br /&gt;
In general, the longer you wait before fixing a bug, the costlier (in time and money) it is to fix.&lt;br /&gt;
For example, when you make a typo or syntax error that the compiler catches, fixing it is basically trivial.&lt;br /&gt;
When you have a bug in your code that you see the first time you try to run it, you will be able to fix it in no time at all, because all the code is still fresh in your mind.&lt;br /&gt;
If you find a bug in some code that you wrote a few days ago, it will take you a while to hunt it down, but when you reread the code you wrote, you&#39;ll remember everything and you&#39;ll be able to fix the bug in a reasonable amount of time.&lt;br /&gt;
But if you find a bug in code that you wrote a few &lt;i&gt;months&lt;/i&gt; ago, you&#39;ll probably have forgotten a lot of things about that code, and it&#39;s much harder to fix. By that time you may be fixing somebody &lt;i&gt;else&#39;s&lt;/i&gt; code, and they may be in Aruba on vacation, in which case, fixing the bug is like science: you have to be slow, methodical, and meticulous, and you can&#39;t be sure how long it will take to discover the cure.&lt;br /&gt;
And if you find a bug in code that has &lt;i&gt;already shipped&lt;/i&gt;, you&#39;re going to incur incredible expense getting it fixed.&lt;br /&gt;
That&#39;s one reason to fix bugs right away: because it takes less time. There&#39;s another reason, which relates to the fact that it&#39;s easier to &lt;i&gt;predict&lt;/i&gt; how long it will take to write new code than to fix an existing bug. For example, if I asked you to predict how long it would take to write the code to sort a list, you could give me a pretty good estimate. But if I asked you how to predict how long it would take to fix that bug where your code doesn&#39;t work if Internet Explorer 5.5 is installed, you can&#39;t even &lt;i&gt;guess&lt;/i&gt;, because you don&#39;t know (by definition) what&#39;s &lt;i&gt;causing&lt;/i&gt; the bug. It could take 3 days to track it down, or it could take 2 minutes.&lt;br /&gt;
What this means is that if you have a schedule with a lot of bugs remaining to be fixed, the schedule is unreliable. But if you&#39;ve fixed all the &lt;i&gt;known&lt;/i&gt; bugs, and all that&#39;s left is new code, then your schedule will be stunningly more accurate.&lt;br /&gt;
Another great thing about keeping the bug count at zero is that you can respond much faster to competition. Some programmers think of this as keeping the product &lt;i&gt;ready to ship&lt;/i&gt; at all times. Then if your competitor introduces a killer new feature that is stealing your customers, you can implement just that feature and ship on the spot, without having to fix a large number of accumulated bugs.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;6. Do you have an up-to-date schedule?&lt;/b&gt;Which brings us to schedules. If your code is at all important to the business, there are lots of reasons why it&#39;s important to the business to know when the code is going to be done. Programmers are notoriously crabby about making schedules. &quot;It will be done when it&#39;s done!&quot; they scream at the business people.&lt;br /&gt;
Unfortunately, that just doesn&#39;t cut it. There are too many planning decisions that the business needs to make well in advance of shipping the code: demos, trade shows, advertising, etc. And the only way to do this is to have a schedule, and to keep it up to date.&lt;br /&gt;
The other crucial thing about having a schedule is that it forces you to decide what features you are going to do, and then it forces you to pick the least important features and &lt;i&gt;cut them&lt;/i&gt; rather than slipping into &lt;a href=&quot;http://www.netmeg.net/jargon/terms/c/creeping_featuritis.html&quot;&gt;featuritis&lt;/a&gt; (a.k.a. scope creep).&lt;br /&gt;
Keeping schedules does not have to be hard. Read my article &lt;a href=&quot;http://www.blogger.com/articles/fog0000000245.html&quot;&gt;Painless Software Schedules&lt;/a&gt;, which describes a simple way to make great schedules.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;7. Do you have a spec?&lt;/b&gt;Writing specs is like flossing: everybody agrees that it&#39;s a good thing, but nobody does it.&lt;br /&gt;
I&#39;m not sure why this is, but it&#39;s probably because most programmers hate writing documents. As a result, when teams consisting solely of programmers attack a problem, they prefer to express their solution in code, rather than in documents. They would much rather dive in and write code than produce a spec first.&lt;br /&gt;
At the design stage, when you discover problems, you can fix them easily by editing a few lines of text. Once the code is written, the cost of fixing problems is dramatically higher, both emotionally (people hate to throw away code) and in terms of time, so there&#39;s resistance to actually fixing the problems. Software that wasn&#39;t built from a spec usually winds up badly designed and the schedule gets out of control.&amp;nbsp; This seems to have been the problem at Netscape, where the first four versions grew into such a mess that management &lt;a href=&quot;http://www.blogger.com/articles/fog0000000069.html&quot;&gt;stupidly decided&lt;/a&gt; to throw out the code and start over. And then they made this mistake all over again with Mozilla, creating a monster that spun out of control and took &lt;i&gt;several years&lt;/i&gt; to get to alpha stage.&lt;br /&gt;
My pet theory is that this problem can be fixed by teaching programmers to be less reluctant writers by sending them off to take &lt;a href=&quot;http://www.yale.edu/engl450b/&quot;&gt;an intensive course in writing&lt;/a&gt;. Another solution is to hire smart program managers who produce the written spec. In either case, you should enforce the simple rule &quot;no code without spec&quot;.&lt;br /&gt;
Learn all about writing specs by reading my &lt;a href=&quot;http://www.blogger.com/articles/fog0000000036.html&quot;&gt;4-part series&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;8. Do programmers have quiet working conditions?&lt;/b&gt;There are extensively documented productivity gains provided by giving knowledge workers space, quiet, and privacy. The classic software management book &lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0932633439/ref=nosim/joelonsoftware/&quot;&gt;Peopleware&lt;/a&gt; documents these productivity benefits extensively.&lt;br /&gt;
Here&#39;s the trouble. We all know that knowledge workers work best by getting into &quot;flow&quot;, also known as being &quot;in the zone&quot;, where they are fully concentrated on their work and fully tuned out of their environment. They lose track of time and produce great stuff through absolute concentration. This is when they get all of their productive work done. Writers, programmers, scientists, and even basketball players will tell you about being in the zone. &lt;br /&gt;
The trouble is, getting into &quot;the zone&quot; is not easy. When you try to measure it, it looks like it takes an average of 15 minutes to start working at maximum productivity. Sometimes, if you&#39;re tired or have already done a lot of creative work that day, you just can&#39;t get into the zone and you spend the rest of your work day fiddling around, reading the web, playing Tetris. &lt;br /&gt;
The other trouble is that it&#39;s so easy to get knocked &lt;i&gt;out&lt;/i&gt; of the zone. Noise, phone calls, going out for lunch, having to drive 5 minutes to Starbucks for coffee, and interruptions by coworkers -- &lt;i&gt;especially&lt;/i&gt; interruptions by coworkers -- all knock you out of the zone. If a coworker asks you a question, causing a 1 minute interruption, but this knocks you out of the zone badly enough that it takes you half an hour to get productive again, your overall productivity is in serious trouble. If you&#39;re in a noisy bullpen environment like the type that caffeinated dotcoms love to create, with marketing guys screaming on the phone next to programmers, your productivity will plunge as knowledge workers get interrupted time after time and never get into the zone. &lt;br /&gt;
With programmers, it&#39;s especially hard. Productivity depends on being able to juggle a lot of little details in short term memory all at once. Any kind of interruption can cause these details to come crashing down. When you resume work, you can&#39;t remember any of the details (like local variable names you were using, or where you were up to in implementing that search algorithm) and you have to keep looking these things up, which slows you down a lot until you get back up to speed. &lt;br /&gt;
Here&#39;s the simple algebra. Let&#39;s say (as the evidence seems to suggest) that if we interrupt a programmer, even for a minute, we&#39;re really blowing away 15 minutes of productivity. For this example, lets put two programmers, Jeff and Mutt, in open cubicles next to each other in a standard Dilbert veal-fattening farm. Mutt can&#39;t remember the name of the Unicode version of the strcpy function. He could look it up, which takes 30 seconds, or he could ask Jeff, which takes 15 seconds. Since he&#39;s sitting right next to Jeff, he asks Jeff. Jeff gets distracted and loses 15 minutes of productivity (to save Mutt 15 seconds). &lt;br /&gt;
Now let&#39;s move them into separate offices with walls and doors. Now when Mutt can&#39;t remember the name of that function, he could look it up, which still takes 30 seconds, or he could ask Jeff, which now takes 45 seconds and involves standing up (not an easy task given the average physical fitness of programmers!). So he looks it up. So now Mutt loses 30 seconds of productivity, but we save 15 minutes for Jeff. Ahhh!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;9. Do you use the best tools money can buy?&lt;/b&gt;Writing code in a compiled language is one of the last things that still can&#39;t be done instantly on a garden variety home computer. If your compilation process takes more than a few seconds, getting the latest and greatest computer is going to save you time. If compiling takes even 15 seconds, programmers will get bored while the compiler runs and switch over to reading &lt;a href=&quot;http://www.theonion.com/&quot;&gt;The Onion&lt;/a&gt;, which will suck them in and kill hours of productivity.&lt;br /&gt;
Debugging GUI code with a single monitor system is painful if not impossible. If you&#39;re writing GUI code, two monitors will make things much easier.&lt;br /&gt;
Most programmers eventually have to manipulate bitmaps for icons or toolbars, and most programmers don&#39;t have a good bitmap editor available. Trying to use Microsoft Paint to manipulate bitmaps is a joke, but that&#39;s what most programmers have to do.&lt;br /&gt;
At &lt;a href=&quot;http://www.blogger.com/articles/TwoStories.html&quot;&gt;my last job&lt;/a&gt;, the system administrator kept sending me automated spam complaining that I was using more than ... get this ... 220 megabytes of hard drive space on the server. I pointed out that given the price of hard drives these days, the cost of this space was significantly less than the cost of the &lt;i&gt;toilet paper&lt;/i&gt; I used. Spending even 10 minutes cleaning up my directory would be a fabulous waste of productivity.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Top notch development teams don&#39;t torture their programmers.&lt;/b&gt; Even minor frustrations caused by using underpowered tools add up, making programmers grumpy and unhappy. And a grumpy programmer is an unproductive programmer.&lt;br /&gt;
To add to all this... programmers are easily bribed by giving them the coolest, latest stuff. This is a far cheaper way to get them to work for you than actually paying competitive salaries!&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;10. Do you have testers?&lt;/b&gt;If your team doesn&#39;t have dedicated testers, at least one for every two or three programmers, you are either shipping buggy products, or you&#39;re wasting money by having $100/hour programmers do work that can be done by $30/hour testers. Skimping on testers is such an outrageous false economy that I&#39;m simply blown away that more people don&#39;t recognize it.&lt;br /&gt;
Read &lt;a href=&quot;http://www.blogger.com/articles/fog0000000067.html&quot;&gt;Top Five (Wrong) Reasons You Don&#39;t Have Testers&lt;/a&gt;, an article I wrote about this subject.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;11. Do new candidates write code during their interview?&lt;/b&gt;Would you hire a magician without asking them to show you some magic tricks? Of course not.&lt;br /&gt;
Would you hire a caterer for your wedding without tasting their food? I doubt it. (Unless it&#39;s Aunt Marge, and she would hate you for&lt;i&gt;ever&lt;/i&gt; if you didn&#39;t let her make her &quot;famous&quot; chopped liver cake).&lt;br /&gt;
Yet, every day, programmers are hired on the basis of an impressive resumé or because the interviewer enjoyed chatting with them. Or they are asked trivia questions (&quot;what&#39;s the difference between CreateDialog() and DialogBox()?&quot;) which could be answered by looking at the documentation. You don&#39;t care if they have memorized thousands of trivia about programming, you care if they are able to produce code. Or, even worse, they are asked &quot;AHA!&quot; questions: the kind of questions that seem easy when you know the answer, but if you don&#39;t know the answer, they are impossible.&lt;br /&gt;
Please, just &lt;i&gt;stop doing this&lt;/i&gt;. Do whatever you want during interviews, but make the candidate &lt;i&gt;write some code&lt;/i&gt;. (For more advice, read my &lt;a href=&quot;http://www.blogger.com/articles/fog0000000073.html&quot;&gt;Guerrilla Guide to Interviewing&lt;/a&gt;.)&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;12. Do you do hallway usability testing?&lt;/b&gt;A &lt;i&gt;hallway usability test&lt;/i&gt; is where you grab the next person that passes by in the hallway and force them to try to use the code you just wrote. If you do this to five people, you will learn 95% of what there is to learn about usability problems in your code.&lt;br /&gt;
Good user interface design is not as hard as you would think, and it&#39;s crucial if you want customers to love and buy your product. You can read my &lt;a href=&quot;http://www.blogger.com/uibook/chapters/fog0000000057.html&quot;&gt;free online book on UI design&lt;/a&gt;, a short primer for programmers.&lt;br /&gt;
But the most important thing about user interfaces is that if you show your program to a handful of people, (in fact, five or six is enough) you will quickly discover the biggest problems people are having. Read &lt;a href=&quot;http://www.useit.com/alertbox/20000319.html&quot;&gt;Jakob Nielsen&#39;s article&lt;/a&gt; explaining why. Even if your UI design skills are lacking, as long as you force yourself to do hallway usability tests, which cost nothing, your UI will be much, much better.</content><link rel='replies' type='application/atom+xml' href='http://jfvaleroso.blogspot.com/feeds/1217191895368561662/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://jfvaleroso.blogspot.com/2011/10/joel-test-12-steps-to-better-code-by.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/1217191895368561662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/1217191895368561662'/><link rel='alternate' type='text/html' href='http://jfvaleroso.blogspot.com/2011/10/joel-test-12-steps-to-better-code-by.html' title='The Joel Test: 12 Steps to Better Code by Joel Spolsky'/><author><name>Jeffrey Valeroso</name><uri>http://www.blogger.com/profile/08001080593078135203</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1384162512306361231.post-4826065688585628878</id><published>2011-10-05T17:34:00.001-07:00</published><updated>2011-10-05T17:34:56.781-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="News"/><title type='text'>Steve Jobs, Apple founder, dies</title><content type='html'>&lt;a href=&quot;http://edition.cnn.com/2011/10/05/us/obit-steve-jobs/index.html?hpt=hp_t1&quot; style=&quot;clear: left; float: left; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&#39;Great innovator&#39; succumbs to illness&quot; border=&quot;0&quot; height=&quot;234&quot; hspace=&quot;0&quot; src=&quot;http://i.cdn.turner.com/cnn/2011/images/10/05/c1main.steve.jobs.01.gi.jpg&quot; width=&quot;416&quot; /&gt;&lt;/a&gt;&lt;strong&gt;(CNN)&lt;/strong&gt; -- Steve Jobs, the visionary in the black turtleneck  who &lt;a href=&quot;http://www.apple.com/&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #004276;&quot;&gt;co-founded Apple&lt;/span&gt;&lt;/a&gt; in a  Silicon Valley garage, built it into the world&#39;s leading tech company and led a  mobile-computing revolution with wildly popular devices such as the iPhone, died  Wednesday. He was 56.&lt;br /&gt;
&lt;br /&gt;
The hard-driving executive pioneered the concept of the personal computer and  of navigating them by clicking onscreen images with a mouse. In more recent  years, he introduced the iPod portable music player, the iPhone and the iPad  tablet -- all of which changed how we consume content in the digital age.&lt;br /&gt;
&lt;br /&gt;
His friends and Apple fans on Wednesday night mourned the passing of a tech  titan.&lt;br /&gt;
&lt;br /&gt;
&quot;Steve&#39;s brilliance, passion and energy were the source of countless  innovations that enrich and improve all of our lives,&quot; Apple said in a  statement. &quot;The world is immeasurably better because of Steve.&quot;&lt;br /&gt;
&lt;br /&gt;
More than one pundit, praising Jobs&#39; ability to transform entire industries  with his inventions, called him a modern-day Leonardo Da Vinci.&lt;br /&gt;
&lt;br /&gt;
&quot;Steve Jobs is one of the great innovators in the history of modern  capitalism,&quot; New York Times columnist Joe Nocera said in August. &quot;His intuition  has been phenomenal over the years.&quot;&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.cnn.com/2011/TECH/innovation/10/05/steve.jobs.timeline/index.html&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #004276;&quot;&gt;View a time line of Steve Jobs&#39; work&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Jobs&#39; death, while dreaded by Apple&#39;s legions of fans, was not unexpected. He  had battled cancer for years, took a medical leave from Apple in January and  stepped down as chief executive in August because he could &quot;no longer meet (his)  duties and expectations.&quot;&lt;br /&gt;
&lt;br /&gt;
Born February 24, 1955, and then adopted, Jobs grew up in Cupertino,  California -- which would become home to Apple&#39;s headquarters -- and showed an  early interest in electronics. As a teenager, he phoned William Hewlett,  president of Hewlett-Packard, to request parts for a school project. He got  them, along with an offer of a summer job at HP.&lt;br /&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
var currExpandable=&quot;expand110&quot;;
if(typeof CNN.expandableMap===&#39;object&#39;){CNN.expandableMap.push(currExpandable);}
var mObj={};
mObj.type=&#39;video&#39;;
mObj.contentId=&#39;&#39;;
mObj.source=&#39;tech/2011/10/04/velshi-steve-jobs-college.cnn&#39;;
mObj.lgImage=&quot;http://i2.cdn.turner.com/cnn/dam/assets/111004122706-velshi-steve-jobs-college-00000000-story-body.jpg&quot;;
mObj.lgImageX=300;
mObj.lgImageY=169;
mObj.origImageX=&quot;214&quot;;
mObj.origImageY=&quot;120&quot;;
mObj.contentType=&#39;video&#39;;
CNN.expElements.expand110Store=mObj;
&lt;/script&gt; &lt;a href=&quot;&quot; name=&quot;em1&quot;&gt;&lt;/a&gt; &lt;br /&gt;
&lt;div class=&quot;cnn_strylftcntnt cnn_strylftcexpbx&quot; id=&quot;expand110&quot;&gt; &lt;div class=&quot;cnn_strylceclbtn&quot; style=&quot;display: none;&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; height=&quot;23&quot; src=&quot;http://i.cdn.turner.com/cnn/.element/img/3.0/mosaic/bttn_close.gif&quot; width=&quot;58&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;parentMediaContainer&quot; id=&quot;videoContainerexpand110&quot; style=&quot;display: none;&quot;&gt; &lt;div class=&quot;mediaContainer&quot; id=&quot;videoContainerexpand110Media&quot;&gt;&lt;img alt=&quot;&quot; height=&quot;169&quot; src=&quot;http://i2.cdn.turner.com/cnn/dam/assets/111004122706-velshi-steve-jobs-college-00000000-story-body.jpg&quot; width=&quot;300&quot; /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;clickToPlay&quot; id=&quot;clickToPlayvideoContainerexpand110&quot; style=&quot;cursor: pointer;&quot;&gt;&lt;/div&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; class=&quot;box-image&quot; height=&quot;120&quot; src=&quot;http://i2.cdn.turner.com/cnn/dam/assets/111004122706-velshi-steve-jobs-college-00000000-story-body.jpg&quot; style=&quot;cursor: pointer;&quot; width=&quot;214&quot; /&gt;&lt;cite class=&quot;expCaption&quot;&gt;&lt;span&gt;How Steve Jobs grew  up&lt;/span&gt;&lt;/cite&gt; &lt;/div&gt;&lt;script type=&quot;text/javascript&quot;&gt;
var currExpandable=&quot;expand210&quot;;
if(typeof CNN.expandableMap===&#39;object&#39;){CNN.expandableMap.push(currExpandable);}
var mObj={};
mObj.type=&#39;video&#39;;
mObj.contentId=&#39;&#39;;
mObj.source=&#39;us/2011/08/24/bts.steve.jobs.apple.timeline.cnn&#39;;
mObj.lgImage=&quot;http://i2.cdn.turner.com/cnn/dam/assets/110910120835-steve-jobs-san-francisco-06-06-11-story-body.jpg&quot;;
mObj.lgImageX=300;
mObj.lgImageY=169;
mObj.origImageX=&quot;214&quot;;
mObj.origImageY=&quot;120&quot;;
mObj.contentType=&#39;video&#39;;
CNN.expElements.expand210Store=mObj;
&lt;/script&gt; &lt;a href=&quot;&quot; name=&quot;em2&quot;&gt;&lt;/a&gt; &lt;br /&gt;
&lt;div class=&quot;cnn_strylftcntnt cnn_strylftcexpbx&quot; id=&quot;expand210&quot;&gt; &lt;div class=&quot;cnn_strylceclbtn&quot; style=&quot;display: none;&quot;&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; height=&quot;23&quot; src=&quot;http://i.cdn.turner.com/cnn/.element/img/3.0/mosaic/bttn_close.gif&quot; width=&quot;58&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;parentMediaContainer&quot; id=&quot;videoContainerexpand210&quot; style=&quot;display: none;&quot;&gt; &lt;div class=&quot;mediaContainer&quot; id=&quot;videoContainerexpand210Media&quot;&gt;&lt;img alt=&quot;&quot; height=&quot;169&quot; src=&quot;http://i2.cdn.turner.com/cnn/dam/assets/110910120835-steve-jobs-san-francisco-06-06-11-story-body.jpg&quot; width=&quot;300&quot; /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;clickToPlay&quot; id=&quot;clickToPlayvideoContainerexpand210&quot; style=&quot;cursor: pointer;&quot;&gt;&lt;/div&gt;&lt;img alt=&quot;&quot; border=&quot;0&quot; class=&quot;box-image&quot; height=&quot;120&quot; src=&quot;http://i2.cdn.turner.com/cnn/dam/assets/110910120835-steve-jobs-san-francisco-06-06-11-story-body.jpg&quot; style=&quot;cursor: pointer;&quot; width=&quot;214&quot; /&gt;&lt;cite class=&quot;expCaption&quot;&gt;&lt;span&gt;Apple&#39;s passionate  pitchman&lt;/span&gt;&lt;/cite&gt; &lt;/div&gt;&lt;br /&gt;
Jobs dropped out of Oregon&#39;s Reed College after one semester, although he  returned to audit a class in calligraphy, which he says influenced Apple&#39;s  graceful, minimalist aesthetic. He quit one of his first jobs, designing video  games for Atari, to backpack across India and take psychedelic drugs. Those  experiences, Jobs said later, shaped his creative vision.&lt;br /&gt;
&lt;br /&gt;
&quot;You can&#39;t connect the dots looking forward; you can only connect them  looking backwards. So you have to trust that the dots will somehow connect in  your future,&quot; he told Stanford University graduates during a commencement speech  in 2005. &quot;You have to trust in something: your gut, destiny, life, karma,  whatever. This approach has never let me down, and it has made all the  difference in my life.&quot;&lt;br /&gt;
&lt;br /&gt;
While at HP, Jobs befriended Steve Wozniak, who impressed him with his skill  at assembling electronic components. The two later joined a Silicon Valley  computer hobbyists club, and when he was 21, Jobs teamed with Wozniak and two  other men to launch Apple Computer Inc.&lt;br /&gt;
&lt;br /&gt;
It&#39;s long been Silicon Valley legend: Jobs and Wozniak built their first  commercial product, the Apple 1, in Jobs&#39; parents&#39; garage in 1976. Jobs sold his  Volkswagen van to help finance the venture. The primitive computer, priced at  $666.66, had no keyboard or display, and customers had to assemble it  themselves.&lt;br /&gt;
&lt;br /&gt;
The following year, Apple unveiled the Apple II computer at the inaugural  West Coast Computer Faire. The machine was a hit, and the personal computing  revolution was under way.&lt;br /&gt;
&lt;br /&gt;
Jobs was among the first computer engineers to recognize the appeal of the  mouse and the graphical interface, which let users operate computers by clicking  on images instead of writing text.&lt;br /&gt;
&lt;br /&gt;
Apple&#39;s pioneering Macintosh computer launched in early 1984 with a  now-iconic, Orwellian-themed Super Bowl ad. The boxy beige Macintosh sold well,  but the demanding Jobs clashed frequently with colleagues, and in 1986, he was  ousted from Apple after a power struggle.&lt;br /&gt;
&lt;br /&gt;
Then came a 10-year hiatus during which he founded NeXT Computer, whose  pricey, cube-shaped computer workstations never caught on with consumers.&lt;br /&gt;
&lt;br /&gt;
Jobs had more success when he bought Pixar Animation Studios from George  Lucas before the company made it big with &quot;Toy Story.&quot; Jobs brought the same  marketing skill to Pixar that he became known for at Apple. His brief but  emotional pitch for &quot;Finding Nemo,&quot; for example, was a masterful bit of succinct  storytelling.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://ireport.cnn.com/topics/683476&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #004276;&quot;&gt;Share your  memories and images of Steve Jobs&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
In 1996, Apple bought NeXT, returning Jobs to the then-struggling company he  had co-founded. Within a year, he was running Apple again -- older and perhaps  wiser but no less of a perfectionist. And in 2001, he took the stage to  introduce the original iPod, the little white device that transformed portable  music and kick-started Apple&#39;s furious comeback.&lt;br /&gt;
&lt;br /&gt;
Thus began one of the most remarkable second acts in the history of business.  Over the next decade, Jobs wowed launch-event audiences, and consumers, with one  game-changing hit after another: iTunes (2003), the iPhone (2007), the App Store  (2008), and the iPad (2010).&lt;br /&gt;
&lt;br /&gt;
Observers marveled at Jobs&#39; skills as a pitchman, his ability to inspire  godlike devotion among Apple &quot;fanboys&quot; (and scorn from PC fans) and his &quot;one  more thing&quot; surprise announcements. Time after time, he sold people on a product  they didn&#39;t know they needed until he invented it. And all this on an official  annual salary of $1.&lt;br /&gt;
&lt;br /&gt;
He also built a reputation as a hard-driving, mercurial and sometimes  difficult boss who oversaw almost every detail of Apple&#39;s products and rejected  prototypes that didn&#39;t meet his exacting standards.&lt;br /&gt;
&lt;br /&gt;
By the late 2000s, his once-renegade tech company, the David to Microsoft&#39;s  Goliath, was entrenched at the uppermost tier of American business. Apple now  operates more than 300 retail stores in 11 countries. The company has sold more  than 275 million iPods, 100 million iPhones and 25 million iPads worldwide.&lt;br /&gt;
&lt;br /&gt;
Jobs&#39; climb to the top was complete in summer 2011, when Apple listed more  cash reserves than the U.S. Treasury and even briefly surpassed Exxon Mobil as  the world&#39;s most valuable company.&lt;br /&gt;
&lt;br /&gt;
But Jobs&#39; health problems sometimes cast a shadow over his company&#39;s success.  In 2004, he announced to his employees that he was being treated for pancreatic  cancer. He lost weight and appeared unusually gaunt at keynote speeches to Apple  developers, spurring concerns about his health and fluctuations in the company&#39;s  stock price. One wire service accidentally published Jobs&#39; obituary.&lt;br /&gt;
&lt;br /&gt;
Jobs had a secret liver transplant in 2009 in Tennessee during a six-month  medical leave of absence from Apple. He took another medical leave in January  this year. Perhaps mindful of his legacy, he cooperated on his first authorized  biography, scheduled to be published by Simon &amp;amp; Schuster in November.&lt;br /&gt;
&lt;br /&gt;
Jobs is survived by his wife of 20 years, Laurene, and four children,  including one from a prior relationship.&lt;br /&gt;
&lt;br /&gt;
He always spoke with immense pride about what he and his engineers  accomplished at Apple.&lt;br /&gt;
&lt;br /&gt;
&quot;Your work is going to fill a large part of your life, and the only way to be  truly satisfied is to do what you believe is great work. And the only way to do  great work is to love what you do,&quot; he told the Stanford grads in 2005.&lt;br /&gt;
&lt;br /&gt;
&quot;If you haven&#39;t found it yet, keep looking. Don&#39;t settle. As with all matters  of the heart, you&#39;ll know when you find it. And, like any great relationship, it  just gets better and better as the years roll on.&quot;</content><link rel='replies' type='application/atom+xml' href='http://jfvaleroso.blogspot.com/feeds/4826065688585628878/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://jfvaleroso.blogspot.com/2011/10/steve-jobs-apple-founder-dies.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/4826065688585628878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/4826065688585628878'/><link rel='alternate' type='text/html' href='http://jfvaleroso.blogspot.com/2011/10/steve-jobs-apple-founder-dies.html' title='Steve Jobs, Apple founder, dies'/><author><name>Jeffrey Valeroso</name><uri>http://www.blogger.com/profile/08001080593078135203</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1384162512306361231.post-7325466233736899925</id><published>2011-09-10T09:58:00.000-07:00</published><updated>2011-09-10T09:58:58.242-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="SQL Server 2008"/><title type='text'>Fix Firewall Setting to run SQL Server 2008</title><content type='html'>&lt;span class=&quot;label&quot;&gt;&lt;strong&gt;&lt;span style=&quot;font-family: Segoe UI;&quot;&gt;netsh &lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;
The &lt;strong&gt;netsh.exe&lt;/strong&gt; tool can be used by an administrator to configure and monitor Windows-based computers at a command prompt or using a batch file&lt;strong&gt;.&lt;/strong&gt; By using the &lt;strong&gt;netsh&lt;/strong&gt; tool, you can direct the context commands you enter to the appropriate helper, and the helper then performs the command. A helper is a Dynamic Link Library (.dll) file that extends the functionality of the &lt;strong&gt;netsh&lt;/strong&gt; tool by providing configuration, monitoring, and support for one or more services, utilities, or protocols. All operating systems that support SQL Server have a firewall helper. Microsoft Windows Vista and Windows Server 2008 also have an advanced firewall helper called &lt;strong&gt;advfirewall&lt;/strong&gt;. The details of using &lt;strong&gt;netsh&lt;/strong&gt; are not discussed in this topic. However, many of the configuration options described can be configured by using &lt;strong&gt;netsh&lt;/strong&gt;. For example, run the following script at a command prompt to open TCP port 1433:&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;background-color: #ececec; border: 1px solid gray; padding: 5px;&quot;&gt;netsh firewall set portopening protocol = TCP port = 1433 name = SQLPort mode = ENABLE scope = SUBNET profile = CURRENT&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jfvaleroso.blogspot.com/feeds/7325466233736899925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://jfvaleroso.blogspot.com/2011/09/fix-firewall-setting-to-run-sql-server.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/7325466233736899925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/7325466233736899925'/><link rel='alternate' type='text/html' href='http://jfvaleroso.blogspot.com/2011/09/fix-firewall-setting-to-run-sql-server.html' title='Fix Firewall Setting to run SQL Server 2008'/><author><name>Jeffrey Valeroso</name><uri>http://www.blogger.com/profile/08001080593078135203</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1384162512306361231.post-5789486380725667312</id><published>2011-09-10T09:56:00.000-07:00</published><updated>2011-09-10T09:56:54.608-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Iphone"/><title type='text'>The 20 best iPhone apps of 2011 for productive geeks</title><content type='html'>&lt;div id=&quot;siu-horizontal&quot; style=&quot;display: none;&quot;&gt;&lt;div class=&quot;siu siu-horizontal clear&quot;&gt;&lt;div class=&quot;grp siu-cmnt-cont&quot;&gt;&lt;a class=&quot;siu-cmnt&quot; href=&quot;http://www.techrepublic.com/blog/hiner/the-20-best-iphone-apps-of-2011-for-productive-geeks/9133?tag=content;siu-container#talkback&quot;&gt;&lt;span class=&quot;count&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;suffix&quot;&gt;Comments&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;grp clear siu-btns-cont&quot;&gt;&lt;div class=&quot;siu-btn-cont siu-twitter-btn&quot;&gt;&lt;iframe allowtransparency=&quot;true&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://platform.twitter.com/widgets/tweet_button.html?count=horizontal&amp;amp;related=techrepublic%2Czdnet&amp;amp;text=The%2020%20best%20iPhone%20apps%20of%202011%20for%20productive%20geeks&amp;amp;url=http%3A%2F%2Ftek.io%2FpXzvXF&amp;amp;counturl=http%3A%2F%2Fwww.techrepublic.com%2Fblog%2Fhiner%2Fthe-20-best-iphone-apps-of-2011-for-productive-geeks%2F9133&quot; style=&quot;border: currentColor; height: 20px; overflow: hidden; width: 102px;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class=&quot;siu-btn-cont siu-facebook-btn&quot;&gt;&lt;iframe allowtransparency=&quot;true&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://www.facebook.com/plugins/like.php?href=http%3A%2F%2Fwww.techrepublic.com%2Fblog%2Fhiner%2Fthe-20-best-iphone-apps-of-2011-for-productive-geeks%2F9133&amp;amp;send=false&amp;amp;layout=button_count&amp;amp;width=85&amp;amp;height=21&amp;amp;show_faces=false&amp;amp;action=like&amp;amp;colorscheme=light&amp;amp;font=arial&quot; style=&quot;border: currentColor; height: 21px; overflow: hidden; width: 85px;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class=&quot;siu-btn-cont siu-stumbleupon-btn&quot;&gt;&lt;iframe allowtransparency=&quot;true&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot; src=&quot;http://www.stumbleupon.com/badge/embed/1/?url=http%3A%2F%2Fwww.techrepublic.com%2Fblog%2Fhiner%2Fthe-20-best-iphone-apps-of-2011-for-productive-geeks%2F9133&quot; style=&quot;border: currentColor; height: 18px; overflow: hidden; width: 74px;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div class=&quot;siu-btn-cont siu-googleplus-btn&quot;&gt;&lt;div id=&quot;___plusone_1&quot; style=&quot;display: inline-block; float: none; font-size: 1px; height: 20px; line-height: normal; margin: 0px; padding: 0px; text-indent: 0px; vertical-align: baseline; width: 90px;&quot;&gt;&lt;iframe allowtransparency=&quot;true&quot; frameborder=&quot;0&quot; hspace=&quot;0&quot; id=&quot;I2_1315673760283&quot; marginheight=&quot;0&quot; marginwidth=&quot;0&quot; name=&quot;I2_1315673760283&quot; scrolling=&quot;no&quot; src=&quot;https://plusone.google.com/u/0/_/+1/fastbutton?url=http%3A%2F%2Fwww.techrepublic.com%2Fblog%2Fhiner%2Fthe-20-best-iphone-apps-of-2011-for-productive-geeks%2F9133&amp;amp;size=medium&amp;amp;count=true&amp;amp;annotation=&amp;amp;hl=en-US&amp;amp;jsh=r%3Bgc%2F23579912-2b1b2e17#id=I2_1315673760283&amp;amp;parent=http%3A%2F%2Fwww.techrepublic.com&amp;amp;rpctoken=637860051&amp;amp;_methods=onPlusOne%2C_ready%2C_close%2C_open%2C_resizeMe&quot; style=&quot;height: 20px; left: 0px; margin: 0px; position: static; top: 0px; visibility: visible; width: 90px;&quot; tabindex=&quot;-1&quot; title=&quot;+1&quot; vspace=&quot;0&quot; width=&quot;100%&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;grp siu-more-cont&quot;&gt;&lt;a class=&quot;siu-more-btn&quot; href=&quot;&quot;&gt;more +&lt;/a&gt;&lt;div class=&quot;siu-more pop-hidden&quot; style=&quot;position: absolute; visibility: hidden;&quot;&gt;&lt;ul class=&quot;options clear&quot;&gt;&lt;li&gt;&lt;a class=&quot;icon i-email&quot; href=&quot;&quot; shareaction=&quot;email&quot;&gt;Email&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;icon i-print&quot; href=&quot;&quot; shareaction=&quot;print&quot;&gt;Print&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;icon i-trfavorite&quot; href=&quot;&quot; shareaction=&quot;trfavorite&quot;&gt;Add to Favorites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;icon i-delicious&quot; href=&quot;&quot; shareaction=&quot;delicious&quot;&gt;Del.icio.us&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;icon i-digg&quot; href=&quot;&quot; shareaction=&quot;digg&quot;&gt;Digg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;icon i-hackernews&quot; href=&quot;&quot; shareaction=&quot;hackernews&quot;&gt;Hacker News&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;icon i-linkedin&quot; href=&quot;&quot; shareaction=&quot;linkedin&quot;&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;icon i-reddit&quot; href=&quot;&quot; shareaction=&quot;reddit&quot;&gt;Reddit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;icon i-technorati&quot; href=&quot;&quot; shareaction=&quot;technorati&quot;&gt;Technorati&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;content-1 entry space-1 clear&quot;&gt;&lt;div class=&quot;space-1 s-11 c-4&quot;&gt;&lt;div class=&quot;author&quot;&gt;By &lt;a href=&quot;&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Jason Hiner&lt;/span&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;date&quot;&gt;September 6, 2011, 11:42 PM PDT&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span class=&quot;c-6 heavy&quot;&gt;&lt;strong&gt;&lt;span style=&quot;color: #8cbd5b;&quot;&gt;Takeaway: &lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;Jason Hiner offers his top picks for iPhone apps that can help you work smarter and improve your productivity.&lt;br /&gt;
&lt;div class=&quot;content-1 entry space-1 clear&quot;&gt;Mobile apps have become an embarrassment of riches for iPhone and Android. In a world with over 500,000 iPhone apps and over 250,000 Android apps, the toughest part is finding the most useful stuff.&lt;br /&gt;
For iPhone users, I’m going to throw you an assist by sharing my top 20 (&lt;a href=&quot;http://www.techrepublic.com/blog/hiner/25-must-have-iphone-apps-for-productive-geeks/5543&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;this is an update of my 2010 iPhone list&lt;/span&gt;&lt;/a&gt;, and I will update my top Android picks next week). My iPhone picks are all third-party apps that can help you be more productive, streamline regular activities, reduce the number of gadgets in your life, and take advantage of the top benefits that mobile computing has to offer.&lt;br /&gt;
&lt;img alt=&quot;&quot; class=&quot;alignnone size-full wp-image-9137&quot; height=&quot;360&quot; src=&quot;http://i.techrepublic.com.com/blogs/jh-iphone-apps-2011.jpg&quot; title=&quot;JH iPhone apps 2011&quot; width=&quot;500&quot; /&gt;&lt;br /&gt;
&lt;h2&gt;1. &lt;a href=&quot;http://itunes.apple.com/us/app/dropbox/id327630330?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Dropbox&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;Dropbox is a great cloud service that automatically syncs a folder of files between multiple computers (Windows, Mac, or Linux). This app extends Dropbox to the iPhone and includes a built-in reader within the app for PDFs, image files, and Microsoft Office files.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;2. &lt;a href=&quot;http://itunes.apple.com/us/app/evernote/id281796108?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Evernote&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;Once you get used to typing on a virtual keyboard (and it honestly took me over a year to do it), then these devices are great for note taking, and Evernote is a great note taking app. It is similar to Dropbox in that it saves data locally but syncs it across all your machines and devices.&lt;br /&gt;
&lt;h2&gt;3. &lt;a href=&quot;http://itunes.apple.com/us/app/due/id390017969?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Due&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;There are a ton of to-do apps on iPhone but I prefer Due for its simplicity and its audio alerts. However, this is an iPhone-only task list. If you want something that can sync with your PC, Mac, or the Web, then try &lt;a href=&quot;http://itunes.apple.com/us/app/2do-tasks-done-in-style/id303656546?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;2Do&lt;/span&gt;&lt;/a&gt; or &lt;a href=&quot;http://itunes.apple.com/us/app/things/id284971781?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Things&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;4. &lt;a href=&quot;http://itunes.apple.com/us/app/tripit-travel-organizer/id311035142?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Tripit&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;I love Tripit. It is by far the best app I’ve found for keeping track of all my travel itineraries. It is powered by some excellent backend systems. You simply forward your confirmation emails (or use the Gmail plugin to do it automatically) for your flights, hotels, rental cars, and more to Tripit and it automatically organizes them into trips with all your details and confirmation numbers.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;5. &lt;a href=&quot;http://itunes.apple.com/us/app/analytics-app/id303689911?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Analytics App&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;For some reason Google doesn’t have an official app (for either iPhone or Android) for Google Analytics. The best one I’ve found to go deep into all of the data is Analytics App.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;6. &lt;a href=&quot;http://itunes.apple.com/us/app/ego/id306785502?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Ego&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;Even better than Analytics App for a quick-glance dashboard is Ego. It shows basic data from Google Analytics as well as a bunch of other sources, including Squarespace, Twitter, and Feedburner.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;7. &lt;a href=&quot;http://itunes.apple.com/us/app/twitter/id333903271?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Twitter&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;The official Twitter app (formerly known as Tweetie) is still the best Twitter client on iPhone (although Osfoora is catching up). Twitter itself is an amazing instant-intelligence engine. Two other great social media apps for iPhone are &lt;a href=&quot;http://itunes.apple.com/us/app/google/id447119634?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Google+&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;http://itunes.apple.com/us/app/foursquare/id306934924?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Foursquare&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;8. &lt;a href=&quot;http://itunes.apple.com/us/app/reeder/id325502379?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Reeder&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;Twitter has largely replaced RSS for me for finding and filtering the latest news. However, I still track some RSS feeds and the best tool I’ve found to do it with is Reeder. It syncs with Google Reader so it’s easy to flip between the mobile app and the desktop, plus the app lets you share to Twitter (and Facebook) and save to Instapaper and ReadItLater.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;9. &lt;a href=&quot;http://itunes.apple.com/us/app/kindle/id302584613?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Amazon Kindle&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;I’ve never fully warmed up to the Amazon Kindle e-reader, but I’m a big fan of the Kindle iPhone app. Since it was released I’ve read a lot more books simply because my phone is always with me and I can pull it out and read a few pages anytime I’ve got a couple minutes free. Alternatives: &lt;a href=&quot;http://itunes.apple.com/us/app/nook-for-iphone-from-barnes/id384910586?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Nook&lt;/span&gt;&lt;/a&gt;, &lt;a href=&quot;http://itunes.apple.com/us/app/ibooks/id364709193?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;iBooks&lt;/span&gt;&lt;/a&gt;, and &lt;a href=&quot;http://itunes.apple.com/us/app/id301259483?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Kobo&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;10. &lt;a href=&quot;http://itunes.apple.com/us/app/audible/id379693831?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Audible&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;As much as I like the Kindle ebooks, I actually consume more books as audiobooks via Audible. In the past you could download these and sync them via iTunes. But Audible now has its own app, which lets you connect to your Audible library and download over the air, and even gives you a self-contained player optimized for audiobooks.&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;11. &lt;a href=&quot;http://itunes.apple.com/us/app/podcaster-formerly-rss-player/id377195245?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Podcaster&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;Sure, you can use iTunes and the built-in iPod app to listen to podcasts, but if you’re an avid podcast listener (I regularly follow This Week in Tech, Buzz Out Loud, and Tech News Today) then the app Podcaster offers a better experience. You can download over the air (so that you don’t have to constantly sync to a computer to get the latest episodes), you can skip forward and backward 30 seconds, you can increase playback speed to 1.5 times normal speed, and the app is even compatible with AirPlay.&lt;br /&gt;
&lt;h2&gt;12. &lt;a href=&quot;http://itunes.apple.com/us/app/photoshop-com-mobile/id331975235?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Photoshop Mobile&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;Photoshop is, of course, the best known photo editor in the world and its mobile app doesn’t do anything to hurt that reputation. But while the desktop version is known for having a zillion features, the mobile app is distinguished by its simplicity. It’s the best iPhone photo editing app for simple crops, brightness adjustments, and sharpens, for example. However, once editing is built into the native Camera app in iOS5, editors such as Photoshop Mobile may quickly become unnecessary.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;13. &lt;a href=&quot;http://itunes.apple.com/us/app/pano/id293709029?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Pano&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;Pano makes it easy to take excellent panoramas with the iPhone. It helps you line up your shots and it automatically corrects many of the imperfections. My wife is a photographer with a big, expensive Nikon camera and she’s regularly jealous of some of the shots I can get with the iPhone and Pano.&lt;br /&gt;
&lt;h2&gt;14. &lt;a href=&quot;http://itunes.apple.com/us/app/instagram/id389801252?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Instagram&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;The camera and camera app on the iPhone are now good enough to replace a point-and-shoot. You can even take pictures that are worthy of saving in your family albums. For those, I upload them to Flickr using the iPhone app. For the everyday photos that I just want to quickly post on social media, I use Instagram. It is very quick, dead simple to use, and very social media friendly. But, do me a favor and go easy on the filters. They are badly overused by most Instagram users, while 90% of photos are better with no filter at all.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;15. &lt;a href=&quot;http://itunes.apple.com/us/app/navigon-mobilenavigator-north/id321506742?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Navigon Mobile Navigator&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;I used to carry a separate Garmin GPS unit for turn-by-turn directions but I eventually got rid of it and decided to just use the iPhone instead. In researching the various apps, I eventually decided on NAVIGON, which is a company that makes a lot of the built-in navigation systems for many cars. Tip: Make sure your iPhone is plugged in to power when you run a GPS navigation program like this because otherwise it will quickly drain your battery.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;16. &lt;a href=&quot;http://itunes.apple.com/us/app/where-to-gps-points-interest/id314785156?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Where To?&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;A great companion to a GPS system is the app “Where To?” which lets you quickly look up various types of shops and services, from Cuban restaurants to medical specialists to animal hospitals to local museums and much more.&lt;br /&gt;
&lt;h2&gt;17. &lt;a href=&quot;http://itunes.apple.com/us/app/runkeeper/id300235330?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;RunKeeper&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;This is a great little app that can save you from buying a pedometer. It uses the iPhone’s GPS to track the miles you’ve run or walked, and it compiles the data into some nice dashboards that you can view on your phone or on RunKeeper’s website.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;18. &lt;a href=&quot;http://itunes.apple.com/us/app/nutrition-menu-calorie-exercise/id294692235?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;Nutrition Menu&lt;/span&gt;&lt;/a&gt; &lt;/strong&gt;&lt;/h2&gt;Another app for all of you health-conscious geeks out there is Nutrition Menu. This thing is a mobile compendium of nutritional data. It has calorie information on common foods and most major restaurants, and it has calorie-burning information for many types of exercises. It also allows you to track your daily weigh-ins and makes notes on your progress.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;19. &lt;a href=&quot;http://itunes.apple.com/us/app/grocery-gadget-shopping-list/id287932487?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;GroceryGadget&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;This is an app plus a website and you can quickly sync between the two. The way it usually works for me is that my wife makes a grocery list, enters it into grocerygadgets.com, and then it syncs to my iPhone so that I can swing by the grocery store and pick up the stuff.&lt;br /&gt;
&lt;h2&gt;&lt;strong&gt;20. &lt;a href=&quot;http://itunes.apple.com/us/app/redlaser/id312720263?mt=8&quot; target=&quot;_blank&quot;&gt;&lt;span style=&quot;color: #003399;&quot;&gt;RedLaser&lt;/span&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/h2&gt;This is a great app for shoppers. It turns the iPhone camera into a barcode scanner and it’s quite accurate. You simply scan a product’s UPC code and let the app go to work to find it in Google Product Search and TheFind. For food it will even look up allergen information and for books it will scan to see if you can get it in a local library. You’ll be amazed at how fast it works. A similar product is SnapTell, which not only scans barcordes but you can also take a picture of the cover of a book or DVD and it can look them up that way. These apps are great when you’re shopping at a retail store and want to check the prices of products online before buying. It also reads QR codes.&lt;br /&gt;
&lt;br /&gt;
Source: &lt;a href=&quot;http://www.techrepublic.com/&quot;&gt;http://www.techrepublic.com/&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jfvaleroso.blogspot.com/feeds/5789486380725667312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://jfvaleroso.blogspot.com/2011/09/20-best-iphone-apps-of-2011-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/5789486380725667312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/5789486380725667312'/><link rel='alternate' type='text/html' href='http://jfvaleroso.blogspot.com/2011/09/20-best-iphone-apps-of-2011-for.html' title='The 20 best iPhone apps of 2011 for productive geeks'/><author><name>Jeffrey Valeroso</name><uri>http://www.blogger.com/profile/08001080593078135203</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1384162512306361231.post-7308791372025941562</id><published>2011-06-24T10:09:00.001-07:00</published><updated>2011-06-24T10:09:43.846-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET"/><title type='text'>Understanding ASP.NET View State</title><content type='html'>&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic1&quot;&gt;&lt;/a&gt;Introduction&lt;/h2&gt;Microsoft® ASP.NET view state, in a nutshell, is the technique used by an ASP.NET Web page to persist changes to the state of a Web Form across postbacks. In my experiences as a trainer and consultant, view state has caused the most confusion among ASP.NET developers. When creating custom server controls or doing more advanced page techniques, not having a solid grasp of what view state is and how it works can come back to bite you. Web designers who are focused on creating low-bandwidth, streamlined pages oftentimes find themselves frustrated with view state, as well. The view state of a page is, by default, placed in a hidden form field named &lt;code class=&quot;ce&quot;&gt;__VIEWSTATE&lt;/code&gt;. This hidden form field can easily get very large, on the order of tens of kilobytes. Not only does the &lt;code class=&quot;ce&quot;&gt;__VIEWSTATE&lt;/code&gt; form field cause slower downloads, but, whenever the user posts back the Web page, the contents of this hidden form field must be posted back in the HTTP request, thereby lengthening the request time, as well.&lt;br /&gt;
This article aims to be an in-depth examination of the ASP.NET view state. We&#39;ll look at exactly what view state is storing, and how the view state is serialized to the hidden form field and deserialized back on postback. We&#39;ll also discuss techniques for reducing the bandwidth required by the view state.&lt;br /&gt;
&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;This article is geared toward the ASP.NET page developer rather than the ASP.NET server control developer. This article therefore does not include a discussion on how a control developer would implement saving state. For an in-depth discussion on that issue, refer to the book &lt;a href=&quot;http://www.microsoft.com/mspress/books/5728.asp&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Developing Microsoft ASP.NET Server Controls and Components&lt;/span&gt;&lt;/a&gt;.&lt;/div&gt;&lt;/blockquote&gt;Before we can dive into our examination of view state, it is important that we first take a quick moment to discuss the ASP.NET page life cycle. That is, what exactly happens when a request comes in from a browser for an ASP.NET Web page? We&#39;ll step through this process in the next section.&lt;br /&gt;
&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic2&quot;&gt;&lt;/a&gt;The ASP.NET Page Life Cycle&lt;/h2&gt;Each time a request arrives at a Web server for an ASP.NET Web page, the first thing the Web server does is hand off the request to the ASP.NET engine. The ASP.NET engine then takes the request through a pipeline composed of numerous stages, which includes verifying file access rights for the ASP.NET Web page, resurrecting the user&#39;s session state, and so on. At the end of the pipeline, a class corresponding to the requested ASP.NET Web page is instantiated and the &lt;code class=&quot;ce&quot;&gt;ProcessRequest()&lt;/code&gt; method is invoked (see Figure 1).&lt;br /&gt;
&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms972976.viewstate_fig01(l=en-us).gif&quot; target=&quot;_top&quot;&gt;&lt;img alt=&quot;Click here for larger image.&quot; id=&quot;viewstate_fig01thumb&quot; src=&quot;http://i.msdn.microsoft.com/dynimg/IC43757.gif&quot; title=&quot;Click here for larger image.&quot; xmlns=&quot;&quot; /&gt;&lt;/a&gt; &lt;br /&gt;
&lt;div class=&quot;label&quot;&gt;&lt;strong&gt;Figure 1. ASP.NET Page Handling&lt;/strong&gt;&lt;/div&gt;This life cycle of the ASP.NET page starts with a call to the &lt;code class=&quot;ce&quot;&gt;ProcessRequest()&lt;/code&gt; method. This method begins by initializing the page&#39;s control hierarchy. Next, the page and its server controls proceed lock-step through various phases that are essential to executing an ASP.NET Web page. These steps include managing view state, handling postback events, and rendering the page&#39;s HTML markup. Figure 2 provides a graphical representation of the ASP.NET page life cycle. The life cycle ends by handing off the Web page&#39;s HTML markup to the Web server, which sends it back to the client that requested the page.&lt;br /&gt;
&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;A detailed discussion of the steps leading up to the ASP.NET page life cycle is beyond the scope of this article. For more information read Michele Leroux-Bustamante&#39;s &lt;a href=&quot;http://theserverside.net/articles/showarticle.tss?id=IIS_ASP&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Inside IIS &amp;amp; ASP.NET&lt;/span&gt;&lt;/a&gt;. For a more detailed look at HTTP handlers, which are the endpoints of the ASP.NET pipeline, check out my previous article on &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms972953.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;HTTP Handlers&lt;/span&gt;&lt;/a&gt;.&lt;/div&gt;&lt;/blockquote&gt;What is important to realize is that &lt;em&gt;each and every time&lt;/em&gt; an ASP.NET Web page is requested it goes through these same life cycle stages (shown in Figure 2).&lt;br /&gt;
&lt;div class=&quot;fig&quot;&gt;&lt;img alt=&quot;ms972976.viewstate_fig02(en-us,MSDN.10).gif&quot; id=&quot;viewstate_fig02&quot; src=&quot;http://i.msdn.microsoft.com/dynimg/IC152667.gif&quot; title=&quot;ms972976.viewstate_fig02(en-us,MSDN.10).gif&quot; xmlns=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;label&quot;&gt;&lt;strong&gt;Figure 2. Events in the Page Life Cycle&lt;/strong&gt;&lt;/div&gt;&lt;h3 class=&quot;dtH1&quot;&gt;Stage 0 - Instantiation&lt;/h3&gt;The life cycle of the ASP.NET page begins with instantiation of the class that represents the requested ASP.NET Web page, but how is this class created? Where is it stored?&lt;br /&gt;
ASP.NET Web pages, as you know, are made up of both an HTML portion and a code portion, with the HTML portion containing HTML markup and Web control syntax. The ASP.NET engine converts the HTML portion from its free-form text representation into a series of programmatically-created Web controls.&lt;br /&gt;
When an ASP.NET Web page is visited for the first time after a change has been made to the HTML markup or Web control syntax in the &lt;code class=&quot;ce&quot;&gt;.aspx&lt;/code&gt; page, the ASP.NET engine auto-generates a class. If you created your ASP.NET Web page using the code-behind technique, this autogenerated class is derived from the page&#39;s associated code-behind class (note that the code-behind class must be derived itself, either directly or indirectly, from the &lt;code class=&quot;ce&quot;&gt;System.Web.UI.Page&lt;/code&gt; class); if you created your page with an in-line, server-side &lt;code class=&quot;ce&quot;&gt;&amp;lt;script&amp;gt;&lt;/code&gt; block, the class derives directly from &lt;code class=&quot;ce&quot;&gt;System.Web.UI.Page&lt;/code&gt;. In either case, this autogenerated class, along with a compiled instance of the class, is stored in the &lt;code&gt;&lt;code&gt;&lt;strong&gt;WINDOWS&lt;/strong&gt;&lt;/code&gt;&lt;code class=&quot;ce&quot;&gt;\Microsoft.NET\Framework\&lt;/code&gt;&lt;code&gt;&lt;strong&gt;version&lt;/strong&gt;&lt;/code&gt;&lt;code class=&quot;ce&quot;&gt;\Temporary ASP.NET Files&lt;/code&gt;&lt;/code&gt; folder, in part so that it doesn&#39;t need to be recreated for each page request.&lt;br /&gt;
The purpose of this autogenerated class is to programmatically create the page&#39;s &lt;em&gt;control hierarchy&lt;/em&gt;. That is, the class is responsible for programmatically creating the Web controls specified in the page&#39;s HTML portion. This is done by translating the Web control syntax—&lt;code&gt;&lt;code class=&quot;ce&quot;&gt;&amp;lt;asp:&lt;/code&gt;&lt;code&gt;&lt;strong&gt;WebControlName Prop1=&quot;Value1&quot; ...&lt;/strong&gt;&lt;/code&gt;&lt;code class=&quot;ce&quot;&gt; /&amp;gt;&lt;/code&gt;&lt;/code&gt;—into the class&#39;s programming language (C# or Microsoft® Visual Basic® .NET, most typically). In addition to the Web control syntax being converted into the appropriate code, the HTML markup present in the ASP.NET Web page&#39;s HTML portion is translated to Literal controls.&lt;br /&gt;
All ASP.NET server controls can have a parent control, along with a variable number of child controls. The &lt;code class=&quot;ce&quot;&gt;System.Web.UI.Page&lt;/code&gt; class is derived from the base control class (&lt;code class=&quot;ce&quot;&gt;System.Web.UI.Control&lt;/code&gt;), and therefore also can have a set of child controls. The top-level controls declared in an ASP.NET Web page&#39;s HTML portion are the direct children of the autogenerated &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class. Web controls can also be nested inside one another. For example, most ASP.NET Web pages contain a single server-side Web Form, with multiple Web controls inside the Web Form. The Web Form is an HTML control (&lt;code class=&quot;ce&quot;&gt;System.Web.UI.HtmlControls.HtmlForm&lt;/code&gt;). Those Web controls inside the Web Form are children of the Web Form.&lt;br /&gt;
Since server controls can have children, and each of their children may have children, and so on, a control and its descendents form a tree of controls. This tree of controls is called the control hierarchy. The root of the control hierarchy for an ASP.NET Web page is the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt;-derived class that is autogenerated by the ASP.NET engine.&lt;br /&gt;
Whew! Those last few paragraphs may have been a bit confusing, as this is not the easiest subject to discuss or digest. To clear out any potential confusion, let&#39;s look at a quick example. Imagine you have an ASP.NET Web page with the following HTML portion:&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainer&quot; xmlns=&quot;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; name=&quot;CodeSpippet0&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainerCodeCollection&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBar&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBarText&quot; style=&quot;valign: top;&quot;&gt;&lt;a href=&quot;javascript:CodeSnippet_CopyCode(&#39;CodeSnippetContainerCode0&#39;);&quot; name=&quot;CodeSnippetname&quot; style=&quot;display: block;&quot; title=&quot;Copy to clipboard.&quot;&gt;Copy&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;LW_CodeSnippetContainerCode&quot; id=&quot;CodeSnippetContainerCode0&quot;&gt;&lt;div style=&quot;color: black;&quot;&gt;&lt;pre&gt;&amp;lt;html&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;Welcome to my Homepage!&amp;lt;/h1&amp;gt;
  &amp;lt;form runat=&quot;server&quot;&amp;gt;
    What is your name?
    &amp;lt;asp:TextBox runat=&quot;server&quot; ID=&quot;txtName&quot;&amp;gt;&amp;lt;/asp:TextBox&amp;gt;
    &amp;lt;br /&amp;gt;What is your gender?
    &amp;lt;asp:DropDownList runat=&quot;server&quot; ID=&quot;ddlGender&quot;&amp;gt;
      &amp;lt;asp:ListItem Select=&quot;True&quot; Value=&quot;M&quot;&amp;gt;Male&amp;lt;/asp:ListItem&amp;gt;
      &amp;lt;asp:ListItem Value=&quot;F&quot;&amp;gt;Female&amp;lt;/asp:ListItem&amp;gt;
      &amp;lt;asp:ListItem Value=&quot;U&quot;&amp;gt;Undecided&amp;lt;/asp:ListItem&amp;gt;
    &amp;lt;/asp:DropDownList&amp;gt;
    &amp;lt;br /&amp;gt;
    &amp;lt;asp:Button runat=&quot;server&quot; Text=&quot;Submit!&quot;&amp;gt;&amp;lt;/asp:Button&amp;gt;
  &amp;lt;/form&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;When this page is first visited, a class will be autogenerated that contains code to programmatically build up the control hierarchy. The control hierarchy for this example can be seen in Figure 3.&lt;br /&gt;
&lt;div class=&quot;fig&quot;&gt;&lt;img alt=&quot;ms972976.viewstate_fig03(en-us,MSDN.10).gif&quot; id=&quot;viewstate_fig03&quot; src=&quot;http://i.msdn.microsoft.com/dynimg/IC43087.gif&quot; title=&quot;ms972976.viewstate_fig03(en-us,MSDN.10).gif&quot; xmlns=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;label&quot;&gt;&lt;strong&gt;Figure 3. Control Hierarchy for sample page&lt;/strong&gt;&lt;/div&gt;This control hierarchy is then converted to code that is similar to the following:&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainer&quot; xmlns=&quot;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; name=&quot;CodeSpippet1&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainerCodeCollection&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBar&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBarText&quot; style=&quot;valign: top;&quot;&gt;&lt;a href=&quot;javascript:CodeSnippet_CopyCode(&#39;CodeSnippetContainerCode1&#39;);&quot; name=&quot;CodeSnippetname&quot; style=&quot;display: block;&quot; title=&quot;Copy to clipboard.&quot;&gt;Copy&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;LW_CodeSnippetContainerCode&quot; id=&quot;CodeSnippetContainerCode1&quot;&gt;&lt;div style=&quot;color: black;&quot;&gt;&lt;pre&gt;Page.Controls.Add( 
  new LiteralControl(@&quot;&amp;lt;html&amp;gt;\r\n&amp;lt;body&amp;gt;\r\n
    &amp;lt;h1&amp;gt;Welcome to my Homepage!&amp;lt;/h1&amp;gt;\r\n&quot;));
HtmlForm Form1 = new HtmlForm();
Form1.ID = &quot;Form1&quot;;
Form1.Method = &quot;post&quot;;
Form1.Controls.Add(
  new LiteralControl(&quot;\r\nWhat is your name?\r\n&quot;));
TextBox TextBox1 = new TextBox();
TextBox1.ID = &quot;txtName&quot;;
Form1.Controls.Add(TextBox1);
Form1.Controls.Add(
  new LiteralControl(&quot;\r\n&amp;lt;br /&amp;gt;What is your gender?\r\n&quot;));
DropDownList DropDownList1 = new DropDownList();
DropDownList1.ID = &quot;ddlGender&quot;;
ListItem ListItem1 = new ListItem();
ListItem1.Selected = true;
ListItem1.Value = &quot;M&quot;;
ListItem1.Text = &quot;Male&quot;;
DropDownList1.Items.Add(ListItem1);
ListItem ListItem2 = new ListItem();
ListItem2.Value = &quot;F&quot;;
ListItem2.Text = &quot;Female&quot;;
DropDownList1.Items.Add(ListItem2);
ListItem ListItem3 = new ListItem();
ListItem3.Value = &quot;U&quot;;
ListItem3.Text = &quot;Undecided&quot;;
DropDownList1.Items.Add(ListItem3);
Form1.Controls.Add(
  new LiteralControl(&quot;\r\n&amp;lt;br /&amp;gt; \r\n&quot;));
Button Button1 = new Button();
Button1.Text = &quot;Submit!&quot;;
Form1.Controls.Add(Button1);
Form1.Controls.Add(
  new LiteralControl(&quot;\r\n&amp;lt;/body&amp;gt;\r\n&amp;lt;/html&amp;gt;&quot;));
Controls.Add(Form1);

&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;The C# source code above is not the precise code that is autogenerated by the ASP.NET engine. Rather, it&#39;s a cleaner and easier to read version of the autogenerated code. To see the full autogenerated code—which won&#39;t win any points for readability—navigate to the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;&lt;code&gt;&lt;strong&gt;WINDOWS&lt;/strong&gt;&lt;/code&gt;&lt;code class=&quot;ce&quot;&gt;\Microsoft.NET\Framework\&lt;/code&gt;&lt;code&gt;&lt;strong&gt;Version&lt;/strong&gt;&lt;/code&gt;&lt;code class=&quot;ce&quot;&gt;\Temporary ASP.NET Files&lt;/code&gt;&lt;/div&gt;folder and open one of the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;.cs&lt;/div&gt;or &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;.vb&lt;/div&gt;files.&lt;/div&gt;&lt;/blockquote&gt;One thing to notice is that, when the control hierarchy is constructed, the properties that are explicitly set in the declarative syntax of the Web control are assigned in the code. (For example, the Button Web control has its &lt;strong&gt;Text&lt;/strong&gt; property set to &lt;strong&gt;&quot;Submit!&quot;&lt;/strong&gt; in the declarative syntax – &lt;code class=&quot;ce&quot;&gt;Text=&quot;Submit!&quot;&lt;/code&gt; – as well as in the autogenerated class—&lt;code class=&quot;ce&quot;&gt;Button1.Text = &quot;Submit!&quot;;&lt;/code&gt;.&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;Stage 1 - Initialization&lt;/h3&gt;After the control hierarchy has been built, the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt;, along with all of the controls in its control hierarchy, enter the initialization stage. This stage is marked by having the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; and controls fire their &lt;code class=&quot;ce&quot;&gt;Init&lt;/code&gt; events. At this point in the page life cycle, the control hierarchy has been constructed, and the Web control properties that are specified in the declarative syntax have been assigned.&lt;br /&gt;
We&#39;ll look at the initialization stage in more detail later in this article. With regards to view state it is important for two reasons; first, server controls don&#39;t begin tracking view state changes until right at the end of the initialization stage. Second, when adding dynamic controls that need to utilize view state, these controls will need to be added during the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt;&#39;s &lt;code class=&quot;ce&quot;&gt;Init&lt;/code&gt; event as opposed to the &lt;code class=&quot;ce&quot;&gt;Load&lt;/code&gt; event, as we&#39;ll see shortly.&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;Stage 2 - Load View State&lt;/h3&gt;The load view state stage only happens when the page has been posted back. During this stage, the view state data that had been saved from the previous page visit is loaded and recursively populated into the control hierarchy&lt;code class=&quot;ce&quot;&gt; &lt;/code&gt;of the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt;. It is during this stage that the view state is &lt;em&gt;validated&lt;/em&gt;. As we&#39;ll discuss later in this article, the view state can become invalid due to a number of reasons, such as view state tampering, and injecting dynamic controls into the middle of the control hierarchy.&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;Stage 3 - Load Postback Data&lt;/h3&gt;The load postback data stage also only happens when the page has been posted back. A server control can indicate that it is interested in examining the posted back data by implementing the &lt;code class=&quot;ce&quot;&gt;IPostBackDataHandler&lt;/code&gt; interface. In this stage in the page life cycle, the Page class enumerates the posted back form fields, and searches for the corresponding server control. If it finds the control, it checks to see if the control implements the &lt;code class=&quot;ce&quot;&gt;IPostBackDataHandler&lt;/code&gt; interface. If it does, it hands off the appropriate postback data to the server control by calling the control&#39;s &lt;code class=&quot;ce&quot;&gt;LoadPostData()&lt;/code&gt; method. The server control would then update its state based on this postback data.&lt;br /&gt;
To help clarify things, let&#39;s look at a simple example. One nice thing about ASP.NET is that the Web controls in a Web Form remember their values across postback. That is, if you have a TextBox Web control on a page and the user enters some value into the TextBox and posts back the page, the TextBox&#39;s &lt;code class=&quot;ce&quot;&gt;Text&lt;/code&gt; property is automatically updated to the user&#39;s entered value. This happens because the TextBox Web control implements the &lt;code class=&quot;ce&quot;&gt;IPostBackDataHandler&lt;/code&gt; interface, and the Page class hands off the appropriate value to the TextBox class, which then updates its &lt;code class=&quot;ce&quot;&gt;Text&lt;/code&gt; property.&lt;br /&gt;
To concretize things, imagine that we have an ASP.NET Web page with a TextBox whose &lt;code class=&quot;ce&quot;&gt;ID&lt;/code&gt; property is set to &lt;code class=&quot;ce&quot;&gt;txtName&lt;/code&gt;. When the page is first visited, the following HTML will be rendered for the TextBox: &lt;code class=&quot;ce&quot;&gt;&amp;lt;input type=&quot;text&quot; id=&quot;txtName&quot; name=&quot;txtName&quot; /&amp;gt;&lt;/code&gt;. When the user enters a value into this TextBox (such as, &quot;Hello, World!&quot;) and submits the form, the browser will make a request to the same ASP.NET Web page, passing the form field values back in the HTTP POST headers. These include the hidden form field values (such as &lt;code class=&quot;ce&quot;&gt;__VIEWSTATE&lt;/code&gt;), along with the value from the &lt;code class=&quot;ce&quot;&gt;txtName&lt;/code&gt; TextBox.&lt;br /&gt;
When the ASP.NET Web page is posted back in the load postback data stage, the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class sees that one of the posted back form fields corresponds to the &lt;code class=&quot;ce&quot;&gt;IPostBackDataHandler&lt;/code&gt; interface. There is such a control in the hierarchy, so the TextBox&#39;s &lt;code class=&quot;ce&quot;&gt;LoadPostData()&lt;/code&gt; method is invoked, passing in the value the user entered into the TextBox (&quot;Hello, World!&quot;). The TextBox&#39;s &lt;code class=&quot;ce&quot;&gt;LoadPostData()&lt;/code&gt; method simply assigns this passed in value to its &lt;code class=&quot;ce&quot;&gt;Text&lt;/code&gt; property.&lt;br /&gt;
Notice that in our discussion on the load postback data stage, there was no mention of view state. You might naturally be wondering, therefore, why I bothered to mention the load postback data stage in an article about view state. The reason is to note the &lt;em&gt;absence&lt;/em&gt; of view state in this stage. It is a common misconception among developers that view state is somehow responsible for having TextBoxes, CheckBoxes, DropDownLists, and other Web controls remember their values across postback. This is not the case, as the values are identified via posted back form field values, and assigned in the &lt;code class=&quot;ce&quot;&gt;LoadPostData()&lt;/code&gt; method for those controls that implement &lt;code class=&quot;ce&quot;&gt;IPostBackDataHandler&lt;/code&gt;.&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;Stage 4 - Load&lt;/h3&gt;This is the stage with which all ASP.NET developers are familiar, as we&#39;ve all created an event handler for a page&#39;s &lt;code class=&quot;ce&quot;&gt;Load&lt;/code&gt; event (&lt;code class=&quot;ce&quot;&gt;Page_Load&lt;/code&gt;). When the Load event fires, the view state has been loaded (from stage 2, Load View State), along with the postback data (from stage 3, Load Postback Data). If the page has been posted back, when the &lt;code class=&quot;ce&quot;&gt;Load&lt;/code&gt; event fires we know that the page has been restored to its state from the previous page visit.&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;Stage 5 - Raise Postback Event&lt;/h3&gt;Certain server controls raise events with respect to changes that occurred between postbacks. For example, the DropDownList Web control has a &lt;code class=&quot;ce&quot;&gt;SelectedIndexChanged&lt;/code&gt; event, which fires if the DropDownList&#39;s &lt;code class=&quot;ce&quot;&gt;SelectedIndex&lt;/code&gt; has changed from the &lt;code class=&quot;ce&quot;&gt;SelectedIndex&lt;/code&gt; value in the previous page load. Another example: if the Web Form was posted back due to a Button Web control being clicked, the Button&#39;s &lt;code class=&quot;ce&quot;&gt;Click&lt;/code&gt; event is fired during this stage.&lt;br /&gt;
There are two flavors of postback events. The first is a &lt;em&gt;changed&lt;/em&gt; event. This event fires when some piece of data is changed between postbacks. An example is the DropDownLists &lt;code class=&quot;ce&quot;&gt;SelectedIndexChanged&lt;/code&gt; event, or the TextBox&#39;s &lt;code class=&quot;ce&quot;&gt;TextChanged&lt;/code&gt; event. Server controls that provide changed events must implement the &lt;code class=&quot;ce&quot;&gt;IPostBackDataHandler&lt;/code&gt; interface. The other flavor of postback events is the &lt;em&gt;raised&lt;/em&gt; event. These are events that are raised by the server control for whatever reason the control sees fit. For example, the Button Web control raises the &lt;code class=&quot;ce&quot;&gt;Click&lt;/code&gt; event when it is clicked, and the Calendar control raises the &lt;code class=&quot;ce&quot;&gt;VisibleMonthChanged&lt;/code&gt; event when the user moves to another month. Controls that fire raised events must implement the &lt;code class=&quot;ce&quot;&gt;IPostBackEventHandler&lt;/code&gt; interface.&lt;br /&gt;
Since this stage inspects postback data to determine if any events need to be raised, the stage only occurs when the page has been posted back. As with the load postback data stage, the raise postback event stage does not use view state information at all. Whether or not an event is raised depends on the data posted back in the form fields.&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;Stage 6 - Save View State&lt;/h3&gt;In the save view state stage, the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class constructs the page&#39;s view state, which represents the state that must persist across postbacks. The page accomplishes this by recursively calling the &lt;code class=&quot;ce&quot;&gt;SaveViewState()&lt;/code&gt; method of the controls in its control hierarchy. This combined, saved state is then serialized into a base-64 encoded string. In stage 7, when the page&#39;s Web Form is rendered, the view state is persisted in the page as a hidden form field.&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;Stage 7 - Render&lt;/h3&gt;In the render stage the HTML that is emitted to the client requesting the page is generated. The &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class accomplishes this by recursively invoking the &lt;code class=&quot;ce&quot;&gt;RenderControl()&lt;/code&gt; method of each of the controls in its hierarchy.&lt;br /&gt;
These seven stages are the most important stages with respect to understanding view state. (Note that I did omit a couple of stages, such as the PreRender and Unload stages.) As you continue through the article, keep in mind that every single time an ASP.NET Web page is requested, it proceeds through these series of stages.&lt;br /&gt;
&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic3&quot;&gt;&lt;/a&gt;The Role of View State&lt;/h2&gt;View state&#39;s purpose in life is simple: it&#39;s there to persist state across postbacks. (For an ASP.NET Web page, its state is the property values of the controls that make up its control hierarchy.) This begs the question, &quot;What sort of state needs to be persisted?&quot; To answer that question, let&#39;s start by looking at what state &lt;em&gt;doesn&#39;t&lt;/em&gt; need to be persisted across postbacks. Recall that in the instantiation stage of the page life cycle, the control hierarchy is created and those properties that are specified in the declarative syntax are assigned. Since these declarative properties are automatically reassigned on each postback when the control hierarchy is constructed, there&#39;s no need to store these property values in the view state.&lt;br /&gt;
For example, imagine we have a Label Web control in the HTML portion with the following declarative syntax:&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainer&quot; xmlns=&quot;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; name=&quot;CodeSpippet2&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainerCodeCollection&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBar&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBarText&quot; style=&quot;valign: top;&quot;&gt;&lt;a href=&quot;javascript:CodeSnippet_CopyCode(&#39;CodeSnippetContainerCode2&#39;);&quot; name=&quot;CodeSnippetname&quot; style=&quot;display: block;&quot; title=&quot;Copy to clipboard.&quot;&gt;Copy&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;LW_CodeSnippetContainerCode&quot; id=&quot;CodeSnippetContainerCode2&quot;&gt;&lt;div style=&quot;color: black;&quot;&gt;&lt;pre&gt;&amp;lt;asp:Label runat=&quot;server&quot; Font-Name=&quot;Verdana&quot; 
  Text=&quot;Hello, World!&quot;&amp;gt;&amp;lt;/asp:Label&amp;gt;

&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;When the control hierarchy is built in the instantiation stage, the Label&#39;s &lt;code class=&quot;ce&quot;&gt;Text&lt;/code&gt; property will be set to &quot;Hello, World!&quot; and its &lt;code class=&quot;ce&quot;&gt;Font&lt;/code&gt; property will have its &lt;code class=&quot;ce&quot;&gt;Name&lt;/code&gt; property set to Verdana. Since these properties will be set each and every page visit during the instantiation stage, there&#39;s no need to persist this information in the view state.&lt;br /&gt;
What needs to be stored in the view state is any programmatic &lt;em&gt;changes&lt;/em&gt; to the page&#39;s state. For example, suppose that in addition to this Label Web control, the page also contained two Button Web controls, a Change Message Button and an Empty Postback button. The Change Message Button has a &lt;code class=&quot;ce&quot;&gt;Click&lt;/code&gt; event handler that assigns the Label&#39;s &lt;code class=&quot;ce&quot;&gt;Text&lt;/code&gt; property to &quot;Goodbye, Everyone!&quot;; the Empty Postback Button just causes a postback, but doesn&#39;t execute any code. The change to the Label&#39;s &lt;code class=&quot;ce&quot;&gt;Text&lt;/code&gt; property in the Change Message Button would need to be saved in the view state. To see how and when this change would be made, let&#39;s walk through a quick example. Assuming that the HTML portion of the page contains the following markup:&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainer&quot; xmlns=&quot;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; name=&quot;CodeSpippet3&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainerCodeCollection&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBar&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBarText&quot; style=&quot;valign: top;&quot;&gt;&lt;a href=&quot;javascript:CodeSnippet_CopyCode(&#39;CodeSnippetContainerCode3&#39;);&quot; name=&quot;CodeSnippetname&quot; style=&quot;display: block;&quot; title=&quot;Copy to clipboard.&quot;&gt;Copy&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;LW_CodeSnippetContainerCode&quot; id=&quot;CodeSnippetContainerCode3&quot;&gt;&lt;div style=&quot;color: black;&quot;&gt;&lt;pre&gt;&amp;lt;asp:Label runat=&quot;server&quot; ID=&quot;lblMessage&quot; 
  Font-Name=&quot;Verdana&quot; Text=&quot;Hello, World!&quot;&amp;gt;&amp;lt;/asp:Label&amp;gt;
&amp;lt;br /&amp;gt;
&amp;lt;asp:Button runat=&quot;server&quot; 
  Text=&quot;Change Message&quot; ID=&quot;btnSubmit&quot;&amp;gt;&amp;lt;/asp:Button&amp;gt;
&amp;lt;br /&amp;gt;
&amp;lt;asp:Button runat=&quot;server&quot; Text=&quot;Empty Postback&quot;&amp;gt;&amp;lt;/asp:Button&amp;gt;

&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;And the code-behind class contains the following event handler for the Button&#39;s Click event:&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainer&quot; xmlns=&quot;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; name=&quot;CodeSpippet4&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainerCodeCollection&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBar&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBarText&quot; style=&quot;valign: top;&quot;&gt;&lt;a href=&quot;javascript:CodeSnippet_CopyCode(&#39;CodeSnippetContainerCode4&#39;);&quot; name=&quot;CodeSnippetname&quot; style=&quot;display: block;&quot; title=&quot;Copy to clipboard.&quot;&gt;Copy&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;LW_CodeSnippetContainerCode&quot; id=&quot;CodeSnippetContainerCode4&quot;&gt;&lt;div style=&quot;color: black;&quot;&gt;&lt;pre&gt;private void btnSubmit_Click(object sender, EventArgs e)
{
  lblMessage.Text = &quot;Goodbye, Everyone!&quot;;
}

&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;Figure 4 illustrates the sequence of events that transpire, highlighting why the change to the Label&#39;s &lt;code class=&quot;ce&quot;&gt;Text&lt;/code&gt; property needs to be stored in the view state.&lt;br /&gt;
&lt;div class=&quot;fig&quot;&gt;&lt;img alt=&quot;ms972976.viewstate_fig04(en-us,MSDN.10).gif&quot; id=&quot;viewstate_fig04&quot; src=&quot;http://i.msdn.microsoft.com/dynimg/IC159849.gif&quot; title=&quot;ms972976.viewstate_fig04(en-us,MSDN.10).gif&quot; xmlns=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;label&quot;&gt;&lt;strong&gt;Figure 4. Events and View State&lt;/strong&gt;&lt;/div&gt;To understand why saving the Label&#39;s changed &lt;code class=&quot;ce&quot;&gt;Text&lt;/code&gt; property in the view state is vital, consider what would happen if this information were not persisted in view state. That is, imagine that in step 2&#39;s save view state stage, no view state information was persisted. If this were the case, then in step 3 the Label&#39;s Text property would be assigned to &quot;Hello, World!&quot; in the instantiation stage, but would not be reassigned to &quot;Goodbye, Everyone!&quot; in the load view state stage. Therefore, from the end user&#39;s perspective, the Label&#39;s &lt;code class=&quot;ce&quot;&gt;Text&lt;/code&gt; property would be &quot;Goodbye, Everyone!&quot; in step 2, but would seemingly be reset to its original value (&quot;Hello, World!&quot;) in step 3, after clicking the Empty Postback button.&lt;br /&gt;
&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic4&quot;&gt;&lt;/a&gt;View State and Dynamically Added Controls&lt;/h2&gt;Since all ASP.NET server controls contain a collection of child controls exposed through the &lt;code class=&quot;ce&quot;&gt;Controls&lt;/code&gt; property, controls can be dynamically added to the control hierarchy by appending new controls to a server control&#39;s &lt;code class=&quot;ce&quot;&gt;Controls&lt;/code&gt; collection. A thorough discussion of dynamic controls is a bit beyond the scope of this article, so we won&#39;t cover that topic in detail here; instead, we&#39;ll focus on how to manage view state for controls that are added dynamically. (For a more detailed lesson on using dynamic controls, check out &lt;a href=&quot;http://aspnet.4guysfromrolla.com/articles/081402-1.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Dynamic Controls in ASP.NET&lt;/span&gt;&lt;/a&gt; and &lt;a href=&quot;http://aspnet.4guysfromrolla.com/articles/082102-1.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Working with Dynamically Created Controls&lt;/span&gt;&lt;/a&gt;.)&lt;br /&gt;
Recall that in the page life cycle, the control hierarchy is created and the declarative properties are set in the instantiation stage. Later, in the load view state stage, the state that had been altered in the prior page visit is restored. Thinking a bit about this, three things become clear when working with dynamic controls: &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Since the view state only persists changed control state across postbacks, and not the actual controls themselves, dynamically added controls must be added to the ASP.NET Web page, on both the initial visit as well as all subsequent postbacks.&lt;/li&gt;
&lt;li&gt;Dynamic controls are added to the control hierarchy in the code-behind class, and therefore are added at some point &lt;em&gt;after&lt;/em&gt; the instantiation stage.&lt;/li&gt;
&lt;li&gt;The view state for these dynamically added controls is automatically saved in the save view state stage. (What happens on postback if the dynamic controls have not yet been added by the time the load view state stage rolls, however?)&lt;/li&gt;
&lt;/ol&gt;So, dynamically added controls must be programmatically added to the Web page on each and every page visit. The best time to add these controls is during the initialization stage of the page life cycle, which occurs before the load view state stage. That is, we want to have the control hierarchy complete before the load view state stage arrives. For this reason, it is best to create an event handler for the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class&#39;s &lt;code class=&quot;ce&quot;&gt;Init&lt;/code&gt; event in your code-behind class, and add your dynamic controls there.&lt;br /&gt;
&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;You may be able to get away with loading your controls in the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;Page_Load&lt;/div&gt;event handler and maintaining the view state properly. It all depends on whether or not you are setting any properties of the dynamically loaded controls programmatically and, if so, when you&#39;re doing it relative to the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;&lt;code class=&quot;ce&quot;&gt;Controls.Add(&lt;/code&gt;&lt;code&gt;&lt;strong&gt;dynamicControl&lt;/strong&gt;&lt;/code&gt;&lt;code class=&quot;ce&quot;&gt;)&lt;/code&gt;&lt;/div&gt;line. A thorough discussion of this is a bit beyond the scope of this article, but the reason it may work is because the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;Controls&lt;/div&gt;property&#39;s &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;Add()&lt;/div&gt;method recursively loads the parent&#39;s view state into its children, even though the load view state stage has passed.&lt;/div&gt;&lt;/blockquote&gt;When adding a dynamic control &lt;em&gt;c&lt;/em&gt; to some parent control &lt;em&gt;p&lt;/em&gt; based on some condition (that is, when not loading them on each and every page visit), you need to make sure that you add &lt;em&gt;c&lt;/em&gt; to the end of &lt;em&gt;p&lt;/em&gt;&#39;s &lt;code class=&quot;ce&quot;&gt;Controls&lt;/code&gt; collection. The reason is because the view state for &lt;em&gt;p&lt;/em&gt; contains the view state for &lt;em&gt;p&lt;/em&gt;&#39;s children as well, and, as we&#39;ll discuss in the &quot;Parsing the View State&quot; section, &lt;em&gt;p&lt;/em&gt;&#39;s view state specifies the view state for its children by index. (Figure 5 illustrates how inserting a dynamic control somewhere other than the end of the Controls collection can cause a corrupted view state.)&lt;br /&gt;
&lt;div class=&quot;fig&quot;&gt;&lt;img alt=&quot;ms972976.viewstate_fig05(en-us,MSDN.10).gif&quot; id=&quot;viewstate_fig05&quot; src=&quot;http://i.msdn.microsoft.com/dynimg/IC20675.gif&quot; title=&quot;ms972976.viewstate_fig05(en-us,MSDN.10).gif&quot; xmlns=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;label&quot;&gt;&lt;strong&gt;Figure 5. Effect of inserting controls on View State&lt;/strong&gt;&lt;/div&gt;&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic5&quot;&gt;&lt;/a&gt;The ViewState Property&lt;/h2&gt;Each control is responsible for storing its own state, which is accomplished by adding its changed state to its &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt; property. The &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt; property is defined in the &lt;code class=&quot;ce&quot;&gt;System.Web.UI.Control&lt;/code&gt; class, meaning that all ASP.NET server controls have this property available. (When talking about view state in general I&#39;ll use lower case letters with a space between view and state; when discussing the &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt; property, I&#39;ll use the correct casing and code-formatted text.)&lt;br /&gt;
If you examine the simple properties of any ASP.NET server control you&#39;ll see that the properties read and write directly to the view state. (You can view the decompiled source code for a .NET assembly by using a tool like &lt;a href=&quot;http://www.aisto.com/roeder/dotnet/&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Reflector&lt;/span&gt;&lt;/a&gt;.) For example, consider the HyperLink Web control&#39;s &lt;code class=&quot;ce&quot;&gt;NavigateUrl&lt;/code&gt; property. The code for this property looks like so:&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainer&quot; xmlns=&quot;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; name=&quot;CodeSpippet5&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainerCodeCollection&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBar&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBarText&quot; style=&quot;valign: top;&quot;&gt;&lt;a href=&quot;javascript:CodeSnippet_CopyCode(&#39;CodeSnippetContainerCode5&#39;);&quot; name=&quot;CodeSnippetname&quot; style=&quot;display: block;&quot; title=&quot;Copy to clipboard.&quot;&gt;Copy&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;LW_CodeSnippetContainerCode&quot; id=&quot;CodeSnippetContainerCode5&quot;&gt;&lt;div style=&quot;color: black;&quot;&gt;&lt;pre&gt;public string NavigateUrl
{
  get
  {
    string text = (string) ViewState[&quot;NavigateUrl&quot;];
    if (text != null)
       return text;
    else
       return string.Empty;
  }
  set
  {
    ViewState[&quot;NavigateUrl&quot;] = value;
  }
}

&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;As this code sample illustrates, whenever a control&#39;s property is read, the control&#39;s &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt; is consulted. If there is not an entry in the &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt;, then the default value for the property is returned. When the property is assigned, the assigned value is written directly to the &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt;.&lt;br /&gt;
&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;All Web controls use the above pattern for simple properties. Simple properties are those that are scalar values, like strings, integers, Booleans, and so on. Complex properties, such as the Label&#39;s &lt;strong&gt;Font&lt;/strong&gt; property, which might be classes themselves, use a different approach. Consult the book &lt;a href=&quot;http://www.4guysfromrolla.com/ASPScripts/Goto.asp?ID=170&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Developing Microsoft ASP.NET Server Controls and Components&lt;/span&gt;&lt;/a&gt; for more information on state maintenance techniques for ASP.NET server controls.&lt;/div&gt;&lt;/blockquote&gt;The &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt; property is of type &lt;code class=&quot;ce&quot;&gt;System.Web.UI.StateBag&lt;/code&gt;. The &lt;code class=&quot;ce&quot;&gt;StateBag&lt;/code&gt; class provides a means to store name and value pairs, using a &lt;code class=&quot;ce&quot;&gt;System.Collections.Specialized.HybridDictionary&lt;/code&gt; behind the scenes. As the &lt;code class=&quot;ce&quot;&gt;NavigateUrl&lt;/code&gt; property syntax illustrates, items can be added to and queried from the &lt;code class=&quot;ce&quot;&gt;StateBag&lt;/code&gt; using the same syntax you could use to access items from a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/aa289149.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Hashtable&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;
&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic6&quot;&gt;&lt;/a&gt;Timing the Tracking of View State&lt;/h2&gt;Recall that earlier I said the view state only stores state that needs to be persisted across postbacks. One bit of state that does not need to be persisted across postbacks is the control&#39;s properties specified in the declarative syntax, since they are automatically reinstated in the page&#39;s instantiation stage. For example, if we have a HyperLink Web control on an ASP.NET Web page and declaratively set the &lt;code class=&quot;ce&quot;&gt;NavigateUrl&lt;/code&gt; property to &lt;a href=&quot;http://www.scottonwriting.net/&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;http://www.ScottOnWriting.NET&lt;/span&gt;&lt;/a&gt; then this information doesn&#39;t need to be stored in the view state.&lt;br /&gt;
Seeing the HyperLink control&#39;s &lt;code class=&quot;ce&quot;&gt;NavigateUrl&lt;/code&gt; property&#39;s code, however, it looks as if the control&#39;s &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt; is written to whenever the property value is set. In the instantiation stage, therefore, where we&#39;d have something like &lt;code class=&quot;ce&quot;&gt;HyperLink1.NavigateUrl = http://www.ScottOnWriting.NET;&lt;/code&gt;, it would only make sense that this information would be stored in the view state.&lt;br /&gt;
Regardless of what might seem apparent, this is not the case. The reason is because the &lt;code class=&quot;ce&quot;&gt;StateBag&lt;/code&gt; class only tracks changes to its members &lt;em&gt;after&lt;/em&gt; its &lt;code class=&quot;ce&quot;&gt;TrackViewState()&lt;/code&gt; method has been invoked. That is, if you have a &lt;code class=&quot;ce&quot;&gt;StateBag&lt;/code&gt;, any and all additions or modifications that are made before &lt;code class=&quot;ce&quot;&gt;TrackViewState()&lt;/code&gt; is made will not be saved when the &lt;code class=&quot;ce&quot;&gt;SaveViewState()&lt;/code&gt; method is invoked. The &lt;code class=&quot;ce&quot;&gt;TrackViewState()&lt;/code&gt; method is called at the end of the initialization stage, which happens after the instantiation stage. Therefore, the initial property assignments in the instantiation stage—while written to the &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt; in the properties&#39; set accessors—are not persisted during the &lt;code class=&quot;ce&quot;&gt;SaveViewState()&lt;/code&gt; method call in the save view state stage, because the &lt;code class=&quot;ce&quot;&gt;TrackViewState()&lt;/code&gt; method has yet to be invoked.&lt;br /&gt;
&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;The reason the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;StateBag&lt;/div&gt;has the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;TrackViewState()&lt;/div&gt;method is to keep the view state as trimmed down as possible. Again, we don&#39;t want to store the initial property values in the view state, as they don&#39;t need to be persisted across postbacks. Therefore, the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;TrackViewState()&lt;/div&gt;method allows the state management to begin after the instantiation and initialization stages.&lt;/div&gt;&lt;/blockquote&gt;&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic7&quot;&gt;&lt;/a&gt;Storing Information in the Page&#39;s ViewState Property&lt;/h2&gt;Since the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class is derived from the &lt;code class=&quot;ce&quot;&gt;System.Web.UI.Control&lt;/code&gt; class, it too has a &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt; property. In fact, you can use this property to persist page-specific and user-specific information across postbacks. From an ASP.NET Web page&#39;s code-behind class, the syntax to use is simply:&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainer&quot; xmlns=&quot;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; name=&quot;CodeSpippet6&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainerCodeCollection&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBar&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBarText&quot; style=&quot;valign: top;&quot;&gt;&lt;a href=&quot;javascript:CodeSnippet_CopyCode(&#39;CodeSnippetContainerCode6&#39;);&quot; name=&quot;CodeSnippetname&quot; style=&quot;display: block;&quot; title=&quot;Copy to clipboard.&quot;&gt;Copy&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;LW_CodeSnippetContainerCode&quot; id=&quot;CodeSnippetContainerCode6&quot;&gt;&lt;div style=&quot;color: black;&quot;&gt;&lt;pre&gt;ViewState[keyName] = value
&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;There are a number of scenarios when being able to store information in the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt;&#39;s &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt; is useful. The canonical example is in creating a pageable, sortable DataGrid (or a sortable, editable DataGrid), since the sort expression must be persisted across postbacks. That is, if the DataGrid&#39;s data is first sorted, and then paged, when binding the next page of data to the DataGrid it is important that you get the next page of the data when it is sorted by the user&#39;s specified sort expression. The sort expression therefore needs to be persisted in some manner. There are assorted techniques, but the simplest, in my opinion, is to store the sort expression in the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt;&#39;s &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt;.&lt;br /&gt;
For more information on creating sortable, pageable DataGrids (or a pageable, sortable, editable DataGrid), pick up a copy of my book &lt;a href=&quot;http://www.amazon.com/exec/obidos/ASIN/0672325012/&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;ASP.NET Data Web Controls Kick Start&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;
&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic8&quot;&gt;&lt;/a&gt;The Cost of View State&lt;/h2&gt;Nothing comes for free, and view state is no exception. The ASP.NET view state imposes two performance hits whenever an ASP.NET Web page is requested: &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;On all page visits, during the save view state stage the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class gathers the collective view state for all of the controls in its control hierarchy and serializes the state to a base-64 encoded string. (This is the string that is emitted in the hidden &lt;code class=&quot;ce&quot;&gt;__VIEWSTATE&lt;/code&gt; form filed.) Similarly, on postbacks, the load view state stage needs to deserialize the persisted view state data, and update the pertinent controls in the control hierarchy.&lt;/li&gt;
&lt;li&gt;The &lt;code class=&quot;ce&quot;&gt;__VIEWSTATE&lt;/code&gt; hidden form field adds extra size to the Web page that the client must download. For some view state-heavy pages, this can be tens of kilobytes of data, which can require several extra seconds (or minutes!) for modem users to download. Also, when posting back, the &lt;code class=&quot;ce&quot;&gt;__VIEWSTATE&lt;/code&gt; form field must be sent back to the Web server in the HTTP POST headers, thereby increasing the postback request time.&lt;/li&gt;
&lt;/ol&gt;If you are designing a Web site that is commonly accessed by users coming over a modem connection, you should be particularly concerned with the bloat the view state might add to a page. Fortunately, there are a number of techniques that can be employed to reduce view state size. We&#39;ll first see how to selectively indicate whether or not a server control should save its view state. If a control&#39;s state does not need to be persisted across postbacks, we can turn off view state tracking for that control, thereby saving the extra bytes that would otherwise have been added by that control. Following that, we&#39;ll examine how to remove the view state from the page&#39;s hidden form fields altogether, storing the view state instead on the Web server&#39;s file system.&lt;br /&gt;
&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic9&quot;&gt;&lt;/a&gt;Disabling the View State&lt;/h2&gt;In the save view state stage of the ASP.NET page life cycle, the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class recursively iterates through the controls in its control hierarchy, invoking each control&#39;s &lt;code class=&quot;ce&quot;&gt;SaveViewState()&lt;/code&gt; method. This collective state is what is persisted to the hidden &lt;code class=&quot;ce&quot;&gt;__VIEWSTATE&lt;/code&gt; form field. By default, all controls in the control hierarchy will record their view state when their &lt;code class=&quot;ce&quot;&gt;SaveViewState()&lt;/code&gt; method is invoked. As a page developer, however, you can specify that a control should not save its view state or the view state of its children controls by setting the control&#39;s &lt;code class=&quot;ce&quot;&gt;EnableViewState&lt;/code&gt; property to False (the default is True).&lt;br /&gt;
The &lt;code class=&quot;ce&quot;&gt;EnableViewState&lt;/code&gt; property is defined in the &lt;code class=&quot;ce&quot;&gt;System.Web.UI.Control&lt;/code&gt; class, so &lt;em&gt;all&lt;/em&gt; server controls have this property, including the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class. You can therefore indicate that an entire page&#39;s view state need not be saved by setting the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class&#39;s &lt;code class=&quot;ce&quot;&gt;EnableViewState&lt;/code&gt; to False. (This can be done either in the code-behind class with &lt;code class=&quot;ce&quot;&gt;Page.EnableViewState = false;&lt;/code&gt; or as a &lt;code class=&quot;ce&quot;&gt;@Page&lt;/code&gt;-level directive—&lt;code class=&quot;ce&quot;&gt;&amp;lt;%@Page EnableViewState=&quot;False&quot; %&amp;gt;&lt;/code&gt;.)&lt;br /&gt;
Not all Web controls record the same amount of information in their view state. The Label Web control, for example, records only programmatic changes to its properties, which won&#39;t greatly impact the size of the view state. The DataGrid, however, stores all of its contents in the view state. For a DataGrid with many columns and rows, the view state size can quickly add up! For example, the DataGrid shown in Figure 6 (and included in this article&#39;s code download as &lt;code class=&quot;ce&quot;&gt;HeavyDataGrid.aspx&lt;/code&gt;) has a view state size of roughly 2.8 kilobytes, and a total page size of 5,791 bytes. (Almost half of the page&#39;s size is due to the &lt;code class=&quot;ce&quot;&gt;__VIEWSTATE&lt;/code&gt; hidden form field!) Figure 7 shows a screenshot of the view state, which can be seen by visiting the ASP.NET Web page, doing a View\Source, and then locating the &lt;code class=&quot;ce&quot;&gt;__VIEWSTATE&lt;/code&gt; hidden form field.&lt;br /&gt;
&lt;div class=&quot;fig&quot;&gt;&lt;img alt=&quot;ms972976.viewstate_fig06(en-us,MSDN.10).gif&quot; id=&quot;viewstate_fig06&quot; src=&quot;http://i.msdn.microsoft.com/dynimg/IC146676.gif&quot; title=&quot;ms972976.viewstate_fig06(en-us,MSDN.10).gif&quot; xmlns=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;label&quot;&gt;&lt;strong&gt;Figure 6. DataGrid control&lt;/strong&gt;&lt;/div&gt;&lt;div class=&quot;fig&quot;&gt;&lt;img alt=&quot;ms972976.viewstate_fig07(en-us,MSDN.10).gif&quot; id=&quot;viewstate_fig07&quot; src=&quot;http://i.msdn.microsoft.com/dynimg/IC141866.gif&quot; title=&quot;ms972976.viewstate_fig07(en-us,MSDN.10).gif&quot; xmlns=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;label&quot;&gt;&lt;strong&gt;Figure 7. View State for DataGrid control&lt;/strong&gt;&lt;/div&gt;The download for this article also includes an ASP.NET Web page called &lt;code class=&quot;ce&quot;&gt;LightDataGrid.aspx&lt;/code&gt;, which has the same DataGrid as shown in Figure 6, but with the &lt;code class=&quot;ce&quot;&gt;EnableViewState&lt;/code&gt; property set to False. The total view state size for this page? 96 bytes. The entire page size clocks in a 3,014 bytes. &lt;code class=&quot;ce&quot;&gt;LightDataGrid.aspx &lt;/code&gt;boasts a view state size about 1/30&lt;span class=&quot;sup&quot;&gt;th&lt;/span&gt; the size of &lt;code class=&quot;ce&quot;&gt;HeavyDataGrid.aspx&lt;/code&gt;, and a total download size that&#39;s about half of &lt;code class=&quot;ce&quot;&gt;HeavyDataGrid.aspx&lt;/code&gt;. With wider DataGrids with more rows, this difference would be even more pronounced. (For more information on performance comparisons between view state-enabled DataGrids and view state-disabled DataGrids, refer to &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/aa479015.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Deciding When to Use the DataGrid, DataList, or Repeater&lt;/span&gt;&lt;/a&gt;.)&lt;br /&gt;
Hopefully the last paragraph convinces you of the benefit of intelligently setting the &lt;code class=&quot;ce&quot;&gt;EnableViewState&lt;/code&gt; property to False, especially for &quot;heavy&quot; view state controls like the DataGrid. The question now, is, &quot;When can I safely set the &lt;code class=&quot;ce&quot;&gt;EnableViewState&lt;/code&gt; property to False?&quot; To answer that question, consider when you need to use the view state—&lt;strong&gt;only when you need to remember state across postbacks&lt;/strong&gt;. The DataGrid stores its contents in the view state so the page developer doesn&#39;t need to rebind the database data to the DataGrid on each and every page load, but only on the first one. The benefit is that the database doesn&#39;t need to be accessed as often. If, however, you set a DataGrid&#39;s &lt;code class=&quot;ce&quot;&gt;EnableViewState&lt;/code&gt; property to False, you&#39;ll need to rebind the database data to the DataGrid on both the first page load and every subsequent postback.&lt;br /&gt;
For a Web page that has a read-only DataGrid, like the one in Figure 6, you&#39;d definitely want to set the DataGrid&#39;s &lt;code class=&quot;ce&quot;&gt;EnableViewState&lt;/code&gt; property to False. You can even create sortable and pageable DataGrids with the view state disabled (as can be witnessed in the &lt;code class=&quot;ce&quot;&gt;LightDataGrid-WithFeatures.aspx&lt;/code&gt; page, included in the download), but, again, you&#39;ll need to be certain to bind the database data to the DataGrid on the first page visit, as well as on all subsequent postbacks.&lt;br /&gt;
&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;Creating an editable DataGrid with disabled view state requires some intricate programming, which involves parsing of the posted back form fields in the editable DataGrid. Such strenuous effort is required because, with an editable DataGrid blindly rebinding, the database data to the DataGrid will overwrite any changes the user made (see &lt;a href=&quot;http://datawebcontrols.com/faqs/Editing/EditedValuesNotSaved.shtml&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;this FAQ&lt;/span&gt;&lt;/a&gt; for more information).&lt;/div&gt;&lt;/blockquote&gt;&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic10&quot;&gt;&lt;/a&gt;Specifying Where to Persist the View State&lt;/h2&gt;After the page has collected the view state information for all of the controls in its control hierarchy in the save view state stage, it persists it to the &lt;code class=&quot;ce&quot;&gt;__VIEWSTATE&lt;/code&gt; hidden form field. This hidden form field can, of course, greatly add to the overall size of the Web page. The view state is serialized to the hidden form field in the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class&#39;s &lt;code class=&quot;ce&quot;&gt;SavePageStateToPersistenceMedium()&lt;/code&gt; method during the save view state stage, and is deserialized by the Page class&#39;s &lt;code class=&quot;ce&quot;&gt;LoadPageStateFromPersistenceMedium()&lt;/code&gt; method in the load view state stage. With just a bit of work we can have the view state persisted to the Web server&#39;s file system, rather than as a hidden form field weighing down the page. To accomplish this we&#39;ll need to create a class that derives from the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class and overrides the &lt;code class=&quot;ce&quot;&gt;SavePageStateToPersistenceMedium()&lt;/code&gt; and &lt;code class=&quot;ce&quot;&gt;LoadPageStateFromPersistenceMedium()&lt;/code&gt; methods.&lt;br /&gt;
&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;There is a third-party product called &lt;a href=&quot;http://www.flesk.net/fleskviewstate.htm&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Flesk.ViewStateOptimizer&lt;/span&gt;&lt;/a&gt; that reduces the view state bloat using a similar technique.&lt;/div&gt;&lt;/blockquote&gt;The view state is serialized and deserialized by the &lt;code class=&quot;ce&quot;&gt;System.Web.UI.LosFormatter&lt;/code&gt; class—the LOS stands for limited object serialization—and is designed to efficiently serialize certain types of objects into a base-64 encoded string. The &lt;code class=&quot;ce&quot;&gt;LosFormatter&lt;/code&gt; can serialize any type of object that can be serialized by the &lt;code class=&quot;ce&quot;&gt;BinaryFormatter&lt;/code&gt; class, but is built to efficiently serialize objects of the following types: &lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Strings&lt;/li&gt;
&lt;li&gt;Integers&lt;/li&gt;
&lt;li&gt;Booleans&lt;/li&gt;
&lt;li&gt;Arrays&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;ce&quot;&gt;ArrayList&lt;/code&gt;s&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;ce&quot;&gt;Hashtable&lt;/code&gt;s&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;ce&quot;&gt;Pair&lt;/code&gt;s&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;ce&quot;&gt;Triplet&lt;/code&gt;s&lt;/li&gt;
&lt;/ul&gt;&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;The &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;Pair&lt;/div&gt;and &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;Triplet&lt;/div&gt;are two classes found in the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;System.Web.UI&lt;/div&gt;namespace, and provide a single class to store either two or three objects. The &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;Pair&lt;/div&gt;class has properties &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;First&lt;/div&gt;and &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;Second&lt;/div&gt;to access its two elements, while &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;Triplet&lt;/div&gt;has &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;First&lt;/div&gt;, &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;Second&lt;/div&gt;, and &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;Third&lt;/div&gt;as properties.&lt;/div&gt;&lt;/blockquote&gt;The &lt;code class=&quot;ce&quot;&gt;SavePageStateToPersistenceMedium()&lt;/code&gt; method is called from the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class and passed in the combined view state of the page&#39;s control hierarchy. When overriding this method, we need to use the &lt;code class=&quot;ce&quot;&gt;LosFormatter()&lt;/code&gt; to serialize the view state to a base-64 encoded string, and then store this string in a file on the Web server&#39;s file system. There are two main challenges with this approach: &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Coming up with an acceptable file naming scheme. Since the view state for a page will likely vary based on the user&#39;s interactions with the page, the stored view state must be unique for each user and for each page.&lt;/li&gt;
&lt;li&gt;Removing the view state files from the file system when they are no longer needed.&lt;/li&gt;
&lt;/ol&gt;To tackle the first challenge, we&#39;ll name the persisted view state file based on the user&#39;s &lt;code class=&quot;ce&quot;&gt;SessionID&lt;/code&gt; and the page&#39;s URL. This approach will work beautifully for all users whose browsers accept session-level cookies. Those who do not accept cookies, however, will have a unique session ID generated for them on each page visit, thereby making this naming technique unworkable for them. For this article I&#39;m just going to demonstrate using the &lt;code class=&quot;ce&quot;&gt;SessionID&lt;/code&gt; / URL file name scheme, although it won&#39;t work for those whose browsers are configured not to accept cookies. Also, it won&#39;t work for a Web farm unless all servers store the view state files to a centralized location.&lt;br /&gt;
&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&lt;/strong&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;One workaround would be to use a globally unique identifier (GUID) as the file name for the persisted view state, saving this GUID in a hidden form field on the ASP.NET Web page. This approach, unfortunately, would take quite a bit more effort than using the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;SessionID&lt;/div&gt;/ URL scheme, since it involves injecting a hidden form field into the Web Form. For that reason, I&#39;ll stick to illustrating the simpler approach for this article.&lt;/div&gt;&lt;/blockquote&gt;The second challenge arises because, each time a user visits a different page, a new file holding that page&#39;s view state will be created. Over time this will lead to thousands of files. Some sort of automated task would be needed to periodically clean out the view state files older than a certain date. I leave this as an exercise for the reader.&lt;br /&gt;
To persist view state information to a file, we start by creating a class that derives from the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class. This derived class, then, needs to override the &lt;code class=&quot;ce&quot;&gt;SavePageStateToPersistenceMedium()&lt;/code&gt; and &lt;code class=&quot;ce&quot;&gt;LoadPageStateFromPersistenceMedium()&lt;/code&gt; methods. The following code presents such a class:&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainer&quot; xmlns=&quot;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; name=&quot;CodeSpippet7&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainerCodeCollection&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBar&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBarText&quot; style=&quot;valign: top;&quot;&gt;&lt;a href=&quot;javascript:CodeSnippet_CopyCode(&#39;CodeSnippetContainerCode7&#39;);&quot; name=&quot;CodeSnippetname&quot; style=&quot;display: block;&quot; title=&quot;Copy to clipboard.&quot;&gt;Copy&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;LW_CodeSnippetContainerCode&quot; id=&quot;CodeSnippetContainerCode7&quot;&gt;&lt;div style=&quot;color: black;&quot;&gt;&lt;pre&gt;public class PersistViewStateToFileSystem : Page
{
   protected override void 
     SavePageStateToPersistenceMedium(object viewState)
   {
      // serialize the view state into a base-64 encoded string
      LosFormatter los = new LosFormatter();
      StringWriter writer = new StringWriter();
      los.Serialize(writer, viewState);
      // save the string to disk
      StreamWriter sw = File.CreateText(ViewStateFilePath);
      sw.Write(writer.ToString());
      sw.Close();
   }
   protected override object LoadPageStateFromPersistenceMedium()
   {
      // determine the file to access
      if (!File.Exists(ViewStateFilePath))
         return null;
      else
      {
         // open the file
         StreamReader sr = File.OpenText(ViewStateFilePath);
         string viewStateString = sr.ReadToEnd();
         sr.Close();
         // deserialize the string
         LosFormatter los = new LosFormatter();
         return los.Deserialize(viewStateString);
      }
   }
   public string ViewStateFilePath
   {
      get
      {
         string folderName = 
           Path.Combine(Request.PhysicalApplicationPath, 
           &quot;PersistedViewState&quot;);
         string fileName = Session.SessionID + &quot;-&quot; + 
           Path.GetFileNameWithoutExtension(Request.Path).Replace(&quot;/&quot;, 
           &quot;-&quot;) + &quot;.vs&quot;;
         return Path.Combine(folderName, fileName);
      }
   }
}

&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;The class contains a public property &lt;code class=&quot;ce&quot;&gt;ViewStateFilePath&lt;/code&gt;, which returns the physical path to the file where the particular view state information will be stored. This file path is dependent upon the user&#39;s &lt;code class=&quot;ce&quot;&gt;SessionID&lt;/code&gt; and the URL of the requested page.&lt;br /&gt;
Notice that the &lt;code class=&quot;ce&quot;&gt;SavePageStateToPersistenceMedium()&lt;/code&gt; method accepts an &lt;code class=&quot;ce&quot;&gt;object&lt;/code&gt; input parameter. This &lt;code class=&quot;ce&quot;&gt;object&lt;/code&gt; is the view state object that is built up from the save view state stage. The job of &lt;code class=&quot;ce&quot;&gt;SavePageStateToPersistenceMedium()&lt;/code&gt; is to serialize this object and persist it in some manner. The method&#39;s code simply creates an instance of the &lt;code class=&quot;ce&quot;&gt;LosFormatter&lt;/code&gt; object and invokes its &lt;code class=&quot;ce&quot;&gt;Serialize()&lt;/code&gt; method, serializing the passed-in view state information to the &lt;code class=&quot;ce&quot;&gt;StringWriter writer&lt;/code&gt;. Following that, the specified file is created (or overwritten, if it already exists) with the contents of the base-64 encoded, serialized view state string.&lt;br /&gt;
The &lt;code class=&quot;ce&quot;&gt;LoadPageStateFromPersistenceMedium()&lt;/code&gt; method is called at the beginning of the load view state stage. Its job is to retrieve the persisted view state and deserialize back into an object that can be propagated into the page&#39;s control hierarchy. This is accomplished by opening the same file where the persisted view state was stored on the last visit, and returning the deserialized version via the &lt;code class=&quot;ce&quot;&gt;Deserialize()&lt;/code&gt; method in&lt;code class=&quot;ce&quot;&gt; LosFormatter()&lt;/code&gt;.&lt;br /&gt;
Again, this approach won&#39;t work with users that do not accept cookies, but for those that do, the view state is persisted entirely on the Web server&#39;s file system, thereby adding 0 bytes to the overall page size!&lt;br /&gt;
&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;Another approach to reducing the bloat imposed by view state is to compress the serialized view state stream in the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;SavePageStateToPersistenceMedium()&lt;/div&gt;method, and then decompress it back to its original form in the &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;LoadPageStateFromPersistenceMedium()&lt;/div&gt;method. &lt;a href=&quot;http://www.mostlylucid.co.uk/&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Scott Galloway&lt;/span&gt;&lt;/a&gt; has a &lt;a href=&quot;http://www.mostlylucid.co.uk/posts/694.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;blog entry&lt;/span&gt;&lt;/a&gt; where he discusses his experiences with using &lt;a href=&quot;http://www.icsharpcode.net/OpenSource/SharpZipLib/&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;#ziplib&lt;/span&gt;&lt;/a&gt; library to compress the view state.&lt;/div&gt;&lt;/blockquote&gt;&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic11&quot;&gt;&lt;/a&gt;Parsing the View State&lt;/h2&gt;When a page is rendered, it serializes its view state into a base-64 encoded string using the &lt;code class=&quot;ce&quot;&gt;LosFormatter&lt;/code&gt; class and (by default) stores it in a hidden form field. On postback, the hidden form field is retrieved and deserialized back into the view state&#39;s object representation, which is then used to restore the state of the controls in the control hierarchy. One detail we have overlooked up to this point in the article is what, exactly, is the structure of the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class&#39;s view state object?&lt;br /&gt;
As we discussed earlier, entire view state of the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; is the sum of the view state of the controls in its control hierarchy. Put another way, at any point in the control hierarchy, the view state of that control represents the view state of that control along with the view state of all of its children controls. Since the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class forms the root of the control hierarchy, its view state represents the view state for the entire control hierarchy.&lt;br /&gt;
The &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class contains a &lt;code class=&quot;ce&quot;&gt;SavePageViewState()&lt;/code&gt;, which is invoked during the page life cycle&#39;s save view state stage. The &lt;code class=&quot;ce&quot;&gt;SavePageViewState()&lt;/code&gt; method starts by creating a Triplet that contains the following three items: &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;The page&#39;s hash code. This hash code is used to ensure that the view state hasn&#39;t been tampered with between postbacks. We&#39;ll talk more about view state hashing in the &quot;View State and Security Implications&quot; section.&lt;/li&gt;
&lt;li&gt;The collective view state of the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt;&#39;s control hierarchy.&lt;/li&gt;
&lt;li&gt;An &lt;code class=&quot;ce&quot;&gt;ArrayList&lt;/code&gt; of controls in the control hierarchy that need to be explicitly invoked by the page class during the raise postback event stage of the life cycle.&lt;/li&gt;
&lt;/ol&gt;The &lt;code class=&quot;ce&quot;&gt;First&lt;/code&gt; and &lt;code class=&quot;ce&quot;&gt;Third&lt;/code&gt; items in the &lt;code class=&quot;ce&quot;&gt;Triplet&lt;/code&gt; are relatively straightforward; the &lt;code class=&quot;ce&quot;&gt;Second&lt;/code&gt; item is where the view state for the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt;&#39;s control hierarchy is maintained. The &lt;code class=&quot;ce&quot;&gt;Second&lt;/code&gt; item is generated by the Page by calling the &lt;code class=&quot;ce&quot;&gt;SaveViewStateRecursive()&lt;/code&gt; method, which is defined in the &lt;code class=&quot;ce&quot;&gt;System.Web.UI.Control&lt;/code&gt; class. &lt;code class=&quot;ce&quot;&gt;SaveViewStateRecursive()&lt;/code&gt; saves the view state of the control and its descendents by returning a Triplet with the following information: &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;The state present in the &lt;code class=&quot;ce&quot;&gt;Control&lt;/code&gt;&#39;s &lt;code class=&quot;ce&quot;&gt;ViewState&lt;/code&gt; &lt;code class=&quot;ce&quot;&gt;StageBag&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;An &lt;code class=&quot;ce&quot;&gt;ArrayList&lt;/code&gt; of integers. This &lt;code class=&quot;ce&quot;&gt;ArrayList&lt;/code&gt; maintains the indexes of the &lt;code class=&quot;ce&quot;&gt;Control&lt;/code&gt;&#39;s child controls that have a non-&lt;code class=&quot;ce&quot;&gt;null&lt;/code&gt; view state.&lt;/li&gt;
&lt;li&gt;An &lt;code class=&quot;ce&quot;&gt;ArrayList&lt;/code&gt; of the view states for the children controls. The &lt;em&gt;i&lt;/em&gt;th view state in this &lt;code class=&quot;ce&quot;&gt;ArrayList&lt;/code&gt; maps to the child control index in the &lt;em&gt;i&lt;/em&gt;th item in the &lt;code class=&quot;ce&quot;&gt;ArrayList&lt;/code&gt; in the &lt;code class=&quot;ce&quot;&gt;Triplet&lt;/code&gt;&#39;s &lt;code class=&quot;ce&quot;&gt;Second&lt;/code&gt; item.&lt;/li&gt;
&lt;/ol&gt;The &lt;code class=&quot;ce&quot;&gt;Control&lt;/code&gt; class computes the view state, returning a &lt;code class=&quot;ce&quot;&gt;Triplet&lt;/code&gt;. The &lt;code class=&quot;ce&quot;&gt;Second&lt;/code&gt; item of the &lt;code class=&quot;ce&quot;&gt;Triplet&lt;/code&gt; contains the view state of the &lt;code class=&quot;ce&quot;&gt;Control&lt;/code&gt;&#39;s descendents. The end result is that the view state is comprised of many &lt;code class=&quot;ce&quot;&gt;ArrayList&lt;/code&gt;s inside of &lt;code class=&quot;ce&quot;&gt;Triplet&lt;/code&gt;s inside of &lt;code class=&quot;ce&quot;&gt;Triplet&lt;/code&gt;s, inside of &lt;code class=&quot;ce&quot;&gt;Triplet&lt;/code&gt;s, inside of... (The precise contents in the view state depend on the controls in the hierarchy. More complex controls might serialize their own state to the view state using &lt;code class=&quot;ce&quot;&gt;Pair&lt;/code&gt;s or &lt;code class=&quot;ce&quot;&gt;object&lt;/code&gt; arrays. As we&#39;ll see shortly, though, the view state is composed of a number of &lt;code class=&quot;ce&quot;&gt;Triplet&lt;/code&gt;s and &lt;code class=&quot;ce&quot;&gt;ArrayList&lt;/code&gt;s nested as deep as the control hierarchy.)&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;Programmatically Stepping Through the View State&lt;/h3&gt;With just a little bit of work we can create a class that can parse through the view state and display its contents. The download for this article includes a class called &lt;code class=&quot;ce&quot;&gt;ViewStateParser&lt;/code&gt; that provides such functionality. This class contains a &lt;code class=&quot;ce&quot;&gt;ParseViewState()&lt;/code&gt; method that recursively steps through the view state. It takes in three inputs: &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;The current view state object.&lt;/li&gt;
&lt;li&gt;How many levels deep we are in the view state recursion.&lt;/li&gt;
&lt;li&gt;A text label to display.&lt;/li&gt;
&lt;/ol&gt;The last two input parameters are just for display purposes. The code of this method, shown below, determines the type of the current view state object and displays the contents of the view state accordingly, by recursively calling itself on each of the current object&#39;s members. (The variable &lt;code class=&quot;ce&quot;&gt;tw&lt;/code&gt; is a &lt;code class=&quot;ce&quot;&gt;TextWriter&lt;/code&gt; instance to which the output is being written.)&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainer&quot; xmlns=&quot;&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; name=&quot;CodeSpippet8&quot;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;div class=&quot;LW_CodeSnippetContainerCodeCollection&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBar&quot;&gt;&lt;div class=&quot;LW_CodeSnippetToolBarText&quot; style=&quot;valign: top;&quot;&gt;&lt;a href=&quot;javascript:CodeSnippet_CopyCode(&#39;CodeSnippetContainerCode8&#39;);&quot; name=&quot;CodeSnippetname&quot; style=&quot;display: block;&quot; title=&quot;Copy to clipboard.&quot;&gt;Copy&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;LW_CodeSnippetContainerCode&quot; id=&quot;CodeSnippetContainerCode8&quot;&gt;&lt;div style=&quot;color: black;&quot;&gt;&lt;pre&gt;protected virtual void ParseViewStateGraph(
  object node, int depth, string label)
{
   tw.Write(System.Environment.NewLine);
   if (node == null)
   {
      tw.Write(String.Concat(Indent(depth), label, &quot;NODE IS NULL&quot;));
   } 
   else if (node is Triplet)
   {
      tw.Write(String.Concat(Indent(depth), label, &quot;TRIPLET&quot;));
      ParseViewStateGraph(
        ((Triplet) node).First, depth+1, &quot;First: &quot;);
      ParseViewStateGraph(
        ((Triplet) node).Second, depth+1, &quot;Second: &quot;);
      ParseViewStateGraph(
        ((Triplet) node).Third, depth+1, &quot;Third: &quot;);
   }
   else if (node is Pair)
   {
      tw.Write(String.Concat(Indent(depth), label, &quot;PAIR&quot;));
      ParseViewStateGraph(((Pair) node).First, depth+1, &quot;First: &quot;);
      ParseViewStateGraph(((Pair) node).Second, depth+1, &quot;Second: &quot;);
   }
   else if (node is ArrayList)
   {
      tw.Write(String.Concat(Indent(depth), label, &quot;ARRAYLIST&quot;));
      // display array values
      for (int i = 0; i &amp;lt; ((ArrayList) node).Count; i++)
         ParseViewStateGraph(
           ((ArrayList) node)[i], depth+1, String.Format(&quot;({0}) &quot;, i));
   }
   else if (node.GetType().IsArray)
   {
      tw.Write(String.Concat(Indent(depth), label, &quot;ARRAY &quot;));
      tw.Write(String.Concat(&quot;(&quot;, node.GetType().ToString(), &quot;)&quot;));
IEnumerator e = ((Array) node).GetEnumerator();
      int count = 0;
      while (e.MoveNext())
         ParseViewStateGraph(
           e.Current, depth+1, String.Format(&quot;({0}) &quot;, count++));
   }
   else if (node.GetType().IsPrimitive || node is string)
   {
      tw.Write(String.Concat(Indent(depth), label));
      tw.Write(node.ToString() + &quot; (&quot; + 
        node.GetType().ToString() + &quot;)&quot;);
   }
   else
   {
      tw.Write(String.Concat(Indent(depth), label, &quot;OTHER - &quot;));
      tw.Write(node.GetType().ToString());
   }
}

&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;As the code shows, the &lt;code class=&quot;ce&quot;&gt;ParseViewState()&lt;/code&gt; method iterates through the expected types—&lt;code class=&quot;ce&quot;&gt;Triplet&lt;/code&gt;, &lt;code class=&quot;ce&quot;&gt;Pair&lt;/code&gt;, &lt;code class=&quot;ce&quot;&gt;ArrayList&lt;/code&gt;, arrays, and primitive types. For scalar values—integers, strings, etc.—the type and value are displayed; for aggregate types—arrays, Pairs, &lt;code class=&quot;ce&quot;&gt;Triplet&lt;/code&gt;s, etc.—the members that compose the type are displayed by recursively invoking &lt;code class=&quot;ce&quot;&gt;ParseViewState()&lt;/code&gt;.&lt;br /&gt;
The &lt;code class=&quot;ce&quot;&gt;ViewStateParser&lt;/code&gt; class can be utilized from an ASP.NET Web page (see the &lt;code class=&quot;ce&quot;&gt;ParseViewState.aspx&lt;/code&gt; demo), or can be accessed directly from the &lt;code class=&quot;ce&quot;&gt;SavePageStateToPersistenceMedium()&lt;/code&gt; method in a class that is derived from the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class (see the &lt;code class=&quot;ce&quot;&gt;ShowViewState&lt;/code&gt; class). Figures 8 and9 show the &lt;code class=&quot;ce&quot;&gt;ParseViewState.aspx&lt;/code&gt; demo in action. As Figure 8 shows, the user is presented with a multi-line textbox into which they can paste the hidden &lt;code class=&quot;ce&quot;&gt;__VIEWSTATE&lt;/code&gt; form field from some Web page. Figure 9 shows a snippet of the parsed view state for a page displaying file system information in a DataGrid.&lt;br /&gt;
&lt;div class=&quot;fig&quot;&gt;&lt;img alt=&quot;ms972976.viewstate_fig08(en-us,MSDN.10).gif&quot; id=&quot;viewstate_fig08&quot; src=&quot;http://i.msdn.microsoft.com/dynimg/IC155724.gif&quot; title=&quot;ms972976.viewstate_fig08(en-us,MSDN.10).gif&quot; xmlns=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;label&quot;&gt;&lt;strong&gt;Figure 8. Decoding ViewState&lt;/strong&gt;&lt;/div&gt;&lt;div class=&quot;fig&quot;&gt;&lt;img alt=&quot;ms972976.viewstate_fig09(en-us,MSDN.10).gif&quot; id=&quot;viewstate_fig09&quot; src=&quot;http://i.msdn.microsoft.com/dynimg/IC76242.gif&quot; title=&quot;ms972976.viewstate_fig09(en-us,MSDN.10).gif&quot; xmlns=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;label&quot;&gt;&lt;strong&gt;Figure 9. ViewState decoded&lt;/strong&gt;&lt;/div&gt;In addition to the view state parser provided in this article&#39;s download, &lt;a href=&quot;http://weblogs.asp.net/pwilson/&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Paul Wilson&lt;/span&gt;&lt;/a&gt; provides a &lt;a href=&quot;http://www.wilsondotnet.com/Demos/ViewState.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;view state parser&lt;/span&gt;&lt;/a&gt; on his Web site. &lt;a href=&quot;http://staff.develop.com/onion/&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Fritz Onion&lt;/span&gt;&lt;/a&gt; also has a &lt;a href=&quot;http://staff.develop.com/onion/resources.htm&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;view state decoder WinForms application&lt;/span&gt;&lt;/a&gt; available for download from the Resources section on his Web site.&lt;br /&gt;
&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic12&quot;&gt;&lt;/a&gt;View State and Security Implications&lt;/h2&gt;The view state for an ASP.NET Web page is stored, by default, as a base-64 encoded string. As we saw in the previous section, this string can easily be decoded and parsed, displaying the contents of the view state for all to see. This raises two security-related concerns: &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Since the view state can be parsed, what&#39;s to stop someone from changing the values, re-serializing it, and using the modified view state?&lt;/li&gt;
&lt;li&gt;Since the view state can be parsed, does that mean I can&#39;t place any sensitive information in the view state (such as passwords, connection strings, etc.)?&lt;/li&gt;
&lt;/ol&gt;Fortunately, the &lt;code class=&quot;ce&quot;&gt;LosFormatter&lt;/code&gt; class has capabilities to address both of these concerns, as we&#39;ll see over the next two sections. Before we delve into the solutions for these concerns, it is important to first note that view state should only be used to store non-sensitive data. View state does not house code, and should definitely not be used to place sensitive information like connection strings or passwords.&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;Protecting the View State from Modification&lt;/h3&gt;Even though view state should only store the state of the Web controls on the page and other non-sensitive data, nefarious users could cause you headaches if they could successfully modify the view state for a page. For example, imagine that you ran an eCommerce Web site that used a DataGrid to display a list of products for sale along with their cost. Unless you set the DataGrid&#39;s &lt;code class=&quot;ce&quot;&gt;EnableViewState&lt;/code&gt; property to False, the DataGrid&#39;s contents—the names and prices of your merchandise—will be persisted in the view state.&lt;br /&gt;
Nefarious users could parse the view state, modify the prices so they all read $0.01, and then deserialize the view state back to a base-64 encoded string. They could then send out e-mail messages or post links that, when clicked, submitted a form that sent the user to your product listing page, passing along the altered view state in the HTTP POST headers. Your page would read the view state and display the DataGrid data based on this view state. The end result? You&#39;d have a lot of customers thinking they were going to be able to buy your products for only a penny!&lt;br /&gt;
A simple means to protect against this sort of tampering is to use a &lt;em&gt;machine authentication check&lt;/em&gt;, or MAC. Machine authentication checks are designed to ensure that the data received by a computer is the same data that it transmitted out—namely, that it hasn&#39;t been tampered with. This is precisely what we want to do with the view state. With ASP.NET view state, the &lt;code class=&quot;ce&quot;&gt;LosFormatter&lt;/code&gt; performs a MAC by hashing the view state data being serialized, and appending this hash to the end of the view state. (A hash is a quickly computed digest that is commonly used in symmetric security scenarios to ensure message integrity.) When the Web page is posted back, the &lt;code class=&quot;ce&quot;&gt;LosFormatter&lt;/code&gt; checks to ensure that the appended hash matches up with the hashed value of the deserialized view state. If it does not match up, the view state has been changed en route.&lt;br /&gt;
By default, the &lt;code class=&quot;ce&quot;&gt;LosFormatter&lt;/code&gt; class applies the MAC. You can, however, customize whether or not the MAC occurs by setting the &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class&#39;s &lt;code class=&quot;ce&quot;&gt;EnableViewStateMac&lt;/code&gt; property. The default, True, indicates that the MAC should take place; a value of False indicates that it should not. You can further customize the MAC by specifying what hashing algorithm should be employed. In the &lt;code class=&quot;ce&quot;&gt;machine.config&lt;/code&gt; file, search for the &lt;code class=&quot;ce&quot;&gt;&amp;lt;machineKey&amp;gt;&lt;/code&gt; element&#39;s &lt;code class=&quot;ce&quot;&gt;validation&lt;/code&gt; attribute. The default hashing algorithm used is SHA1, but you can change it to MD5 if you like. (For more information on the SHA1, see &lt;a href=&quot;http://www.faqs.org/rfcs/rfc3174.html&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;RFC 3174&lt;/span&gt;&lt;/a&gt;; for more information on MD5, read &lt;a href=&quot;http://www.faqs.org/rfcs/rfc1321.html&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;RFC 1321&lt;/span&gt;&lt;/a&gt;.)&lt;br /&gt;
&lt;blockquote class=&quot;dtBlock&quot;&gt;&lt;div&gt;&lt;strong&gt;Note&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/strong&gt;When using &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;Server.Transfer()&lt;/div&gt;you may find you receive a problem with view state authentication. A number of articles online have mentioned that the only workaround is to set &lt;br /&gt;
&lt;div class=&quot;tt&quot;&gt;EnableViewStateMac&lt;/div&gt;to False. While this will certainly solve the problem, it opens up a security hole. For more information, including a secure workaround, consult &lt;a href=&quot;http://support.microsoft.com/default.aspx?scid=kb;EN-US;316920&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;this KB article&lt;/span&gt;&lt;/a&gt;.&lt;/div&gt;&lt;/blockquote&gt;&lt;h3 class=&quot;dtH1&quot;&gt;Encrypting the View State&lt;/h3&gt;Ideally the view state should not need to be encrypted, as it should never contain sensitive information. If needed, however, the &lt;code class=&quot;ce&quot;&gt;LosFormatter&lt;/code&gt; does provide limited encryption support. The &lt;code class=&quot;ce&quot;&gt;LosFormatter&lt;/code&gt; only allows for a single type of encryption: Triple DES. To indicate that the view state should be encrypted, set the &lt;code class=&quot;ce&quot;&gt;&amp;lt;machineKey&amp;gt;&lt;/code&gt; element&#39;s &lt;code class=&quot;ce&quot;&gt;validation&lt;/code&gt; attribute in the &lt;code class=&quot;ce&quot;&gt;machine.config&lt;/code&gt; file to &lt;code class=&quot;ce&quot;&gt;3DES&lt;/code&gt;.&lt;br /&gt;
In addition to the validation &lt;code class=&quot;ce&quot;&gt;attribute&lt;/code&gt;, the &lt;code class=&quot;ce&quot;&gt;&amp;lt;machineKey&amp;gt;&lt;/code&gt; element contains &lt;code class=&quot;ce&quot;&gt;validationKey&lt;/code&gt; and &lt;code class=&quot;ce&quot;&gt;decryptionKey&lt;/code&gt; attributes, as well. The &lt;code class=&quot;ce&quot;&gt;validationKey&lt;/code&gt; attribute specifies the key used for the MAC; &lt;code class=&quot;ce&quot;&gt;decryptionKey&lt;/code&gt; indicates the key used in the Triple DES encryption. By default, these attributes are set to the value &quot;AutoGenerate,IsolateApp,&quot; which uniquely autogenerates the keys for each Web application on the server. This setting works well for a single Web server environment, but if you have a Web farm, it&#39;s vital that all Web servers use the same keys for MAC and/or encryption and decryption. In this case you&#39;ll need to manually enter a shared key among the servers in the Web farm. For more information on this process, and the &lt;code class=&quot;ce&quot;&gt;&amp;lt;machineKey&amp;gt;&lt;/code&gt; element in general, refer to the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/w8h3skw9.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;&amp;lt;machineKey&amp;gt; technical documentation&lt;/span&gt;&lt;/a&gt; and Susan Warren&#39;s article &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms972427.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Taking a Bite Out of ASP.NET ViewState&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;The ViewStateUserKey Property&lt;/h3&gt;Microsoft® ASP.NET version 1.1 added an additional &lt;code class=&quot;ce&quot;&gt;Page&lt;/code&gt; class property—&lt;code class=&quot;ce&quot;&gt;ViewStateUserKey&lt;/code&gt;. This property, if used, must be assigned a string value in the initialization stage of the page life cycle (in the &lt;code class=&quot;ce&quot;&gt;Page_Init&lt;/code&gt; event handler). The point of the property is to assign some user-specific key to the view state, such as a username. The &lt;code class=&quot;ce&quot;&gt;ViewStateUserKey&lt;/code&gt;, if provided, is used as &lt;a href=&quot;http://www.dotnetjunkies.com/Tutorial/77D4AFDC-585D-4539-A364-30028327FF14.dcik&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;a salt to the hash&lt;/span&gt;&lt;/a&gt; during the MAC.&lt;br /&gt;
What the &lt;code class=&quot;ce&quot;&gt;ViewStateUserKey&lt;/code&gt; property protects against is the case where a nefarious user visits a page, gathers the view state, and then entices a user to visit the same page, passing in their view state (see Figure 10). For more information on this property and its application, refer to &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/aa302426.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Building Secure ASP.NET Pages and Controls&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;
&lt;div class=&quot;fig&quot;&gt;&lt;img alt=&quot;ms972976.viewstate_fig10(en-us,MSDN.10).gif&quot; id=&quot;viewstate_fig10&quot; src=&quot;http://i.msdn.microsoft.com/dynimg/IC161589.gif&quot; title=&quot;ms972976.viewstate_fig10(en-us,MSDN.10).gif&quot; xmlns=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;label&quot;&gt;&lt;strong&gt;Figure 10. Protecting against attacks using ViewStateUserKey&lt;/strong&gt;&lt;/div&gt;&lt;h2 class=&quot;dtH1&quot;&gt;&lt;a href=&quot;http://www.blogger.com/&quot; id=&quot;viewstate_topic13&quot;&gt;&lt;/a&gt;Conclusion&lt;/h2&gt;In this article we examined the ASP.NET view state, studying not only its purpose, but also its functionality. To best understand how view state works, it is important to have a firm grasp on the ASP.NET page life cycle, which includes stages for loading and saving the view state. In our discussions on the page life cycle, we saw that certain stages—such as loading postback data and raising postback events—were not in any way related to view state.&lt;br /&gt;
While view state enables state to be effortlessly persisted across postbacks, it comes at a cost, and that cost is page bloat. Since the view state data is persisted to a hidden form field, view state can easily add tens of kilobytes of data to a Web page, thereby increasing both the download and upload times for Web pages. To cut back on the page weight imposed by view state, you can selectively instruct various Web controls not to record their view state by setting the &lt;code class=&quot;ce&quot;&gt;EnableViewState&lt;/code&gt; property to False. In fact, view state can be turned off for an entire page by setting the &lt;code class=&quot;ce&quot;&gt;EnableViewState&lt;/code&gt; property to false in the &lt;code class=&quot;ce&quot;&gt;@Page&lt;/code&gt; directive. In addition to turning off view state at the page-level or control-level, you can also specify an alternate backing store for view state, such as the Web server&#39;s file system.&lt;br /&gt;
This article wrapped up with a look at security concerns with view state. By default, the view state performs a MAC to ensure that the view state hasn&#39;t been tampered with between postbacks. ASP.NET 1.1 provides the &lt;code class=&quot;ce&quot;&gt;ViewStateUserKey&lt;/code&gt; property to add an additional level of security. The view state&#39;s data can be encrypted using the Triple DES encryption algorithm, as well.&lt;br /&gt;
Happy Programming!&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;Works Consulted&lt;/h3&gt;There are a number of good resources for learning more about ASP.NET view state. &lt;a href=&quot;http://weblogs.asp.net/pwilson/&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Paul Wilson&lt;/span&gt;&lt;/a&gt; has provided a number of resources, such as &lt;a href=&quot;http://authors.aspalliance.com/PaulWilson/Articles/?id=7&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;View State: All You Wanted to Know&lt;/span&gt;&lt;/a&gt;, and the &lt;a href=&quot;http://www.wilsondotnet.com/Demos/ViewState.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Page View State Parser&lt;/span&gt;&lt;/a&gt;. &lt;a href=&quot;http://weblogs.asp.net/despos/&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Dino Esposito&lt;/span&gt;&lt;/a&gt; authored an article for &lt;a href=&quot;http://msdn.microsoft.com/msdnmag/default.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;MSDN Magazine&lt;/span&gt;&lt;/a&gt; in February, 2003, titled &lt;a href=&quot;http://msdn.microsoft.com/msdnmag/issues/03/02/CuttingEdge/&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;The ASP.NET View State&lt;/span&gt;&lt;/a&gt;, which discusses a technique for storing view state on the Web server&#39;s file system. &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms972427.aspx&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Taking a Bite Out of ASP.NET View State&lt;/span&gt;&lt;/a&gt;, written by Susan Warren, provides a good high-level overview of the view state, including a discussion on encrypting the view state. &lt;a href=&quot;http://www.mostlylucid.co.uk/&quot;&gt;&lt;span style=&quot;color: #1364c4;&quot;&gt;Scott Galloway&lt;/span&gt;&lt;/a&gt;&#39;s blog has some good posts on working with ASP.NET view state, too.&lt;br /&gt;
&lt;h3 class=&quot;dtH1&quot;&gt;&amp;nbsp;&lt;/h3&gt;</content><link rel='replies' type='application/atom+xml' href='http://jfvaleroso.blogspot.com/feeds/7308791372025941562/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://jfvaleroso.blogspot.com/2011/06/understanding-aspnet-view-state.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/7308791372025941562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/7308791372025941562'/><link rel='alternate' type='text/html' href='http://jfvaleroso.blogspot.com/2011/06/understanding-aspnet-view-state.html' title='Understanding ASP.NET View State'/><author><name>Jeffrey Valeroso</name><uri>http://www.blogger.com/profile/08001080593078135203</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1384162512306361231.post-8568373846118465631</id><published>2011-06-04T10:01:00.001-07:00</published><updated>2011-06-04T10:01:57.225-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="hungarian notation"/><title type='text'>ASP.NET Naming Convention(Hungarian Notation)</title><content type='html'>&lt;table&gt;&lt;tbody&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;font-weight: bold; height: 12.75pt; padding-bottom: 0in; padding-top: 0in; width: 109pt;&quot; width=&quot;145&quot;&gt;Control Name&lt;/td&gt; &lt;td class=&quot;xl22&quot; style=&quot;font-weight: bold; width: 122pt;&quot; width=&quot;163&quot;&gt;Example&lt;/td&gt; &lt;td class=&quot;xl22&quot; style=&quot;font-weight: bold; width: 106pt;&quot; width=&quot;141&quot;&gt;Prefix&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;Label&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;lblName&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;lbl&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;TextBox&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;txtName&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;txt&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;GridView&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;gvResult&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;gv&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;Button&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;btnSave&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;btn&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;ImageButton&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;ibtnSave&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;ibtn&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;Hyperlink&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;lnkHomePage&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;lnk&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;DropDownList&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;ddlCompany&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;ddl&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;ListBox&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;lstCompany&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;lst&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;DataList&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;dlstAddress&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;dlst&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;Repeater&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;repSection&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;rep&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;Checkbox&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;chkMailList&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;chk&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;CheckBoxList&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;chkAddress&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;chk&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;RadioButton&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;rdoSex&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;rdo&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;RadioButtonList&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;rdoAgeGroup&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;rdo&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;Image&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;imgLogo&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;img&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;Panel&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;panSection&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;pan&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;PlaceHolder&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;plhHeader&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;plh&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;Calender&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;calMyDate&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;cal&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;Adrotator&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;adrBanner&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;adr&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;Table&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;tblResults&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;tbl&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt;[All]Validators&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;valCreditCardNumber&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;val&lt;/td&gt;&lt;/tr&gt;
&lt;tr height=&quot;17&quot; style=&quot;height: 12.75pt;&quot;&gt; &lt;td class=&quot;xl22&quot; height=&quot;17&quot; style=&quot;height: 12.75pt; padding-bottom: 0in; padding-top: 0in;&quot;&gt;ValidationSummary&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;valsErrors&lt;/td&gt; &lt;td class=&quot;xl22&quot;&gt;vals&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt; &lt;/table&gt;</content><link rel='replies' type='application/atom+xml' href='http://jfvaleroso.blogspot.com/feeds/8568373846118465631/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://jfvaleroso.blogspot.com/2011/06/aspnet-naming-conventionhungarian.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/8568373846118465631'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/8568373846118465631'/><link rel='alternate' type='text/html' href='http://jfvaleroso.blogspot.com/2011/06/aspnet-naming-conventionhungarian.html' title='ASP.NET Naming Convention(Hungarian Notation)'/><author><name>Jeffrey Valeroso</name><uri>http://www.blogger.com/profile/08001080593078135203</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1384162512306361231.post-6522795962771586761</id><published>2011-02-12T03:55:00.000-08:00</published><updated>2011-02-12T04:38:39.551-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET Web Matrix"/><title type='text'>Introducing Microsoft® WebMatrix</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;http://www.microsoft.com/web/gallery/install.aspx?appid=webmatrix&quot;&gt;&lt;img border=&quot;0&quot; h5=&quot;true&quot; height=&quot;260&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKLU3caUfAZ50odbRzF_eyY7fYuyg9WxX17IqR7s951fptqw9dfp6Cpd7_aBLwyrOy6UWDEgyWwau009Qyk4i2MWrOBYizQDQcVXTfD5yLIJ99RR9Vd_aB1OZvEmh08nmY6b2kKF_lOsiF/s640/webmatix.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
WebMatrix is a brand new web development tool from Microsoft that includes everything you need for website development. Start from open source web applications, built-in web templates or just start writing code yourself. It’s all-inclusive, simple and best of all free. Developing websites has never been easier. &lt;br /&gt;
&lt;a href=&quot;http://www.microsoft.com/web/webmatrix/&quot;&gt;Learn More about WebMatrix&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://jfvaleroso.blogspot.com/feeds/6522795962771586761/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://jfvaleroso.blogspot.com/2011/02/introducing-microsoft-webmatrix.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/6522795962771586761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/6522795962771586761'/><link rel='alternate' type='text/html' href='http://jfvaleroso.blogspot.com/2011/02/introducing-microsoft-webmatrix.html' title='Introducing Microsoft® WebMatrix'/><author><name>Jeffrey Valeroso</name><uri>http://www.blogger.com/profile/08001080593078135203</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKLU3caUfAZ50odbRzF_eyY7fYuyg9WxX17IqR7s951fptqw9dfp6Cpd7_aBLwyrOy6UWDEgyWwau009Qyk4i2MWrOBYizQDQcVXTfD5yLIJ99RR9Vd_aB1OZvEmh08nmY6b2kKF_lOsiF/s72-c/webmatix.jpg" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1384162512306361231.post-2357555986225556357</id><published>2011-01-29T09:39:00.000-08:00</published><updated>2011-01-29T09:42:37.034-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET Pattern"/><title type='text'>ASP.NET Patterns every developer should know</title><content type='html'>&lt;strong&gt;Basic Design Patterns and Groups&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Design patterns fall into groups, based on the type and aims of the pattern. For example, some patterns provide presentation logic for displaying specific views that make up the user interface. Others control the way that the application behaves as the user interacts with it. There are also groups of patterns that specify techniques for persisting data, define best practices for data access, and indicate optimum approaches for creating instances of objects that the application uses. The following list shows some of the most common design patterns within these groups:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Presentation Logic &lt;ul&gt;&lt;li&gt;Model-View-Controller (MVC)&lt;/li&gt;
&lt;li&gt;Model-View-Presenter (MVP)&lt;/li&gt;
&lt;li&gt;Use Case Controller&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Host or Behavioral &lt;ul&gt;&lt;li&gt;Command&lt;/li&gt;
&lt;li&gt;Publish-Subscribe / Observer&lt;/li&gt;
&lt;li&gt;Plug-in / Module / Intercepting Filter&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Structural &lt;ul&gt;&lt;li&gt;Service Agent / Proxy / Broker&lt;/li&gt;
&lt;li&gt;Provider / Adapter&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Creational &lt;ul&gt;&lt;li&gt;Factory / Builder / Injection&lt;/li&gt;
&lt;li&gt;Singleton&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Persistence &lt;ul&gt;&lt;li&gt;Repository&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;The remaining sections of this and the two following articles discuss the patterns that are most suitable for use in ASP.NET, or which ASP.NET implements automatically and allows you to extend to adapt the behavior to suit your own requirements. See the index at the start of each article for a list of the patterns described. &lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Model-View-Controller and Model-View-Presenter Patterns&lt;/h2&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpxvzSFiFmO4QStNMLsp9agArOAPNEhpiVlXUR_Pfzv5jyYFFQ9pdvqlX_-DXsWg9u_AD5_djCMhqRWQc8IzO2LF_hMv39p5ILiUxm4_kHX13TuNssFiktZyqeNDulPPi-3z3d6R29U7HN/s1600/1.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;/a&gt;&lt;/div&gt;The Model-View-Controller (MVC) and Model-View-Presenter (MVP) Patterns improve reusability of business logic by separating the three components required to generate and manage a specific user interface (such as a single Web page). The Model contains the data that the View (the Web page) will display and allow the user to manipulate. The Controller or Presenter links the Model and the View, and manages all interaction and processing of the data in the Model (see Figure 1).&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpxvzSFiFmO4QStNMLsp9agArOAPNEhpiVlXUR_Pfzv5jyYFFQ9pdvqlX_-DXsWg9u_AD5_djCMhqRWQc8IzO2LF_hMv39p5ILiUxm4_kHX13TuNssFiktZyqeNDulPPi-3z3d6R29U7HN/s1600/1.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; s5=&quot;true&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpxvzSFiFmO4QStNMLsp9agArOAPNEhpiVlXUR_Pfzv5jyYFFQ9pdvqlX_-DXsWg9u_AD5_djCMhqRWQc8IzO2LF_hMv39p5ILiUxm4_kHX13TuNssFiktZyqeNDulPPi-3z3d6R29U7HN/s1600/1.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Figure 1 - The Model-View-Controller and Model-View-Presenter Patterns&lt;br /&gt;
In the MVC pattern, user interaction with the View raises events in the Controller, which updates the Model. The Model then raises events to update the View. However, this introduces a dependency between the Model and the View. To avoid this, the MVP pattern uses a Presenter that both updates the Model and receives update events from it, using these updates to update the View. The MVP pattern improves testability, as all the logic and processing occurs within the Presenter, but it does add some complexity to the implementation because updates must pass from the Presenter to the View.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Provider and Adapter Patterns&lt;/h2&gt;The Provider and Adapter patterns allows otherwise incompatible classes to work together by converting the interface of one class into an interface expected by the other. In more practical terms, these patterns provide separation between components that allows behavioral changes to occur without prior knowledge of requirements. The application and any data sources it uses, outputs it generates, or classes it must interact with, can be created independently yet still work together (see Figure 2).&lt;br /&gt;
&lt;br /&gt;
The Provider and Adapter patterns allows otherwise incompatible classes to work together by converting the interface of one class into an interface expected by the other. In more practical terms, these patterns provide separation between components that allows behavioral changes to occur without prior knowledge of requirements. The application and any data sources it uses, outputs it generates, or classes it must interact with, can be created independently yet still work together (see Figure 2).&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga3sFrMVCI05npnq5RCXfJ9ch2cUbQr4sKwm8WKgi5Z55f7MJpqVm8b_a1v-YYBgjiV8d2pk6SKZ0faUGXIPst7Xrb9GaqABrVDi4Yz_lg7ZX2kTzh9Ry4PFZTzAyxHlfAg1OoN8wk8FVO/s1600/2.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; s5=&quot;true&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga3sFrMVCI05npnq5RCXfJ9ch2cUbQr4sKwm8WKgi5Z55f7MJpqVm8b_a1v-YYBgjiV8d2pk6SKZ0faUGXIPst7Xrb9GaqABrVDi4Yz_lg7ZX2kTzh9Ry4PFZTzAyxHlfAg1OoN8wk8FVO/s1600/2.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Figure 2 - The Provider and Adapter Patterns&lt;br /&gt;
The Provider pattern separates the data processing objects, and the application, from the source data. It allows the code in the application to be independent of the type of data source and the format of the data. A Provider component or service exposes standard methods that the application can call to read and write data. Internally, it converts these calls to the equivalents that match the data source. This means that the application can work with any source data type (such as any kind of database, XML document, disk file, or data repository) for which a suitable provider is available.&lt;br /&gt;
The Adapter pattern has the same advantages, and works in a similar way. Often, the target of an Adapter is some kind of output. For example, a printer driver is an example of an Adapter. ASP.NET itself, and other frameworks such as Enterprise Library, make widespread use of the Provider and Adapter patterns.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Service Agent, Proxy, and Broker Patterns&lt;/h2&gt;Various patterns exist that remove dependencies between a client and a service by using intermediate brokers. There are many different implementations of the basic pattern, some of which use an extra service-agent logic component to connect the client with the local proxy or gateway interface (see Figure 3).&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLr03QEC0ZMCu_D2BLpDSoNI8Gy580AQrFOxiNIlmjjHvZ0_dh6A1ryKoPtdj6Fn2huafXX6RzXeRHwIYZ3cbd6RHm2jDo3AuzGQJJzXHkzvj_a4_Jb-6tfsIy1pRpsPtn0xDG563ap7uK/s1600/3.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; s5=&quot;true&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLr03QEC0ZMCu_D2BLpDSoNI8Gy580AQrFOxiNIlmjjHvZ0_dh6A1ryKoPtdj6Fn2huafXX6RzXeRHwIYZ3cbd6RHm2jDo3AuzGQJJzXHkzvj_a4_Jb-6tfsIy1pRpsPtn0xDG563ap7uK/s1600/3.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
Figure 3 - The Service Agent, Proxy, and Broker Patterns&lt;br /&gt;
The aim of all these patterns is to allow remote connection to, and use of, a service without the client having to know how the service works. The service exposes a Contract that defines its interface, such as the Web Service Description Language (WSDL) document for a Web Service. A client-side proxy or gateway interface uses the Contract to create a suitably formatted request, and passes this to the service interface. The service sends the formatted response back through its gateway interface to the client proxy, which exposes it to the client. In effect, the client just calls the service methods on the client proxy, which returns the results just as if the service itself was a local component.&lt;br /&gt;
In the Service Agent pattern, an extra component on the client can perform additional processing and logic operations to further separate the client from the remote service. For example, the Service Agent may perform service address lookup, manipulate or format the client data to match the proxy requirements, or carry out any other kind of processing requirements common to different clients that use the service.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Repository Pattern&lt;/h2&gt;The Repository pattern virtualizes storage of entities in a persistent medium, such as a database or as XML. For example, a repository may expose data held in the tables of a database as strongly typed Customer and Order objects rather than data sets or data rows. It effectively hides the storage implementation from the application code, and allows the use of a common set of methods in the application without requiring knowledge of the storage mechanism or format. Often, the repository uses a series of providers to connect to the source data (see Figure 4).&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7qh7XRH03z3N-diad8TlWsLW0dOAWArqoD6fp3nxECq5TkMtEfFlgJwyQuzvno2-fY8-b1ify7ixrl-pL5ajup0T2ReY-5gdzFy36z7frXVz0j7Nynj_IdJd3epwkXw-hVGCkMvRWyBA9/s1600/4.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; s5=&quot;true&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7qh7XRH03z3N-diad8TlWsLW0dOAWArqoD6fp3nxECq5TkMtEfFlgJwyQuzvno2-fY8-b1ify7ixrl-pL5ajup0T2ReY-5gdzFy36z7frXVz0j7Nynj_IdJd3epwkXw-hVGCkMvRWyBA9/s1600/4.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Figure 4 - The Repository Pattern&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;The Singleton Pattern&lt;/h2&gt;The Singleton pattern defines the creation of a class for which only a single instance can exist. It is useful for exposing read-only data, and static methods that do not rely on instance data. Rather than creating an instance of the class each time, the application obtains a reference to an existing instance using a static method of the class that implements the Singleton pattern.&lt;br /&gt;
If this is the first call to the method that returns the instance, the Singleton creates an instance, populates it with any required data, and returns that instance. Subsequent calls to the method simply return this instance. The instance lifetime is that of the application domain - in ASP.NET this is usually the lifetime of the domain Application object.&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;text-align: right;&quot;&gt;&lt;em&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;- info from &lt;/span&gt;&lt;/em&gt;&lt;a href=&quot;http://www.developerfusion.com/&quot;&gt;&lt;em&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;http://www.developerfusion.com/&lt;/span&gt;&lt;/em&gt;&lt;/a&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jfvaleroso.blogspot.com/feeds/2357555986225556357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://jfvaleroso.blogspot.com/2011/01/aspnet-patterns-every-developer-should.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/2357555986225556357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/2357555986225556357'/><link rel='alternate' type='text/html' href='http://jfvaleroso.blogspot.com/2011/01/aspnet-patterns-every-developer-should.html' title='ASP.NET Patterns every developer should know'/><author><name>Jeffrey Valeroso</name><uri>http://www.blogger.com/profile/08001080593078135203</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpxvzSFiFmO4QStNMLsp9agArOAPNEhpiVlXUR_Pfzv5jyYFFQ9pdvqlX_-DXsWg9u_AD5_djCMhqRWQc8IzO2LF_hMv39p5ILiUxm4_kHX13TuNssFiktZyqeNDulPPi-3z3d6R29U7HN/s72-c/1.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1384162512306361231.post-4442003588589442391</id><published>2011-01-22T07:48:00.000-08:00</published><updated>2011-01-22T08:18:26.757-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term=".Net Developer"/><title type='text'>Try Ramp- Up for .Net Developers</title><content type='html'>&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrgsP4g8rduSfmh_Svu1wXyYAcjJtIyo0jt6EjKurGts-v0PyDU2WD1-x-GISrhjo4CBcvp6gZD_rsbX1b9WrbrjFbBXv2qq-7hvdjz8j3CYsU0v0Z0qZ_JwMrPDoDsaTkCu_-WNfZpzUg/s1600/Untitled-1.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;177&quot; s5=&quot;true&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrgsP4g8rduSfmh_Svu1wXyYAcjJtIyo0jt6EjKurGts-v0PyDU2WD1-x-GISrhjo4CBcvp6gZD_rsbX1b9WrbrjFbBXv2qq-7hvdjz8j3CYsU0v0Z0qZ_JwMrPDoDsaTkCu_-WNfZpzUg/s640/Untitled-1.jpg&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Ramp Up is a free, online, community-based learning program that will help you build professional development skills. Join &lt;a href=&quot;http://msdn.microsoft.com/en-us/rampup/default&quot;&gt;Ramp Up&lt;/a&gt; (it&#39;s free!) and help advance your career.&lt;br /&gt;
&lt;br /&gt;
In the next few days, I&#39;ll be posting several stuff using this program..I&#39;ll try to keep you posted. Thanks</content><link rel='replies' type='application/atom+xml' href='http://jfvaleroso.blogspot.com/feeds/4442003588589442391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://jfvaleroso.blogspot.com/2011/01/try-ramp-up-for-net-developers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/4442003588589442391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/4442003588589442391'/><link rel='alternate' type='text/html' href='http://jfvaleroso.blogspot.com/2011/01/try-ramp-up-for-net-developers.html' title='Try Ramp- Up for .Net Developers'/><author><name>Jeffrey Valeroso</name><uri>http://www.blogger.com/profile/08001080593078135203</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrgsP4g8rduSfmh_Svu1wXyYAcjJtIyo0jt6EjKurGts-v0PyDU2WD1-x-GISrhjo4CBcvp6gZD_rsbX1b9WrbrjFbBXv2qq-7hvdjz8j3CYsU0v0Z0qZ_JwMrPDoDsaTkCu_-WNfZpzUg/s72-c/Untitled-1.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1384162512306361231.post-1743228376639270255</id><published>2011-01-13T07:49:00.001-08:00</published><updated>2011-01-13T08:32:16.623-08:00</updated><title type='text'>Welcome</title><content type='html'>Welcome to my blog. I just thought of creating my own blog...since everybody is into blogging..</content><link rel='replies' type='application/atom+xml' href='http://jfvaleroso.blogspot.com/feeds/1743228376639270255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://jfvaleroso.blogspot.com/2011/01/test.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/1743228376639270255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1384162512306361231/posts/default/1743228376639270255'/><link rel='alternate' type='text/html' href='http://jfvaleroso.blogspot.com/2011/01/test.html' title='Welcome'/><author><name>Jeffrey Valeroso</name><uri>http://www.blogger.com/profile/08001080593078135203</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>