2009-08-03 21 views
2

Ist es möglich, ein ASP.NET-Webformular zu serialisieren, einschließlich aller Daten, die ein Benutzer eingegeben hat? Ich möchte den Benutzern die Möglichkeit geben, ein halb ausgefülltes Formular zu speichern und hoffte, dass ich dies mit der Serialisierung erreichen könnte. Alle einfachen Beispiele würden sehr geschätzt werden.Serialisierung eines ASP.NET-Webformulars

Edit: Ich möchte vermeiden, separate Datenschicht für die "unvollständige" Formulare haben, die die Ebenen für die ausgefüllten Formulare spiegelt. Ich möchte die unvollständigen Formulare nicht mit den vollständigen Formularen speichern, da sie meine DB-Einschränkungen möglicherweise nicht bestehen.

+1

warum wurde das abgelehnt? – Jason

+0

Sie möchten keinen separaten Datenspeicher für die unvollständigen Formulare, und Sie möchten sie nicht mit den vollständigen Formularen speichern. Wie und wo möchten Sie sie dann speichern? – LukeH

+0

Editiert für Klarheit. Entschuldigung Luke. –

Antwort

4

Sie können einen separaten Speicherort für unvollständige Formulare nicht wirklich vermeiden. Sie müssen sie an einem anderen Ort aufbewahren, und Sie können sie nicht mit den vollständigen hinzufügen, da Sie anscheinend einige Datenbankeinschränkungen für die zugrunde liegenden Datenbanktabelle (n) haben und diese beibehalten möchten. Ich würde vorschlagen, da @Ramesh die Daten Ihres Formulars in einer Klasse eingekapselt hat.

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

Binden Sie das FormData-Objekt an Ihre UI-Steuerelemente. Wenn der Benutzer unvollständige Daten speichern möchte, serialisieren Sie das FormData-Objekt in xml, da Sie die Serialisierung hier wirklich verwenden möchten.

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

Sie können serializedFormDataObject dann in einer separaten Tabelle speichern. Wenn der Benutzer das Formular lädt, können Sie in der Tabelle überprüfen, ob das Formular unvollständig ist. Wenn ja, können Sie die Daten auf Formularladeereignis zum Beispiel deserialisieren:

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; 

können Sie dann binden Formdata auf Ihre Kontrollen. Wenn das Formular abgeschlossen ist, können Sie den unvollständigen Formulareintrag entfernen und das ausgefüllte Formular in der Tabelle für die ausgefüllten Formulare speichern.

8

Mike,

Sie brauchen nicht die ganze asp.net Form zu serialisiert haben die Hälfte gefüllt Daten zu erfassen. Es ist besser, die Daten zu erfassen, die in die Felder beim Entladen (oder bei einem Trigger) eingegeben werden, und speichert sie in der Datenbank. und u die Daten einfach zu Kontrollen neu zuweisen, während die Seite erneut geladen .. das ist besser als die gesamte Seite Serialisierung ...

EDIT ::

i wie pro ur mehrere Kommentare in diesem verstehen Post, ist ur Anforderung an

  • die Hälfte gefüllt Daten nicht zusammen mit vollständigen Daten bestehen
  • und ur Daten ist sehr empfindlich
  • und u wollen die serialisierte Form pa speichern ge und machen es direkt whenener benötigt ...

aber denken die Serialisierung u in diesem Zusammenhang recommented ist, und es wird alle ur Probleme .. NO ..

betrachten Sie die folgenden Tatsachen lösen

  1. Wenn Sie das gesamte Formular serialisieren, können Sie am Ende die Daten speichern das ist nicht einmal erforderlich. (Wenn Ihr Formular 15 Textfelder enthält und der Benutzer gerade nur 2 Einträge gefüllt hat, dann verwendet die Verwendung des gesamten Formularobjekts ).
  2. Und die Anzahl der zu übertragenden Daten ist höher (erhöht die Paketgröße, langsam Übertragungsraten).
  3. Und Ihre Kontrolle über die Seite (von serialisierten Objekt gerendert werden) ist weniger. Sehen Sie, wenn Sie auf die serialisierte Form eine Meldung zeigen wollte .. ther irgendeine Weise es sicher sein könnte, zu tun .. aber ich weiß, seine nicht so einfach ..

alle Fakten betrachten gegeben von hier pPL, die Erfahrung in diesem bekam und tun urself einige Analysen und wählen den besten Ansatz .. alles Gute

EDIT

ich kam gerade über die JQuery AutoSave Plugin .. und seine das gleiche zu tun, was ich vorschlagen st über, aber in einer ziemlich einfachen Art .... (die in einem bestimmten Zeitintervall & läuft, den ungesicherten Inhalt speicherend. Sie können dies leicht anpassen, um Ihre Anforderungen zu erfüllen.

+0

Scheint eine praktikable Wahl zu sein. Einverstanden bis hierher, es sei denn, jemand hat eine bessere Antwort gefunden. –

+1

Ich möchte die Option der Serialisierung erkunden. Genau darum ging es in meiner Frage. –

1

Sie sagen, dass Sie das Formular in seinem unvollständigen Zustand serialisieren möchten. Aus Ihrer Frage und verschiedenen Kommentaren klingt es so, als würden Sie versuchen, die Serialisierung zu verwenden, um separate Speicher zu vermeiden. Aber darum geht es bei der Serialisierung nicht.

Das Serialisieren verwandelt ein Objekt, normalerweise im Speicher, in ein bekanntes Format (z. B. eine XML-Datei), sodass es über ein Netzwerk übertragen oder in einer Datenbank gespeichert werden kann. Serialisierung bedeutet nichts über das, was Sie tun mit einem Objekt in seiner serialisierten Form, nur dass es in eine serialisierte Form ist.

Sorry, wenn diese Cookie-Cutter ist, aber ich denke, es ist ziemlich klar gemacht hat: http://en.wikipedia.org/wiki/Serialization

Edit: vielleicht verstehen Sie, was ich sagte oben bereits - sind Sie auf der Suche nach zum Beispiel die serialisierte Form in die setzen Session?

Edit 2: Okay, ich denke, ich verstehe es. Sie können ein serialisiertes Formular in einer Datenbank speichern, aber Sie möchten lieber keine einzelnen Formulareingaben in einer Datenbank speichern - so, wie Sie ein ausgefülltes Formular speichern würden. Also, Sie suchen nach einer Möglichkeit, unvollständige Formulare anders von abgeschlossenen zu persistieren. Zu diesem Zweck würde ich eine neue Tabelle in Ihrer Datenbank für genau diese Sache erstellen. Es könnte eine einzelne Datenspalte (die die serialisierten Daten speichert) oder die gleichen Spalten wie Ihre normale Tabelle (abgeschlossenes Formular) haben, ohne die von Ihnen erwähnten Einschränkungen. Macht das Sinn?

+0

Ich verstehe, wofür Serialisierung ist. Ich bin auf der Suche nach einer einfachen Möglichkeit, den Zustand meiner Seite zu erfassen, sie in einen Ball zu verpacken und in der Datenbank zu speichern, mit der Annahme, dass sie niemals aus irgendeinem anderen Grund verwendet wird, um sich auf der Seite wiederherzustellen Irgendwann. Ich dachte Serialisierung wäre eine gute, einfache Wahl für so etwas. Ich bin offen für andere einfachere Ideen. –

0

Die Serialisierung wird Ihnen nicht helfen, es sei denn, Sie sind froh, die serilisierten Daten irgendwo zu speichern, vielleicht als XML-Fragment in einer db-Tabelle oder als Datei (yuk). Es scheint die falsche Herangehensweise an mich, aber wenn Sie wirklich Serialisierung verwenden wollten, gibt es viele Möglichkeiten. Das einfachste, was ich mir vorstellen kann, wäre, die request.form-Sammlung in xml zu serialisieren, entweder indem Sie den xmlserializer verwenden oder indem Sie es durchschleifen und selbst eine XML-Zeichenkette erstellen.

Mein Vorschlag wäre, ...

Wenn Sie glücklich sind Javascript zu verwenden, warum nicht versuchen, und dies auf dem Client zu tun?

Sie könnten die Daten aus dem Formular zum Beispiel durch Klicken auf eine Schaltfläche "Speichern" sammeln und in einem Cookie speichern.

Wenn der Benutzer zurückkommt, können Sie nach dem Cookie suchen und die Daten aus dem Cookie erneut laden.

Sie würden die Formulardaten nur dann zurück auf den Server stellen, wenn das Formular vollständig ist. Dies würde das Problem mit DB-Beschränkungen vermeiden.

Versuchen Sie folgendes: http://www.bigresource.com/Tutorial/PHP/Saving_Form_Data_Into_A_Cookie.htm

UPDATE

folgende Anmerkungen: OK, wenn Sie den Ansatz von Serialisierung Ihre Form nehmen wollen Sie müssen irgendwo die Daten speichern.

Nach dem, was ich denke, was Sie tun mögen:

Wenn Ihre Formulardaten in einer einzigen Tabelle passen schlage ich würde, dass Sie ohne die db Einschränkungen einen ‚Replik Tisch‘ haben und es so etwas nennen formDataHolding (wo Ihr Original fomrData war). Sie würden lesen und schreiben von dieser Tabelle und nur die Daten migrieren, wenn die Formulardaten abgeschlossen sind, verwende ich das Wort migrieren, was bedeutet, dass Daten die Haltetisch verlässt und irgendwie in die vollständige Tabelle geht. Wenn Ihr Formular aus Daten besteht, die in mehrere Tabellen passen, dann ist die Serialisierung möglicherweise die richtige Antwort, aber seien Sie bereit, diese Daten so zu speichern, dass sie nicht mit Ihrem vorhandenen Datenmodell übereinstimmen oder bereit sind, Replikat-Tabellen 'ohne die Einschränkungen für alle Tabellen, die die Daten speichern.

Serialisierung der Daten bedeutet nicht notwendigerweise, dass Sie xml erstellen, aber ich nehme an, dass dies das ist, was Sie wollen. Ich würde den Ansatz nehmen, die NameValueCollection aus Request.Form zurückzuholen und sie dann zu serialisieren. Möglicherweise möchten Sie dies anders machen, wenn Sie Webformulare verwenden.

Hier ist eine URL für jemanden, der eine Namevaluecollection serialisiert hat: http://nayyeri.net/blog/Serialize-NameValueCollection/

+0

Ich möchte die halbfertigen Daten nicht in einem Cookie speichern. Dieses Formular enthält vertrauliche Daten und ich möchte nicht das Sicherheitsrisiko eines Cookies öffnen, das an einer anderen Stelle verfügbar ist. Ich möchte auch den Administratoren des Systems die Möglichkeit geben, die unvollständigen Daten auf derselben Seite zu sehen. –

+0

OK, aber von deinen Antworten sagst du "Ich will nicht xyz". In meiner Antwort erwähnte ich, wenn Sie das Formular wirklich "serialisieren" möchten, können Sie es auf dem Server in vielerlei Hinsicht speichern, ein Beispiel wäre als ein XML-Fragment. Ich erwähne, alternativ könnten Sie dies in einem Cookie tun, wenn Sie Bedenken haben, warum nicht öffentliche/private Schlüsselverschlüsselung verwenden, um die Daten im Cookie zu verschlüsseln, damit sie sicher sind. Sieht aus, Sie haben mehrere Antworten auf Ihre ursprünglichen Fragen und jetzt Antworten auf mehrere andere! – Lewis

0

Betrachten wir für google gears zu entwickeln, die der Benutzer offline arbeiten können. Dies bedeutet im Wesentlichen, dass die Formulardaten lokal gespeichert werden, bis sie an den Server übergeben werden. Während Google selbst nicht daran interessiert ist, Microsoft-Entwickler zu befähigen, gibt es diejenigen in der Entwickler-Community, die es sind. Hier ist ein tutorial auf eine ASP.NET-Anwendung, um Google-Getriebe zu nutzen.

+0

Dieses Formular enthält vertrauliche Daten und ich möchte nicht das Sicherheitsrisiko eines Cookies öffnen, das an einer anderen Stelle verfügbar ist. Ich möchte auch den Administratoren des Systems die Möglichkeit geben, die unvollständigen Daten auf derselben Seite zu sehen. –

+0

http://stackoverflow.com/questions/259461/method-to-serialize-objects-from-appserver-to-web-server-without-code-duplication/259572#259572 – Glenn

0

Ich habe diese großen Antworten nicht durchgegangen, aber für mich sieht es aus, als müsste man einfach viewstate persistieren und viewstate verwenden, anstatt neue zu erstellen, wenn die Hälfte der eingegebenen Form benötigt wird.

Keine zusätzliche Logik erforderlich, ViewState ist so konzipiert, dass er genau so verwendet werden kann.

Jede Post zurück ist technisch neue Seite machen, sondern nutzt Wert von Ansichtszustand und op ist genau das gleiche, was nicht nur mit Postbacks zu tun versuchen, aber ein andermal aber brauchen gleiche

+0

Wie behalte ich Viewstate zu einer Datenbank? –

+0

Wenn Sie Postback ausführen, enthält die ViewState-Eigenschaft der Seite alle Informationen, die jemals vom Benutzer eingegeben wurden. Das kann serialisiert werden und gibt Ihnen eine Zeichenkette zum Speichern in die Datenbank – mamu

+0

Können Sie ein Code-Snippet anzeigen oder einen Link darauf verweisen, wie man einen Viewstate serialisiert und wie man ihn entserialisiert und wiederherstellt? –

1

Viewstate ist leider nicht genug; Sie müssen Postdaten und Abfrageparameter berücksichtigen, um den Seitenstatus genau speichern und wiederherstellen zu können. Here ist ein sehr umfangreicher Artikel über die damit verbundenen Probleme und enthält auch Arbeitscode.

0

Ein Ansatz, den ich mit einer Anzahl von Formularen (hauptsächlich mehrseitig, aber für einzelne Seite) durchgeführt habe, ist, dass jede Formularseite von einer gemeinsamen Basisklasse erbt, die eine Reihe von Eigenschaften hat. Eine der Eigenschaften würde Formdata sein und könnte definiert werden als:

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

     return (FormData)Session["FormDataStore"]; 
    } 
    set 
    { 
     Session["FormDataStore"] = value; 
    } 
} 

