I was working on some ASP.NET hacks and wanted to move the ViewState to the bottom of the page in order to get Google to pay more attention to my page and less to the wad of Base64'ed ViewState.
First I tried this because it's the closest to the way my mind works:
static readonly Regex viewStateRegex = new Regex(@"(<input type=""hidden"" name=""__VIEWSTATE"" value=""[a-zA-Z0-9\+=\\/]+"" />)", RegexOptions.Multiline|RegexOptions.Compiled);
static readonly Regex endFormRegex = new Regex(@"</form>", RegexOptions.Multiline|RegexOptions.Compiled);
protected override void Render(HtmlTextWriter writer)
//Defensive coding checks removed for speed and simplicity.
// If these don't work out, you've likely got bigger problems.
System.IO.StringWriter stringWriter = new System.IO.StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
string html = stringWriter.ToString();
Match viewStateMatch = viewStateRegex.Match(html);
string viewStateString = viewStateMatch.Captures.Value;
html = html.Remove(viewStateMatch.Index,viewStateMatch.Length);
// This will only work if you have only one </form> on the page
Match endFormMatch = endFormRegex.Match(html,viewStateMatch.Index);
html = html.Insert(endFormMatch.Index,viewStateString);
However, it was taking 1 thousanth of a second (~0.001230s) to do the work and that didn't feel right. Of course, by taking over the HtmlTextWriter and spitting it out as a string I've boogered up all the benefits of buffering and the whole streaming thing, but it still felt wrong.
So, against my better judgement, I did it again like this:
protected override void Render(System.Web.UI.HtmlTextWriter writer)
int StartPoint = html.IndexOf("<input type=\"hidden\" name=\"__VIEWSTATE\"");
if (StartPoint >= 0)
int EndPoint = html.IndexOf("/>", StartPoint) + 2;
string viewstateInput = html.Substring(StartPoint, EndPoint - StartPoint);
html = html.Remove(StartPoint, EndPoint - StartPoint);
int FormEndStart = html.IndexOf("</form>") - 1;
if (FormEndStart >= 0)
html = html.Insert(FormEndStart, viewstateInput);
I always assumed (mistake #1) that IndexOf was pretty expensive, particularly on larger strings. However, this method averaged out at 0.000995s. It consistently beat the Regex one, even though the Regex one was very simple, the Regexes were precompiled and (I think) simple.
Now, to be clear, I'm just playing here, and I know it's microperf and premature optimization. The really interesting thing would be to do a matrix of page size vs. viewstate size. You know, large page, small viewstate against small page, large viewstate and all points in between, then try it with both techniques and see which is better for these different scenarios. But, I'm tired and have other things to do, so if you like, there's some homework for you. What does this data set look like: viewstate size vs. page size vs. technique?
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. I am a failed stand-up comic, a cornrower, and a book author.
Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.