using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Web.UI;
using System.Collections;
using System.Xml;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
namespace ViewState解码分析器
{
public partial class Form1 : Form
{
TextBox textbox = null;
public Form1()
{
InitializeComponent();
}
private void txtViewState_Leave(object sender, EventArgs e)
{
textbox = (TextBox)sender;
}
private void splitContainer1_SplitterMoved(object sender, SplitterEventArgs e)
{
if (textbox == null)
{
textbox = txtViewState;
}
textbox.Focus();
}
#region 对输入的ViewState字符串进行解码分析 + private void txtDecoder_Click(object sender, EventArgs e)
private void txtDecoder_Click(object sender, EventArgs e)
{
XmlDocument document = null;
string vs = get__ViewCodeString(txtViewState.Text.Trim());//获取待解码的ViewState字符串
if (string.IsNullOrEmpty(vs)) return;
byte[] buff = Encoding.UTF8.GetBytes(vs);
Stream stream = new MemoryStream(buff);
try
{
LosFormatter lf = new LosFormatter();
object allViewState = lf.Deserialize(stream);//解码
XmlDocument dom = ViewStateXmlBuilder.BuildXml(allViewState);
StringBuilder sb = new StringBuilder();
using (StringWriter writer = new StringWriter(sb))
{
dom.Save(writer);
}
txtResult.Text = sb.ToString();
}
catch (Exception er)
{
MessageBox.Show(er.Message, "解析错误", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
}
#endregion
#region 简化显示ViewState解码后的内容 + private void btnSimple_Click(object sender, EventArgs e)
private void btnSimple_Click(object sender, EventArgs e)
{
string s = Regex.Replace(txtResult.Text, "<[^>]+>", "");
txtResult.Text = Regex.Replace(s, @"(?m)^\s+{1}quot;, "\r\n");
}
#endregion
#region 窗体加载时设置Panel2的最小宽度 + private void Form1_Load(object sender, EventArgs e)
private void Form1_Load(object sender, EventArgs e)
{
splitContainer1.Panel2MinSize = 430;//设置Panel2的最小宽度
}
#endregion
#region 获取正确的待解码的ViewState + private string get__ViewCodeString(string s)
/// <summary>
/// 获取正确的待解码的ViewState
/// </summary>
/// <param name="s">可能含有“引号外多余内容”的ViewState串</param>
/// <returns></returns>
private string get__ViewCodeString(string s)
{
int p1 = s.IndexOf('"');
if (p1 >= 0)//若不含双引号,则取整串内容
{
int p2 = s.IndexOf('"', p1 + 1);
if (p2 > 0)//有一对双引号,则取双引号内部的东东
{
s = s.Substring(p1 + 1, p2 - p1 - 1);
}
else//若仅有一个双引号,则取引号两侧较长的字符串
{
string s1 = s.Substring(0, p1).Trim();
string s2 = s.Substring(p1 + 1).Trim();
s = s1.Length > s2.Length ? s1 : s2;
}
}
return s;
}
#endregion
}
#region 类ViewStateXmlBuilder,创建ViewState XMLDocument
public class ViewStateXmlBuilder
{
public static XmlDocument BuildXml(object tree)
{
XmlDocument dom = new XmlDocument();
dom.AppendChild(dom.CreateElement("ViewState"));
BuildElement(dom, dom.DocumentElement, tree);
return dom;
}
private static void BuildElement(XmlDocument dom, XmlElement elem, object treeNode)
{
if (treeNode != null)
{
XmlElement element;
Type type = treeNode.GetType();
if (type == typeof(Pair))
{
element = dom.CreateElement(GetShortTypename(treeNode));
elem.AppendChild(element);
BuildElement(dom, element, ((Pair)treeNode).First);
BuildElement(dom, element, ((Pair)treeNode).Second);
}
else if (type == typeof(Triplet))
{
element = dom.CreateElement(GetShortTypename(treeNode));
elem.AppendChild(element);
BuildElement(dom, element, ((Triplet)treeNode).First);
BuildElement(dom, element, ((Triplet)treeNode).Second);
BuildElement(dom, element, ((Triplet)treeNode).Third);
}
else if (type == typeof(ArrayList))
{
element = dom.CreateElement(GetShortTypename(treeNode));
elem.AppendChild(element);
foreach (object obj in (ArrayList)treeNode)
{
BuildElement(dom, element, obj);
}
}
else if (treeNode is Array)
{
element = dom.CreateElement("Array");
elem.AppendChild(element);
foreach (object obj in (Array)treeNode)
{
BuildElement(dom, element, obj);
}
}
else if (treeNode is HybridDictionary)
{
element = dom.CreateElement(GetShortTypename(treeNode));
dom.DocumentElement.AppendChild(element);
foreach (object obj in (HybridDictionary)treeNode)
{
BuildElement(dom, element, obj);
}
}
else if (treeNode is DictionaryEntry)
{
element = dom.CreateElement(GetShortTypename(treeNode));
elem.AppendChild(element);
DictionaryEntry entry = (DictionaryEntry)treeNode;
BuildElement(dom, element, entry.Key);
BuildElement(dom, element, entry.Value);
}
else
{
element = dom.CreateElement(GetShortTypename(treeNode));
if (type == typeof(IndexedString))
{
element.InnerText = ((IndexedString)treeNode).Value;
}
else
{
element.InnerText = treeNode.ToString();
}
elem.AppendChild(element);
}
}
}
private static string GetShortTypename(object obj)
{
string str = obj.GetType().ToString();
return str.Substring(str.LastIndexOf(".") + 1);
}
}
#endregion
}
通过对Page类的分析研究,对ViewState的组织结构有了进一步的了解。编写此程序,方便对ViewStste的分析,以便有效控制文件大小。
可能还存在其他的一些问题,目前发现的有:
原来开发的Web系统,比如VS2003、2005可能存在ViewState无法解码,难道不同VS版本间生成的ViewState稍有不同?
有时间,再研究 LosFormatte.Deserialize() 方法得到进一步的解释。