Formdata ist eine Klasse, die alle Eigenschaften (Felder des Formulars) hält, z.B.

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

Jedes Formular enthält einen ‚Loaddata‘ und ‚Savedata‘ -Funktion, die jeweils zum Füllen der Form mit Daten aus dem FormDataObject Objekt und Speichern von Daten in dem FormDataObject Objekt verantwortlich ist.

Die Basisklasse enthält auch 2 Methoden, SaveDraft und LoadDraft. SaveDraft serialisiert FormDataObject zu Xml und speichert sie in einer DB-Tabelle (die als 2 Spalten kann so einfach sein, ID und 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 einfach die Xml lädt und deserialises zurück in ein Objekt, das die Formulare automatisch abholt up und bevölkern die Felder. Die Funktionsweise von LoadDraft hängt von der Art der Datei und der Empfindlichkeit der Daten ab - z. wenn das Formular von einem angemeldeten Benutzer ausgefüllt wird oder anonym und in der Datenbank und in einem Cookie gespeichert werden kann.

Ich erstelle viele Websites, die an 1 oder mehrere Webdienste senden, und dieser Ansatz funktioniert sehr gut, wenn ein Stub aus einer WSDL-Datei erstellt und als FormData-Klasse verwendet wird.

0

Ein Weg, der in der Vergangenheit verwendet wurde, besteht darin, die POST-Werte aus dem Form-Objekt zu erfassen und unter Verwendung einer Momemto-Klasse zu speichern, die mit dem Soap-Formatierer serialisiert werden kann. Wenn es erforderlich ist, um wiederherzustellen, alles, was ich tun wird GET auf eine HttpHandler-Klasse mit querystring Parameter, die die beabsichtigte ID analysiert und deserilizes den Zustand für die Wiederherstellung, die verdeckte Felder simuliert den Benutzer macht einen Beitrag von der ursprünglichen Seite. Hier sind die zwei Klassen.

HINWEIS, dass Sie den Status der FORM erfassen, also wenn Sie das Formular wiederherstellen, den Zustand in einem Zustand wiederherstellen, in dem Sie eine Wiederherstellung anfordern, müssen Sie möglicherweise behandeln, wenn Sie ein Problem finden.

''' <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