Salient Solutions

wrasslin ones and nones for fun and profit - Sky Sanders' Blog
posts - 96, comments - 70, trackbacks - 0

ASP.Net ViewState Parser (__ViewState)

// Project: Salient
// http://salient.codeplex.com
//
// Copyright 2010, Sky Sanders <sky at skysanders.net>
// Dual licensed under the MIT or GPL Version 2 licenses.
// http://salient.codeplex.com/license
//
// Date: May 5 2010

#region

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Web.UI;
using System.Xml;

#endregion

namespace Salient.Web
{
    ///<summary>
    /// A helper class that decodes, deserializes the '__ViewState' hidden field
    /// of an ASP.Net in to an object and then XML serializes the object to provide
    /// a navigable map of the view state and control state.
    ///</summary>
    public class ViewStateParser
    {
        #region Fields

        private readonly XmlDocument _controlState;

        private readonly string _text;

        private readonly object _value;

        private readonly XmlDocument _viewState;

        #endregion

        #region Constructors

        ///<summary>
        ///</summary>
        ///<param name="fieldValue"></param>
        public ViewStateParser(string fieldValue)
        {
            _text = fieldValue;

            (_viewState = new XmlDocument())
                .AppendChild(_viewState.CreateElement("viewstate"));

            (_controlState = new XmlDocument())
                .AppendChild(_controlState.CreateElement("controlstate"));

            _value = new LosFormatter().Deserialize(_text);

            XmlSerializeValue(_viewState, _controlState, _viewState.DocumentElement, _value);
        }

        #endregion

        #region Properties

        ///<summary>
        ///</summary>
        public XmlDocument ControlState
        {
            get { return _controlState; }
        }

        ///<summary>
        /// The unencoded __ViewState
        ///</summary>
        public string Text
        {
            get { return _text; }
        }


        ///<summary>
        /// The ViewState object
        ///</summary>
        public object Value
        {
            get { return _value; }
        }


        ///<summary>
        ///
        ///</summary>
        public XmlDocument ViewState
        {
            get { return _viewState; }
        }

        #endregion

        #region Private Methods

        private static void XmlSerializeValue(XmlDocument viewState, XmlDocument controlState, XmlNode parentNode, object value)
        {
            if (value != null)
            {
                string typename = value.GetType().Name;

                if (typename == "HybridDictionary")
                {
                    XmlElement childNode = controlState.CreateElement(typename);

                    HybridDictionary hybridDictionary = (HybridDictionary) value;

                    if (controlState.DocumentElement != null)
                    {
                        controlState.DocumentElement.AppendChild(childNode);

                        foreach (object item in hybridDictionary)
                        {
                            XmlSerializeValue(controlState, controlState, childNode, item);
                        }
                    }
                }
                else
                {
                    XmlElement childNode = viewState.CreateElement(typename);

                    parentNode.AppendChild(childNode);

                    switch (typename)
                    {
                        case "Triplet":
                            Triplet triplet = (Triplet) value;

                            XmlSerializeValue(viewState, controlState, childNode, triplet.First);
                            XmlSerializeValue(viewState, controlState, childNode, triplet.Second);
                            XmlSerializeValue(viewState, controlState, childNode, triplet.Third);
                            break;

                        case "Pair":
                            Pair pair = (Pair) value;
                            XmlSerializeValue(viewState, controlState, childNode, pair.First);
                            XmlSerializeValue(viewState, controlState, childNode, pair.Second);
                            break;

                        case "ArrayList":
                            foreach (object item in (ArrayList) value)
                            {
                                XmlSerializeValue(viewState, controlState, childNode, item);
                            }
                            break;

                        case "Array":
                            foreach (object item in (Array) value)
                            {
                                XmlSerializeValue(viewState, controlState, childNode, item);
                            }
                            break;

                        case "DictionaryEntry":
                            DictionaryEntry dictionaryEntry = (DictionaryEntry) value;
                            XmlSerializeValue(viewState, controlState, childNode, dictionaryEntry.Key);
                            XmlSerializeValue(viewState, controlState, childNode, dictionaryEntry.Value);
                            break;

                        case "IndexedString":
                            childNode.InnerText = ((IndexedString) value).Value;
                            break;

                        default:
                            childNode.InnerText = value.ToString();
                            break;
                    }
                }
            }
        }

        #endregion
    }
}

Print | posted on Wednesday, May 05, 2010 8:55 PM |

Feedback

Gravatar

# re: ASP.Net ViewState Parser (__ViewState)

I'm curious to see the instances that your are using this functionality.
5/18/2010 12:51 AM | David Robbins
Gravatar

# re: ASP.Net ViewState Parser (__ViewState)

It is incorporated in the seed of an idea revolving around programmatic manipulation of asp.net pages. It is my thought that the viewstate/controlstate will assist in mapping the codebehind identifier to the clientId, thus allowing a tester to, say, insert a value in TextBox1 regardless of the actual clientId.

If it even moderately pans out it will be highlighted in the initial release of the Salient project.
5/18/2010 1:24 AM | Sky

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 3 and 3 and type the answer here:

Powered by: