有点背景...在工作中,我已从Windows XP(32位)升级到Windows 7(64位)。升级时,我也从以下位置切换:
Visual Web Developer 2005速成版到Web的Visual Studio Express 2013
从ASP.Net 2.0到ASP.Net 4.5.1
转换到GitHub
我正在测试我的网站,以确保什么都没有发生,并且发生了某些事情……通过我指定的键将值存储在ViewState
中似乎已损坏。
早期,我创建了一些用户控件(.ascx),以使生活更加轻松。为了保留属性,我将它们存储在ViewState
中,该属性在ASP.Net 2.0中绝对正常。
属性存储的示例(来自我的ValidatedTextBox
类,该类是具有预定义验证器的<asp:TextBox />
):
Private ReadOnly Property ViewStateControlPrefix() As String
Get
Return "Maggie:ValidatedTextBox:" & txt.ClientID & ":"
End Get
End Property
Public Property TextMode() As System.Web.UI.WebControls.TextBoxMode
Get
If Not ViewState(Me.ViewStateControlPrefix & "TextMode") Is Nothing Then
Return ViewState(Me.ViewStateControlPrefix & "TextMode")
Else
Return System.Web.UI.WebControls.TextBoxMode.SingleLine
End If
End Get
Set(ByVal value As System.Web.UI.WebControls.TextBoxMode)
ViewState(Me.ViewStateControlPrefix & "TextMode") = value
End Set
End Property
既然已经发生了对ASP.Net 4.5.1的更新,那么它将不再能按我的预期工作。
ViewStateControlPrefix
返回我期望的值(例如"Maggie:ValidatedTextBox:ctl00_cphMaggie_vtKeywords_txt:"
),但这不是ViewState中的键实际是(应该是)。这是调试器中发生的情况的屏幕截图:
键的区别归结为
ClientID
属性。在
Get
中,将其设置为ctl00_cphMaggie_vtResponse_txt
,但在Set
中,将其设置为vtResponse_txt
,这使我在要检索值时不知所措。pages
中的web.config
元素已自动添加了controlRenderingCompatibilityVersion="4.0"
和clientIDMode="AutoID"
,我怀疑clientIDMode
无效) )。我也尝试使用Predictable
,但是会出现相同的问题(分别从UniqueID
到ctl00$cphMaggie$vtResponse$txt
)。我假设在
vtResponse$txt
上调用了Set
,因为我是通过ascx中的标记设置属性的:<Maggie:ValidatedTextBox ID="vtResponse" runat="server" CSSClass="rte" TextMode="MultiLine" Columns="60" Rows="20" IsRequiredField="false" IsValidatedField="false" ScrubberFunction="trim(normalizeWhitespace(this));" ScrubberFunctionTrigger="onchange" />
并且
PreInit
在Get
上显式调用。有人可以启发我:
为什么这在ASP.Net 2.0中有效,但现在不行?
是什么原因造成的?
我该如何解决?
更新
将
PreRender
切换为ClientIDMode
可使Static
属性非常一致(尽管在同一页面上有多个ClientID
控件时,其唯一性不足)。我还将此添加到控件的代码后面:
Protected Sub Page_Init(sender As Object, e As EventArgs) Handles Me.Init
Dim clientId As String = txt.ClientID
Dim uniqueId As String = txt.UniqueID
Dim h As Hashtable = New System.Collections.Hashtable(ViewState)
Dim i As Integer = 0 'Used for a breakpoint
End Sub
暂停
ValidatedTextBox
行之后,很明显,在触发Dim i As Integer
事件时,已设置Init
属性(并且使用我惯用的方式)。另外,在.ascx.vb代码后面(我得到
ClientID
)中似乎没有要捕获的PreInit
事件,所以现在我真的很好奇何时调用属性设置器。更新
我已经尝试了以下所有方法:
将
"Event 'PreInit' cannot be found"
更改为ViewStateControlPrefix
在.ascx中的
Return "Maggie:ValidatedTextBox:" & txt.UniqueID & ":"
块中添加了clientIDMode
。在.ascx中的
<%@ Control %>
中添加了clientIDMode
。在
<asp:Textbox />
元素中的AutoID
,Predictable
,Inherit
和Static
中循环。在.ascx的
pages
块中的AutoID
,Predictable
,Inherit
和Static
中循环。在.ascx中的
<%@ Control %>
中的AutoID
,Predictable
,Inherit
和Static
中循环。将
<asp:Textbox />
从controlRenderingCompatibilityVersion
更改为3.5
到4.0
。从
4.5
的controlRenderingCompatibilityVersion
元素中删除了clientIDMode
和pages
Google再次狂热地寻求解决方案,但没有成功。
使用Googled来确定在ASP.Net页面生命周期中何时设置了
web.config
属性(也没有成功)。我更改什么似乎并不重要。从设置器调用时,
ClientID
吸气剂将返回ViewStateControlPrefix
,从getter调用时,其他内容(取决于我所做的更改)将返回。有谁知道为什么这种行为与ASP.Net 2.0如此根本不同?还是如何改回去?
最佳答案
我想出的解决方法是重写ViewStateControlPrefix
getter以返回独立于ClientIDMode
设置的唯一值:
Private ReadOnly Property ViewStateControlPrefix() As String
Get
Dim parts As String() = Me.ClientID.Split("_")
Dim id As String = Me.ClientID 'Default to ClientID
Dim prefix As String = String.Empty
If parts.Length > 0 Then
'By using Me.ClientID, the last element of the array will always be
'the ID specified in the markup, regardless of ClientIDMode settings.
id = parts(parts.GetUpperBound(0))
End If
prefix = "Maggie:ValidatedTextBox:" & id & ":"
Return prefix
End Get
End Property
这将返回一个一致的值用作
ViewState
包中的键,无论何时调用此getter以及无论ClientIDMode
设置如何(无论在何处设置)。我会暂时保留这个答案
任何人都可以提出更好的解决方案
或者任何人都可以在帖子中解释我的任何原始问题:
为什么这在ASP.Net 2.0中有效,但现在不行?
是什么原因造成的?
我该如何解决?
在页面生命周期中何时以声明方式设置属性时调用属性设置器?
为什么这种行为与ASP.Net 2.0如此根本不同?
如何改回来?
关于asp.net - 为什么PreInit上的ClientID与Init或PreRender中的ClientID不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23087047/