【问题标题】:Serializing an ASP.NET web form序列化 ASP.NET Web 表单
【发布时间】:2009-08-03 04:18:44
【问题描述】:

是否可以序列化 ASP.NET Web 表单,包括用户输入的所有数据?我想让用户能够保存半完成的表单,并希望我可以通过序列化来实现这一点。任何简单的例子都将不胜感激。

编辑: 我想避免必须为“不完整”表单提供单独的数据层,以反映已完成表单的层。我不想将不完整的表单与完整的表单一起存储,因为它们可能无法通过我的数据库约束。

【问题讨论】:

  • 为什么这被否决了?
  • 您不想为不完整的表格单独存储数据,也不希望将它们与完整的表格一起存储。那么你想如何以及在哪里存储它们?
  • 为清晰起见进行了编辑。对不起卢克。

标签: asp.net serialization


【解决方案1】:

迈克,

您不必序列化整个 asp.net 表单来捕获半填充数据。最好捕获在卸载(或whaterver触发器)字段中输入的数据并将其保存在数据库中。并且您只需在再次加载页面时将数据重新分配给控件。这比序列化整个页面要好...

编辑::

我理解你在这篇文章中的几个cmet,你的要求是

  • 保留半填充数据而不是完整数据
  • 而且你的数据非常敏感
  • 你想存储页面的序列化形式并渲染它 需要的时候直接...

但你认为在这种情况下推荐序列化,它会解决你所有的问题..不..

考虑以下事实

  1. 如果您正在序列化整个 形式,你最终可能会存储数据 那甚至不需要。 (如果你的 表单包含 15 个文本框和用户 只填写了 2 个条目。然后 使用持久化整体 表单对象)。
  2. 而且你传输的数据量会更高 (增加数据包大小,慢 传输速率)。
  3. 以及您对页面的控制(从序列化呈现 对象)较少。考虑如果你 想显示一些通知 序列化形式..可能是 肯定有办法做到这一点..但我 知道事情没那么简单..

考虑这里有经验的 ppl 给出的所有事实,并自己做一些分析,然后选择最好的方法.. 一切顺利

编辑

我刚刚遇到JQuery AutoSave 插件.. 它的作用与我上面的建议相同,但方式非常简单....(在指定的某个时间间隔内运行并保存未保存的内容。你可以轻松地调整它以满足您的需求)看看..

【讨论】:

  • 似乎是一个可行的选择。同意到这里为止,除非有人提出更好的答案。
  • 我想探索序列化的选项。这就是我的问题的具体内容。
【解决方案2】:

您无法真正避免为不完整的表格设置单独的存储位置。您需要将它们保存在某个地方,并且不能将它们与完整的放在一起,因为显然您对基础数据库表有一些数据库约束并且您希望保留它们。我建议@Ramesh 将表单的数据封装在一个类中。

public class FormData
{
  public int IntField { get;set;}
  public string StringField {get;set;}
  public decimal DecimalField {get;set;}
  public decimal DateTimeField {get;set;}
}

将 FormData 对象绑定到您的 UI 控件。当用户想要保存不完整的数据时,将 FormData 对象序列化为 xml,因为您真的想在这里使用序列化。

XmlSerializer serializer = new XmlSerializer(typeof(FormData));
StringWriter writer = new StringWriter(new StringBuilder());
serializer.Serialize(writer,formDataObject);
string serializedFormDataObject = writer.GetStringBuilder().ToString();

然后您可以将 serializedFormDataObject 保存到单独的表中。当用户加载表单时,您可以检查表格以查看表单是否不完整。如果是,您可以反序列化表单加载事件中的数据,例如:

string serializedFormDataObject = GetFromDatabase(formId,userId); //you get the idea I guess
StringReader reader = new StringReader(serializedFormDataObject);
XmlSerializer serializer = new XmlSerializer(typeof(FormData));
formDataObject = serializer.Deserialize(reader) as FormData;

然后您可以将 formData 绑定到您的控件。表格完成后,您可以删除不完整的表格条目并将已完成的表格保存到已完成表格的表格中。

【讨论】:

    【解决方案3】:

    您说您想序列化处于部分完成状态的表单。从您的问题和各种 cmets 听起来您正在尝试使用序列化作为避免使用单独存储的一种方式。然而,这不是序列化的意义所在。

    序列化是将某些对象(通常在内存中)转换为已知格式(例如,XML 文件),以便它可以通过网络传输或保存在数据库中。序列化并不意味着您对序列化形式的对象做什么,只是它是一种序列化形式。

    对不起,如果这是千篇一律,但我认为它已经很清楚了:http://en.wikipedia.org/wiki/Serialization

    编辑:也许你已经明白我上面所说的 - 例如,你是否希望将序列化的表单放入会话中?

    编辑 2:好的,我想我明白了。您可以将序列化的表单保存到数据库,但您不希望将单个表单输入保存到数据库 - 就像保存已完成的表单一样。因此,您正在寻找一种方法来将不完整的表单与已完成的表单以不同方式保留下来。 为此,我会在你的数据库中为这个确切的东西创建一个新表。它可以有一个数据列(存储序列化数据)或与您的普通(完整表格)表相同的列,只是没有您提到的约束。这有意义吗?

    【讨论】:

    • 我了解序列化的用途。我正在寻找一种简单的方法来获取我的页面状态,将其包裹在一个球中,并将其保存到数据库中,并假设它永远不会因任何其他原因而被使用,即将自身恢复到页面一点。我认为序列化对于这样的事情来说是一个很好的、简单的选择。我愿意接受其他更简单的想法。
    【解决方案4】:

    不幸的是,Viewstate 是不够的;您还需要考虑发布数据和查询参数,以便能够准确地保存和恢复页面状态。 Here 是一篇关于所涉及问题的非常全面的文章,其中包括工作代码。

    【讨论】:

      【解决方案5】:

      考虑为google gears 开发,它允许用户离线工作。基本上,这意味着表单数据会在本地保存,直到提交到服务器。虽然谷歌本身对赋予微软开发者权力不感兴趣,但开发者社区中有一些人对此感兴趣。这是一个tutorial,关于让 ASP.NET 应用程序利用 google gears。

      【讨论】:

      • 此表单包含敏感数据,我不想公开 cookie 被留在其他人可以获取的地方的安全风险。我还想让系统管理员能够在同一页面中查看不完整的数据。
      【解决方案6】:

      序列化对您没有帮助,除非您乐于将序列化数据存储在某处,可能作为 db 表中的 xml 片段或文件 (yuk)。 这对我来说似乎是错误的方法,但如果你真的想使用序列化,有很多选择。我能想到的最简单的方法是将 request.form 集合序列化为 xml,方法是使用 xmlserializer 或通过循环它并自己构建一个 xml 字符串。

      我的建议是……

      如果您乐于使用 javascript,为什么不在客户端尝试这样做呢?

      例如,您可以通过单击“保存”按钮从表单中收集数据并将其保存在 cookie 中。

      当用户回来时,您可以检查 cookie 并重新加载 cookie 中的数据。

      您只能在表单完成后将表单数据发布回服务器。这将避免您的数据库约束问题。

      试试这个:http://www.bigresource.com/Tutorial/PHP/Saving_Form_Data_Into_A_Cookie.htm

      更新

      以下cmets: 好的,如果你想采用序列化表单的方法,你需要将数据存储在某个地方。

      基于我认为你想做的:

      如果您的表单数据适合一个表,我建议您有一个没有 db 约束的“副本表”,并将其命名为 formDataHolding(您的原始数据是 fomrData)。您将从该表中读取和写入,并且仅在表单数据完成时迁移数据,我使用迁移一词意味着数据离开保留表并以某种方式进入完整表。 如果您的表单包含适合多个表的数据,那么序列化可能是正确的答案,但要准备好将这些数据存储在某个地方,以一种可能不适合您现有数据模型的方式,或者准备创建“副本”没有约束的表,用于存储数据的所有表。

      序列化数据并不一定意味着您正在创建 xml,但我假设这就是您想要的。我会采取从 Request.Form 取回 NameValueCollection 然后序列化它的方法。如果您使用网络表单,您可能希望这样做。

      这里是序列化 NameValueCollection 的人的 url: http://nayyeri.net/blog/Serialize-NameValueCollection/

      【讨论】:

      • 我不想将半成品数据存储在 cookie 中。此表单包含敏感数据,我不想公开 cookie 被留在其他人可以获取的地方的安全风险。我还想让系统管理员能够在同一页面中查看不完整的数据。
      • 好的,但是从你的回复中你说你“我不想要 xyz”。在我的回复中,我提到如果您真的想“序列化”表单,您可以通过多种方式将其存储在服务器上,例如 xml 片段。我提到,或者您可以在 cookie 中执行此操作,如果您有安全问题,为什么不使用公钥/私钥加密来加密 cookie 中的数据以使其安全。看起来你已经得到了几个原始问题的答案,现在又得到了其他几个问题的答案!
      【解决方案7】:

      我还没有经历过这么大的答案,但对我来说似乎只需要持久化视图状态并使用持久化的视图状态,而不是在需要半输入表单时创建新的视图状态。

      不需要任何额外的逻辑,viewstate就是这样设计的。

      任何回发在技术上都是新的页面渲染,但使用来自视图状态的值,并且 op 只是试图做同样的事情,但不是回发而是其他时间,但需要同样的事情

      【讨论】:

      • 如何将视图状态保存到数据库中?
      • 当您进行回发时,页面的 ViewState 属性包含有关用户输入的所有信息。可以序列化,并将给你一个字符串保存到数据库中
      • 您能否显示代码 sn-p 或参考有关如何序列化视图状态以及如何反序列化和恢复它的链接?
      【解决方案8】:

      我对许多表单(主要是多页,但同样适用于单页)采取的一种方法是让每个表单页面都继承自一个公共基类,该基类具有许多属性。其中一个属性是 FormData,可以定义为:

      public FormData FormDataStore
      {
          get
          {
              if (Session["FormDataStore"] == null)
              {
                  Session["FormDataStore"] = new FormData();
              }
      
              return (FormData)Session["FormDataStore"];
          }
          set
          {
              Session["FormDataStore"] = value;
          }
      }
      

      FormData 是一个包含所有属性(表单字段)的类,例如

      public class FormData
      {
        public string name {get; set;}
        public string email {get; set;}
      }
      

      每个表单页面都有一个“LoadData”和“SaveData”函数,分别负责用来自FormDataObject对象的数据填充表单并将数据保存到FormDataObject对象。

      基类还包含 2 个方法,SaveDraft 和 LoadDraft。 SaveDraft 将 FormDataObject 序列化为 Xml 并保存到 DB 表(可以简单到 2 列,ID 和 XmlData):

                  StringWriter sw_wf = new StringWriter();
                  XmlSerializer xs_wf = new XmlSerializer(FormData.GetType(), new System.Type[] { typeof(additionalObjects)});
                  xs_wf.Serialize(sw_wf, FormDataObject);
                  string WebFormData = sw_wf.ToString();
                  sw_wf.Close();
      
                  //write WebFormData to database
      

      LoadDraft 只是将 Xml 加载并反序列化回一个对象,表单将自动拾取并填充字段。 LoadDraft 的工作方式取决于 iste 的性质和数据的敏感性——例如如果表单是由登录用户填写的,或者它可能是匿名的,并且是存储在 DB 和 cookie 中的唯一 ID。

      我构建了许多提交到 1 个或多个 Web 服务的网站,当从 WSDL 文件构建存根并将其用作 FormData 类时,这种方法非常有效。

      【讨论】:

        【解决方案9】:

        我过去使用的一种方法是从表单对象中捕获 POST 值,并使用可以使用 soapformatter 序列化的 momemto 类存储该值。当需要恢复时,我所做的只是 GET 到带有查询字符串参数的 HttpHandler 类,该类解析预期的 id 并反序列化状态以进行恢复,从而呈现隐藏字段以模拟用户从原始页面发布帖子。这是两个类。

        请注意,您正在捕获 FORM 的状态,因此当您恢复表单时,您会将状态恢复到您要求恢复的状态,如果您发现问题,您可能需要处理此问题。

        ''' <summary>
        ''' This class encapsulates the form state
        ''' </summary>
        <Serializable()> _
        Public NotInheritable Class FormState
        
            Private _path As String
            Private _form As NameValueCollection
        
            ''' <summary>
            ''' Constructor.
            ''' </summary>
            ''' <param name="path">The path of the original form post request.</param>
            ''' <param name="form">The form to save.</param>
            Public Sub New(ByVal path As String, ByVal form As NameValueCollection)
                _path = path
                _form = form
            End Sub
        
        
            ''' <summary>
            ''' Serializer Ctor.
            ''' </summary>
            ''' <remarks></remarks>
            Sub New()
            End Sub
        
        
            ''' <summary>
            ''' The path of the original form post request.
            ''' </summary>
            Public ReadOnly Property Path() As String
                Get
                    Return _path
                End Get
            End Property
        
            ''' <summary>
            ''' The saved form.
            ''' </summary>
            Public ReadOnly Property Form() As NameValueCollection
                Get
                    Return _form
                End Get
            End Property
        
        End Class
        
            ''' <summary>
            ''' This http handler will render a small page that will reconstruct the form as it was before session timeout, using hidden fields.
            ''' The page will submit itself upon loading, meaning that the user will barely see it.
            ''' </summary>
            Public Class FormStateRestoreHandler
                Implements IHttpHandler, IRequiresSessionState
        
                Private _state As FormState
                Private _dealGuid As Guid
        
                ''' <summary>
                ''' The form state.
                ''' </summary>
                Protected ReadOnly Property FormState() As FormState
                    Get
                        Return _state
                    End Get
                End Property
        
                ''' <summary>
                ''' Gets a value indicating whether another request can use this IHttpHandler instance.
                ''' </summary>
                Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
                    Get
                        Return False
                    End Get
                End Property
        
        
                ''' <summary>
                ''' Processes the web request - this is where the page is rendered.
                ''' </summary>
                ''' <param name="context"></param>
                Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
                    Dim Id = context.Request.QueryString("id")
        
                    If Id Is Nothing Then Return
        
                    _state = LoadFormState(Id)
        
                    Using writer As HtmlTextWriter = CreateHtmlTextWriter(context.Response.Output, context.Request.Browser)
                    Me.Render(writer)
                End Using
        
           End Sub
        
           ''' <summary>
           ''' Loads the specified FormState by id
           ''' </summary>
           ''' <param name="id">The unique id of the saved form state.</param>
           ''' <returns></returns>
           Private Shared Function LoadFormState(ByVal id As Guid) As FormState
               Dim _storageProvider = ConfigurationFacade.GetUnityContainer.Resolve(Of IDealProvider)()
               Dim result As FormState = Nothing
               Dim bytes = _storageProvider.LoadUserState(id)
        
               Dim soapFormatter = New SoapFormatter
               Using ms = New IO.MemoryStream(bytes)
                   result = soapFormatter.Deserialize(ms)
                   ms.Close()
               End Using
        
        
               Return result
           End Function
        
        
        
           ''' <summary>
           ''' Renders a small page that will resubmit the saved form
           ''' </summary>
           ''' <param name="writer"></param>
           Protected Overridable Sub Render(ByVal writer As HtmlTextWriter)
               writer.RenderBeginTag(HtmlTextWriterTag.Html)
               writer.RenderBeginTag(HtmlTextWriterTag.Head)
               writer.RenderBeginTag(HtmlTextWriterTag.Title)
               writer.Write("Restoring form")
               writer.RenderEndTag()
               ' TITLE
               writer.RenderEndTag()
               ' HEAD
               writer.AddAttribute("onload", "document.forms[0].submit();")
               writer.RenderBeginTag(HtmlTextWriterTag.Body)
        
               writer.AddAttribute("method", "post")
               writer.AddAttribute("action", Me.FormState.Path)
        
               writer.RenderBeginTag(HtmlTextWriterTag.Form)
        
               Dim form As NameValueCollection = Me.FormState.Form
               For Each name As String In form.Keys
                   RenderHiddenField(writer, name, form(name))
               Next
        
               writer.AddAttribute(HtmlTextWriterAttribute.Align, "center")
               writer.RenderBeginTag(HtmlTextWriterTag.P)
               writer.Write("You should be redirected in a moment.")
               writer.WriteFullBeginTag("br")
               writer.Write("If nothing happens, please click ")
               RenderSubmitButton(writer, "Submit")
               writer.RenderEndTag()
               ' P
               writer.RenderEndTag()
               ' FORM
               writer.RenderEndTag()
               ' BODY
               writer.RenderEndTag()
               ' HTML
           End Sub
        
           ''' <summary>
           ''' Renders a hidden field.
           ''' </summary>
           ''' <param name="writer">The writer to use.</param>
           ''' <param name="name">The name of the hidden field.</param>
           ''' <param name="value">The value of the hidden field.</param>
           Protected Shared Sub RenderHiddenField(ByVal writer As HtmlTextWriter, ByVal name As String, ByVal value As String)
               writer.AddAttribute(HtmlTextWriterAttribute.Type, "hidden")
               writer.AddAttribute(HtmlTextWriterAttribute.Name, name)
               writer.AddAttribute(HtmlTextWriterAttribute.Value, value)
               writer.RenderBeginTag(HtmlTextWriterTag.Input)
               writer.RenderEndTag()
               ' INPUT
           End Sub
        
           ''' <summary>
           ''' Renders a submit button.
           ''' </summary>
           ''' <param name="writer">The writer to use.</param>
           ''' <param name="text">The text of the button.</param>
           Protected Shared Sub RenderSubmitButton(ByVal writer As HtmlTextWriter, ByVal text As String)
               writer.AddAttribute(HtmlTextWriterAttribute.Type, "submit")
               writer.AddAttribute(HtmlTextWriterAttribute.Value, text)
               writer.RenderBeginTag(HtmlTextWriterTag.Input)
               writer.RenderEndTag()
               ' INPUT
           End Sub
        
           ''' <summary>
           ''' Gets a HtmlTextWriter to write output to, based on a TextWriter.
           ''' </summary>
           ''' <param name="writer">The Text writer holding the output stream.</param>
           ''' <param name="browser">The browser capabilities of the client browser.</param>
           ''' <returns></returns>
           Protected Shared Function CreateHtmlTextWriter(ByVal writer As TextWriter, ByVal browser As HttpCapabilitiesBase) As HtmlTextWriter
               If browser Is Nothing Then
                   Return New HtmlTextWriter(writer)
               End If
               Return browser.CreateHtmlTextWriter(writer)
           End Function
          End Class
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-11
          相关资源
          最近更新 更多