惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
博客园 - 叶小钗
S
SegmentFault 最新的问题
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
博客园_首页
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
月光博客
月光博客
酷 壳 – CoolShell
酷 壳 – CoolShell
腾讯CDC
D
Darknet – Hacking Tools, Hacker News & Cyber Security
V
V2EX
阮一峰的网络日志
阮一峰的网络日志
L
Lohrmann on Cybersecurity
量子位
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tor Project blog
J
Java Code Geeks
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
博客园 - 三生石上(FineUI控件)
Attack and Defense Labs
Attack and Defense Labs
AI
AI
The Cloudflare Blog
T
Tailwind CSS Blog
S
Schneier on Security
爱范儿
爱范儿
PCI Perspectives
PCI Perspectives
Stack Overflow Blog
Stack Overflow Blog
S
Secure Thoughts
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
The Exploit Database - CXSecurity.com
博客园 - 【当耐特】
V2EX - 技术
V2EX - 技术
S
Securelist
P
Proofpoint News Feed
T
Threat Research - Cisco Blogs
Help Net Security
Help Net Security
C
Cisco Blogs
N
News and Events Feed by Topic
人人都是产品经理
人人都是产品经理
B
Blog RSS Feed
K
Kaspersky official blog
T
The Blog of Author Tim Ferriss
G
Google Developers Blog
S
Security Affairs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Simon Willison's Weblog
Simon Willison's Weblog

博客园 - hgtj

谈谈产品和项目 重新开始写博客 组件 访问被拒绝 --“/”应用程序中的服务器错误。IIS重启不行,系统注销也不行 (转).Net 揭密--JIT怎样运行你的代码 第一部分 (普通调用) MS-SQLSERVER数据库SUSPECT状态如何解决 Com Interop入门 可按任意字段排序的分页存储过程(转) 拨开SOA的面纱(一篇对SOA概念讲解的很透彻的文章) 基于角色管理的系统访问控制 MySQL查询优化系列讲座之查询优化器 SQL语句优化技术分析 对ORM的疑问 MonoRail - 生命周期及controller/action/view详解 (转) 了解AOP(转) 接口的终结解释 (转) Asp.Net 背后原理 关于类型转换方面的备忘 java设计模式之State(转) javascript 实现类似C#中字符串的Trim()方法
思归的“动态控件的状态问题”的分析
hgtj · 2006-04-21 · via 博客园 - hgtj

思归的“动态控件的状态问题”很有意思:XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:office" />

http://blog.joycode.com/saucer/archive/2004/10/20/35927.aspx

希望写下这样的logic对大家做troubleshooting有所帮助。我们可以这样分析这个问题:

第一步,简化一下Page。建一个新的ASP.net Web Application,用下面的code

private void Page_Load(object sender, System.EventArgs e)

{

        DropDownList ddlDynamic = new DropDownList();

        ddlDynamic.ID = "ddlDynamic";

        HtmlForm form1 = (HtmlForm)this.FindControl("Form1");

        if (!IsPostBack)

        {

                ddlDynamic.Items.Add("Before");

        }

        form1.Controls.Add(ddlDynamic);

        if (!IsPostBack)

        {

                ddlDynamic.Items.Add("After");

        }

}

Page上扔个Button,以便可以PostBack。运行后Postback的结果,“Before” item没被保留,“After”被保留了。问题被isolate:问题不在于DropDownList或者ListCollection对于view state的处理出问题,而是特定一个ListItem view state的处理有异。

现在有目标了,接下来看ListItem source code:

internal object SaveViewState()

{

      if (this.misc.Get(2) && this.misc.Get(3))

      {

            return new Pair(this.Text, this.Value);

      }

      if (this.misc.Get(2))

      {

            return this.Text;

      }

      if (this.misc.Get(3))

      {

            return new Pair(null, this.Value);

      }

      return null;

}

可以看到只有misc.Get(2)misc.Get(3)符合一定条件才存view state,鉴于miscprivate member,继续在ListItemcode里找什么会影响misc.Get(2) or misc.Get(3)的值,结果如下:

internal bool Dirty

{

       set

      {

            this.misc.Set(2, value);

            this.misc.Set(3, value);

      }

}

找到了唯一的可能,在Reflector里看Set方法的Callee Graph,找到System.Web.UI.WebControls.ListItemCollection.Add(ListItem):Void方法。接续看source code:

public void Add(ListItem item)

{

      this.listItems.Add(item);

      if (this.marked)

      {

            item.Dirty = true;

      }

}

这里有一个private bool marked flag。继续在ListItemCollection里找:

internal void TrackViewState()

{

      this.marked = true;

      for (int num1 = 0; num1 < this.Count; num1++)

      {

            this[num1].TrackViewState();

      }

}

void IStateManager.TrackViewState()

{

      this.TrackViewState();

}

好了,看来这个方法就是关键了……由于是Interface的方法,我们可以尝试一下在Page2里调用它:

((IStateManager)(ddlDynamic.Items)).TrackViewState();

if (!IsPostBack)
{
for (int i=1; i <=3; i++)
ddlDynamic.Items.Add(new ListItem(i.ToString(), i.ToString()));
}
form1.Controls.Add(ddlDynamic);

确实是起作用了……鉴于如此,我们可以猜测ControlCollection.Add一定调用了System.Web.UI.WebControls.ListItemCollection.TrackViewState()这个方法。要证明这点容易多了……

WinDbg,在System.Web.UI.WebControls.ListItemCollection.TrackViewState()方法上设个断点。Call Stack如下:

019cf8b0 06538fd0 [DEFAULT] [hasThis] Void System.Web.UI.WebControls.ListItemCollection.TrackViewState()
019cf8b4 06538fbe [DEFAULT] [hasThis] Void System.Web.UI.WebControls.ListControl.TrackViewState()
019cf8bc 06538e53 [DEFAULT] [hasThis] Void System.Web.UI.Control.InitRecursive(Class System.Web.UI.Control)
019cf8d8 0653758a [DEFAULT] [hasThis] Void System.Web.UI.Control.AddedControl(Class System.Web.UI.Control,I4)
019cf8f4 06537462 [DEFAULT] [hasThis] Void System.Web.UI.ControlCollection.Add(Class
System.Web.UI.Control)
019cf904 063c06fc [DEFAULT] [hasThis] Void WebApplication37.WebForm3.Page_Load(Object,Class System.EventArgs)
at [+0x13c] [+0x8c] c:\inetpub\wwwroot\webapplication37\webform3.aspx.cs:36
019cf944 065391a4 [DEFAULT] [hasThis] Void System.Web.UI.Control.OnLoad(Class System.EventArgs)

好了……一切都明了……