65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET 表单数据助手类

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2010年4月1日

CPOL

3分钟阅读

viewsIcon

29401

downloadIcon

176

一个实用程序类,允许您将表单数据作为集合处理。

引言

.NET WebForms 开发人员最常处理的事情之一就是表单数据。将表单数据视为强类型可编辑集合可以大大改善表单数据的处理。 我创建了一个包装类,可以处理开发人员遇到的许多常见情况。 它允许将表单数据读取为输入以进行处理,并且/或者允许创建一个集合,该集合随后可用于在页面之间作为 POST 或 GET 数据传递数据。

以下是此库提供的主要功能。 当将集合数据导出到查询字符串时,它会为您对值数据进行 URL 编码;当将集合数据导出到要发布的表单中的隐藏变量时,它会对该数据进行 HTML 编码。 一个非常有用的功能是它提供了使用线程本地存储 (TLS) 的能力,以允许 Server.Transfer API 调用导致数据在执行已转移到的页面中可用。 ASP.NET 模型只允许将现有的只读表单数据集合转发到转移的页面。

我创建了一个测试页面,允许您尝试几乎所有的导入和导出选项。 它允许您使用 GET 或 POST 方法提交源页面。 您始终可以选择使用 GET 方法进行 Response.Redirect,或者使用 TLS 在页面之间存储数据进行 Server.Transfer。 提供的另一个示例页面展示了如何获取在页面初始加载时传递到页面的数据,并将此数据存储为表单上的一组隐藏字段。

代码非常简单,但它是我使用的最有用的实用程序类之一。 使用 BuildFromGetRequestBuildFromPostRequestBuildFromTls 方法导入数据。 也可以添加或删除键值对。 如果需要,可以使用 ToPostFormToQueryStringToTls 方法导出数据。

唯一有点深奥的代码是 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
© . All rights reserved.