.

July 5, 2009

Validation of viewstate MAC failed error

when the following preconditions are true:

1. You aren't using a web farm.
2. It appears when using built-in databound controls such as GridView, DetailsView or FormView which utilize “DataKeyNames”.
3. It appears if you have a large page which loads slowly for any reason.

If following preconditions are true and you click a postbacking control/link and the page hasn't loaded completely in client browser, you might get the "Validation of ViewState MAC failed" exception.

When this happens, if you just try setting the page property "EnableViewStateMac" to false, it does not solve the problem, it just changes the error message in same navigation behavior:



The state information is invalid for
this page and might be corrupted.


Root Cause

This exception appears because Controls using DataKeyNames require Viewstate to be encrypted. When Viewstate is encrypted (Default mode, Auto, is to encrypt if controls require that, otherwise not), Page adds field just before closing of the < form > tag. But this hidden field might not have been rendered to the browser with long-running pages, and if you make a postback before it does, the browser initiates postback without this field (in form post collection). End result is that if this field is omitted on postback, the page doesn't know that Viewstate is encrypted and causes the aforementioned Exception. I.E. page expects to be fully-loaded before you make a postback.

And by the way similar problem is with event validation since __EVENTVALIDATION field is also rendered on the end of the form. This is a security feature that ensures that postback actions only come from events allowed and created by the server to help prevent spoofed postbacks. This feature is implemented by having controls register valid events when they render (as in, during their actual Render() methods). The end result is that at the bottom of your rendered tag, you'll see something like this: . When a postback occurs, ASP.NET uses the values stored in this hidden field to ensure that the button you clicked invokes a valid event. If it's not valid, you get the exception above.

The problem happens specifically when you postback before the EventValidation field has been rendered. If EventValidation is enabled (which it is, by default), but ASP.net doesn't see the hidden field when you postback, you also get the exception. If you submit a form before it has been entirely rendered, then chances are the EventValidation field has not yet been rendered, and thus ASP.NET cannot validate your click.

Workarounds

1. Set enableEventValidation to false and viewStateEncryptionMode to Never as follows:



This has the unwanted side-effect of disabling validation and encryption. On some sites, this may be ok to do, but it isn't a best practice, especially in publicly facing sites.



2. Another way around the problem is to mark the form as disabled and then enable it in script once the load is complete:
function enableForm() {
document.getElementById("form").disabled = false;
}

window.onLoad = enableForm();



Or you can disable the individual form elements and enable them once everything is loaded:

function disableElements(elements) {
for (var i = elements.length - 1; i >= 0; i--) {
var elmt = elements[i];

if (!elmt.disabled) {
elmt.disabled = true;
}
else {
elmt._wasDisabled = true;
}
}
}

function disableFormElements() {
disableElements(_form.getElementsByTagName("INPUT"));
disableElements(_form.getElementsByTagName("SELECT"));
disableElements(_form.getElementsByTagName("TEXTAREA"));
disableElements(_form.getElementsByTagName("BUTTON"));
disableElements(_form.getElementsByTagName("A"));
}

function enableElements(elements) {
for (var i = elements.length - 1; i >= 0; i--) {
var elmt = elements[i];
if (!elmt._wasDisabled) {
elmt.disabled = false;
}
else {
elmt._wasDisabled = null;
}
}
}

function enableFormElements() {
enableElements(_form.getElementsByTagName("INPUT"));
enableElements(_form.getElementsByTagName("SELECT"));
enableElements(_form.getElementsByTagName("TEXTAREA"));
enableElements(_form.getElementsByTagName("BUTTON"));
enableElements(_form.getElementsByTagName("A"));
}


Make sure that the variable _form is set to the ASP.net form on the page. Then just call enableFormElements() and disableFormElements().



3. The last way to workaround this problem is to override the Render Event of the page to place the hidden fields for Encrypted Viewstate and Event validation on the top of the form. This will ensure that these things get written out before anything that can submit the form:



protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
System.IO.StringWriter stringWriter =
new System.IO.StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
base.Render(htmlWriter);
string html = stringWriter.ToString();
string[] aspnet_formelems = new string[5];
aspnet_formelems[0] = "__EVENTTARGET";
aspnet_formelems[1] = "__EVENTARGUMENT";
aspnet_formelems[2] = "__VIEWSTATE";
aspnet_formelems[3] = "__EVENTVALIDATION";
aspnet_formelems[4] = "__VIEWSTATEENCRYPTED";
foreach (string elem in aspnet_formelems)
{
//Response.Write("input type=""hidden"" name=""" & abc.ToString & """")
int StartPoint = html.IndexOf("= 0)
{
//does __VIEWSTATE exist?
int EndPoint = html.IndexOf("/>", StartPoint) + 2;
string ViewStateInput = html.Substring(StartPoint,
EndPoint - StartPoint);
html = html.Remove(StartPoint, EndPoint - StartPoint);
int FormStart = html.IndexOf("< form "); int="" endform = "html. IndexOf("">", FormStart ) + 1;
if (EndForm >= 0)
html = html.Insert( EndForm , ViewStateInput);
}
}

writer.Write(html);
}


< / form");>
< / form>

July 2, 2009

About Visual Studio 2008

Microsoft Visual Studio is an Integrated Development Environment (IDE) from Microsoft. It can be used to develop console and graphical user interface applications along with Windows Forms applications, web sites, web applications, and web services in both native codetogether with managed code for all platforms supported by Microsoft Windows, Windows Mobile, Windows CE, .NET Framework, .NET Compact Framework and Microsoft Silverlight.

Visual Studio includes a code editor supporting IntelliSense as well as code refactoring. The integrated debugger works both as a source-level debugger and a machine-level debugger. Other built-in tools include a forms designer for building GUI applications, web designer, classdesigner, and database schema designer. It allows plug-ins to be added that enhance the functionality at almost every level - including adding support for source control systems (likeSubversion and Visual SourceSafe) to adding new toolsets like editors and visual designers fordomain-specific languages or toolsets for other aspects of the software development lifecycle(like the Team Foundation Server client: Team Explorer).

Visual Studio supports languages by means of language services, which allow anyprogramming language to be supported (to varying degrees) by the code editor and debugger, provided a language-specific service has been authored. Built-in languages include C/C++ (viaVisual C++), VB.NET (via Visual Basic .NET), and C# (via Visual C#). Support for other languages such as F#, M, Python, and Ruby among others has been made available via language services which are to be installed separately. It also supports XML/XSLT,HTML/XHTML, JavaScript and CSS. Language-specific versions of Visual Studio also exist which provide more limited language services to the user. These individual packages are called Microsoft Visual Basic, Visual J#, Visual C#, and Visual C++.

Microsoft provides "Express" editions of its Visual Studio 2008 components Visual Basic, Visual C#, Visual C++, and Visual Web Developer at no cost. Visual Studio 2008 and 2005 Professional Editions, along with language-specific versions (Visual Basic, C++, C#, J#) of Visual Studio 2005 are available for free to students as downloads via Microsoft's DreamSpark program. Visual Studio 2010 is currently in beta testing and can be downloaded by the general public at no cost.