ASP.NET 表单数据助手类





0/5 (0投票)
一个实用程序类,允许您将表单数据作为集合处理。
引言
.NET WebForms 开发人员最常处理的事情之一就是表单数据。将表单数据视为强类型可编辑集合可以大大改善表单数据的处理。 我创建了一个包装类,可以处理开发人员遇到的许多常见情况。 它允许将表单数据读取为输入以进行处理,并且/或者允许创建一个集合,该集合随后可用于在页面之间作为 POST 或 GET 数据传递数据。
以下是此库提供的主要功能。 当将集合数据导出到查询字符串时,它会为您对值数据进行 URL 编码;当将集合数据导出到要发布的表单中的隐藏变量时,它会对该数据进行 HTML 编码。 一个非常有用的功能是它提供了使用线程本地存储 (TLS) 的能力,以允许 Server.Transfer
API 调用导致数据在执行已转移到的页面中可用。 ASP.NET 模型只允许将现有的只读表单数据集合转发到转移的页面。
我创建了一个测试页面,允许您尝试几乎所有的导入和导出选项。 它允许您使用 GET 或 POST 方法提交源页面。 您始终可以选择使用 GET 方法进行 Response.Redirect
,或者使用 TLS 在页面之间存储数据进行 Server.Transfer
。 提供的另一个示例页面展示了如何获取在页面初始加载时传递到页面的数据,并将此数据存储为表单上的一组隐藏字段。
代码非常简单,但它是我使用的最有用的实用程序类之一。 使用 BuildFromGetRequest
、BuildFromPostRequest
和 BuildFromTls
方法导入数据。 也可以添加或删除键值对。 如果需要,可以使用 ToPostForm
、ToQueryString
和 ToTls
方法导出数据。
唯一有点深奥的代码是 System.Threading
中的 TLS 相关 API 调用。 首先,我们使用我们选择的名称,通过 Thread.AllocateNamedDataSlot
调用分配一个命名数据槽。 由于 ASP.NET 将为每个请求使用一个线程,因此我们可以安全地使用常量名称(除非专门使用异步页面模型)。 其次,我们使用 Thread.GetNamedDataSlot
获取对数据槽的引用。 最后,我们调用 Thread.SetData
API 将集合分配给数据槽。
检索 TLS 数据在本质上与设置 TLS 数据类似。 首先,如上所述检索对数据槽的引用。 随后,Thread.GetData
API 将检索该集合。 重要的是要记住使用 Thread.FreeNamedDataSlot
调用来释放正在使用的内存。
该类中有一些使用注意事项值得注意。 TLS 数据仅在处理单个请求时有用。 将响应返回给用户后,该线程将返回到线程池。 另一个值得注意的情况是,当一个页面有多个具有相同名称的文本字段时。 这些字段以用于 name 属性的一系列逗号分隔值提供。 例如,如果字段的值为 val1 和 val2,则结果将为“val1, val2”。 支持这种用法充其量是困难的。 我忽略了这种情况,并将结果视为单个值(如上所述)。 另一个设计选择是,如果您添加一个其键已存在于集合中的条目,则旧条目将被删除。 另一个做出的设计选择是始终删除键值为 *submit* 的条目(如果存在),因为这通常用作 Submit 按钮字段的名称。
Imports System.Collections.Specialized
Imports System.Text
Imports System.Threading
Public Class HttpFormUtil
Inherits System.Object
'allocating here to prevent misuse with null reference
Private fc As New NameValueCollection
Private sActionPage As String
Public Sub Add(ByVal sKeyName As String, ByVal sValString As String)
If Not fc.Item(sKeyName) Is Nothing Then
fc.Remove(sKeyName)
End If
fc.Add(sKeyName, sValString)
End Sub
Public Function Count() As Integer
Return fc.Count()
End Function
Public Sub Remove(ByVal sKeyName As String)
If Not fc.Item(sKeyName) Is Nothing Then
fc.Remove(sKeyName)
End If
End Sub
Public Function Lookup(ByVal sKeyName As String) As String
Dim sValueString As String
sValueString = fc.Item(sKeyName)
If sValueString Is Nothing Then
sValueString = String.Empty
End If
Return sValueString
End Function
Public Sub BuildFromPostRequest()
fc = New NameValueCollection(System.Web.HttpContext.Current.Request.Form)
End Sub
Public Sub BuildFromGetRequest()
fc = New NameValueCollection(System.Web.HttpContext.Current.Request.QueryString)
End Sub
Public Sub BuildFromTls()
Dim dataSlot As LocalDataStoreSlot
Dim retrievedData As Object
dataSlot = Thread.GetNamedDataSlot("passedData")
retrievedData = Thread.GetData(dataSlot)
Try
If retrievedData Is Nothing Then
'do nothing
Else
fc = CType(retrievedData, NameValueCollection)
End If
Catch ex As Exception
'treat collection has having nothing in it.
fc = New NameValueCollection
Finally
Try
Thread.FreeNamedDataSlot("passedData")
Catch ex As Exception
End Try
End Try
End Sub
Public Function ToPostForm() As String
Dim iCurrElem As Integer
Dim sb As New StringBuilder
Remove("submit")
For iCurrElem = 0 To fc.Count - 1
sb.Append("<input type=""hidden"" name =""")
sb.Append( System.Web.HttpContext.Current.Server.HtmlEncode(fc.Keys(iCurrElem)))
sb.Append(""" value=""")
sb.Append( System.Web.HttpContext.Current.Server.HtmlEncode(fc.Get(iCurrElem)))
sb.AppendLine(""" />")
Next
Return sb.ToString()
End Function
Public Function ToQueryString() As String
Dim sb As New StringBuilder
Dim oPageContext As System.Web.HttpContext
Dim iCurrElem As Integer
oPageContext = System.Web.HttpContext.Current
Remove("submit")
For iCurrElem = 0 To fc.Count - 1
If iCurrElem = 0 Then
sb.Append("?")
Else
sb.Append("&")
End If
sb.Append(oPageContext.Server.UrlEncode(fc.Keys(iCurrElem)))
sb.Append("=")
sb.Append(oPageContext.Server.UrlEncode(fc.Get(iCurrElem)))
Next
Return sb.ToString()
End Function
Public Sub ToTls()
Dim dataSlot As LocalDataStoreSlot
Remove("submit")
Thread.AllocateNamedDataSlot("passedData")
dataSlot = Thread.GetNamedDataSlot("passedData")
Thread.SetData(dataSlot, fc)
End Sub
Public Function ToDictionary() As Dictionary(Of String, String)
Dim oList As New Dictionary(Of String, String)
For Each currEntry As String In fc.AllKeys
oList.Add(currEntry, fc(currEntry))
Next
Return oList
End Function
End Class