W3C Validation and ASP.NET ViewState
The problem
I came across a very interesting point about validating XHTML pages using W3C XHTML Strict and ViewState. By default ASP.NET ViewState adds a number of hidden fields to handle the postback of ASP.NET pages, control state and control event validation. See example below.
<input type=”hidden” name=”__VIEWSTATE” id=”__VIEWSTATE” value=”" />
When validating web pages using the XHTML strict option, you will find that the above line is invalid:
value of attribute “ID” invalid: “_” cannot start a name .
…type=”hidden” name=”__VIEWSTATE” id=”__VIEWSTATE” value=”/wEPDwUJOTkzNjk4NjQ4
This becomes a major issue when you have clients who expect their product to be compliant with todays web standards.
The solution
Step 1 - I created a FilterModule that inherits the IHttpModule interface which will be the basis of renaming the __VIEWSTATE to VIEWSTATE.
using System;
using System.Web;namespace Company.Utilities
{
public class IdFilterModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication app)
{
app.ReleaseRequestState += new EventHandler(InstallResponseFilter);
}
private void InstallResponseFilter(object sender, EventArgs e)
{
HttpResponse response = HttpContext.Current.Response;if (response.ContentType == “text/html”)
{
response.Filter = new IdFilter(response.Filter);
}
}
}
}
The above code creates a event handler called InstallResponseFilter that gets fired when the ReleaseRequestState event is raised. The ReleaseRequestState event saves all the current state data.
Step 2 - I then create a class inheriting from the Stream class that takes the current state data and does a simple search and replace on the key ViewState identifiers and adjusts the output to be what we decide is valid XHTML.
public class IdFilter : Stream
{
Stream responseStream;
StringBuilder responseHtml;
long position;public IdFilter(Stream inputStream)
{
responseStream = inputStream;
responseHtml = new StringBuilder();
}public override bool CanRead
{
get
{
return true;
}
}
public override bool CanSeek
{
get
{
return true;
}
}
public override bool CanWrite
{
get
{
return true;
}
}
public override void Close()
{
responseStream.Close();
}
public override void Flush()
{
responseStream.Flush();
}
public override long Length
{
get
{
return 0;
}
}
public override long Position
{
get
{
return position;
}
set
{
position = value;
}
}
public override long Seek(long offset, SeekOrigin origin)
{
return responseStream.Seek(offset, origin);
}
public override void SetLength(long length)
{
responseStream.SetLength(length);
}
public override int Read(byte[] buffer, int offset, int count)
{
return responseStream.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
string strBuffer = System.Text.UTF8Encoding.UTF8.GetString(buffer, offset, count);Regex eof = new Regex(“</html>”, RegexOptions.IgnoreCase);
if (!eof.IsMatch(strBuffer))
{
responseHtml.Append(strBuffer);
}
else
{
responseHtml.Append(strBuffer);string finalHtml = responseHtml.ToString();
finalHtml = finalHtml.Replace(“id=\”__VIEWSTATE\”", “id=\”VIEWSTATE\”");
finalHtml = finalHtml.Replace(“id=\”__EVENTARGUMENT\”", “id=\”\”EVENTARGUMENT”);
finalHtml = finalHtml.Replace(“id=\”\”__EVENTTARGET”, “id=\”\”EVENTTARGET”);
finalHtml = finalHtml.Replace(“ />”, “>”);
finalHtml = finalHtml.Replace(” />”, “>”);
finalHtml = finalHtml.Replace(“/>”, “>”);byte[] data = System.Text.UTF8Encoding.UTF8.GetBytes(finalHtml);
responseStream.Write(data, 0, data.Length);
}
}
}
The new IdFilterModule gets registered is the web.config file under httpModules.
References:
http://forum.umbraco.org/yaf_postst5965_W3C-Validation-ASPNET-ViewState-and-HTML-401.aspx
http://msdn.microsoft.com/en-us/library/system.web.httpapplication.releaserequeststate.aspx
1 Comment
Leave a Reply
You must be logged in to post a comment.



I use master page in my site. I put this code on a class library and built the solution and put the dll file on bin folder and register it on web.config file. How I use this in my master page to replace the __viewstate to viewstate.
Can any one please describe how I use this code step by to step?????