Don't get me wrong - I really don't like ASP.NET very much. I think it's overly complex, unless you have DS, and the default settings for just about everything are wrong, wrong, wrong. (See my rants about "malicious characters" - those bits intended harm!)

However, there is one thing that .NET got right - viewstate.

The viewstate is actually not a security control by design, but it's one of those "accidental security" features. What the viewstate provides is a means of the server to tell the client what values were on a form when the form was rendered. So, for example, if there's a table view type control, it's rendered in ordinary HTML, but the viewstate contains the values that were in the table when it was rendered. If a user clicks an item, the POST that goes back to the server contains the index of the element they clicked, not a key value.

There is a handy by-product of this, and a setting that can make it more secure.

The by-product of keeping the rendered values in the viewstate is that a level of indirection is achieved. The key values are kept in the view state, and so selections or manipulations take place against an index into the viewstate, rather than the key values.

That doesn't mean much if the user can alter the key values in the viewstate. But the viewstate is actually signed by default. So a key on the server is appended to the cleartext of the viewstate, and a hash of the viewstate with the key is appended to the viewstate itself. When the server receives the viewstate, it recalculates the hash by taking the plaintext of the viewstate (without the hash), appends the signing value again, then hashes again. This makes the viewstate tamper-proof by default.

So if I have a table view with items 1001, 1002, 1005, and 1006, and I decide I want to delete item 1004 (I don't have access), I'd have to decode the viewstate (no big deal, it's just base-64), alter the Nth item's key value to 1004, then re-calculate the hash. Only, by default, there's a value provided by the server that is appended to the viewstate before the hash is calculated. And it's not exactly trivial to get that hash value - Web.config is guarded even more closely (in my experience) than web.xml in J2EE - even if the application provides a directory traversal, it's hard to get at.

Another feature of viewstate is that if you configure it properly, you can actually encrypt the viewstate. Since Javascript doesn't manipulate the viewstate (it's just there for the user to carry it around so that really long lists aren't kept in server memory in sessions), it's okay for the user to carry around this encrypted value that only the server can decrypt. So then, not only do you get the tamper-proofing, you remove key exposure altogether because the user wouldn't be able to figure out the key values.

And all of this, you get "for free". Viewstate is an inherent part of using ASP.NET. The problem, however, is that in many implementations I've seen, it's just not used properly. Developers are rendering their own controls or adding their own linkages which contain the same old key exposure - and generally privilege escalation to boot.

So along with all the rotten things they did with ASP.NET, they got this one right. In other frameworks, you manage this by hand, and do so (generally) on the server side by keeping all those values in the session, so if you've got a million users with hundreds of rows showing on their screen at once you've got memory management issues to deal with.