Monday, November 26, 2012

Resolving the Validation of viewstate MAC failed error

I have been receiving the following error on the page when I clicked on the link (in the Gridview) before the Page had fully loaded. My Page has a Gridview which uses DataKeyNames. Additionally it had a lot of Javascript ads which slowed down loading of the Page.

Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.

On doing some research, I found out that the due to the use of GridView and the DataKeyNames, the Framework implements a ViewState Encryption Technique for keeping the data secure. Hence, when a link is clicked on a partial page load, the encryption tag might not have been rendered on the page, causing the page to crash.  

I read this excellent post which aptly details the issue and its resolution.

Basically, it appears to be some sort of bug in the existing Framework and the blog posts a workaround.

I used Solution 3 since it still was keeping the Security aspects in place which executing the page elegantly. Basically what it did was to remove the Validation script right before the end of the form tag and place it after the beginning of the Tag. 
protected override void Render(System.Web.UI.HtmlTextWriter writer)
        System.IO.StringWriter stringWriter =
            new System.IO.StringWriter();
        HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
        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("", FormStart) + 1;
                if (EndForm >= 0)
                    html = html.Insert(EndForm, ViewStateInput);

There was an error in this gadget