FormSubmitXml.cs
- //
- // This code is part of Document Solutions for PDF demos.
- // Copyright (c) MESCIUS inc. All rights reserved.
- //
- using System.Drawing;
- using System.IO;
- using System.Linq;
- using System.Xml;
- using System.Text;
- using System.Collections.Generic;
- using GrapeCity.Documents.Pdf;
- using GrapeCity.Documents.Pdf.AcroForms;
- using GrapeCity.Documents.Pdf.Actions;
- using GrapeCity.Documents.Pdf.Annotations;
- using GrapeCity.Documents.Text;
-
- namespace DsPdfWeb.Demos
- {
- // Note that the FormDataSubmit sample shows a better and easier solution for submitting form data.
- //
- // This sample creates an AcroForm PDF that can be submitted to the server.
- // It relies on the server to put the submitted data into an XML,
- // import that XML into a PDF containing a similar form,
- // and send the form with loaded data back to the client.
- // Note that the produced PDF with filled form fields
- // is shown in the client browser's default PDF viewer.
- // The code is similar to FormSubmit.
- public class FormSubmitXml
- {
- public int CreatePDF(Stream stream)
- {
- var doc = new GcPdfDocument();
- var page = doc.NewPage();
-
- var rc = Common.Util.AddNote("Fill the fields in the form and click 'Submit' to send it back to the server. " +
- "The sample server will put the submitted data into an XML, feed that XML" +
- "to a PDF with a different but compatible form, and send the resulting form" +
- "filled with the submitted data back to your browser." +
- "Note that the form with the submitted data is opened in the browser's default PDF viewer," +
- "and does not have the 'Submit' and 'Reset' buttons.", page);
-
- var g = page.Graphics;
- var tf = new TextFormat() { Font = StandardFonts.Times, FontSize = 14 };
- var ip = new PointF(72, rc.Bottom + 36);
- float fldOffset = 72 * 2 + 46;
- float fldHeight = tf.FontSize * 1.2f;
- float dY = 32;
-
- // Text field:
- g.DrawString("First name:", tf, ip);
- var fldFirstName = new TextField() { Name = "FirstName", Value = "John" };
- fldFirstName.Widget.Page = page;
- fldFirstName.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight);
- fldFirstName.Widget.DefaultAppearance.Font = tf.Font;
- fldFirstName.Widget.DefaultAppearance.FontSize = tf.FontSize;
- doc.AcroForm.Fields.Add(fldFirstName);
- ip.Y += dY;
-
- // Text field:
- g.DrawString("Last name:", tf, ip);
- var fldLastName = new TextField() { Name = "LastName", Value = "Smith" };
- fldLastName.Widget.Page = page;
- fldLastName.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight);
- fldLastName.Widget.DefaultAppearance.Font = tf.Font;
- fldLastName.Widget.DefaultAppearance.FontSize = tf.FontSize;
- doc.AcroForm.Fields.Add(fldLastName);
- ip.Y += dY;
-
- // Checkbox:
- g.DrawString("Subscribe to Mailing List:", tf, ip);
- var fldCheckbox = new CheckBoxField() { Name = "Subscribe", Checked = true };
- fldCheckbox.Widget.Page = page;
- fldCheckbox.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, fldHeight, fldHeight);
- doc.AcroForm.Fields.Add(fldCheckbox);
- ip.Y += dY;
-
- // Multiline TextBox:
- g.DrawString("Additional information:", tf, ip);
- var fldAdditionalInfo = new TextField() { Name = "AdditionalInfo", Multiline = true };
- fldAdditionalInfo.Widget.Page = page;
- fldAdditionalInfo.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight * 2);
- fldAdditionalInfo.Widget.DefaultAppearance.Font = tf.Font;
- fldAdditionalInfo.Widget.DefaultAppearance.FontSize = tf.FontSize;
- doc.AcroForm.Fields.Add(fldAdditionalInfo);
- ip.Y += dY * 2;
-
- // Submit form button:
- var btnSubmit = new PushButtonField();
- btnSubmit.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72, fldHeight);
- btnSubmit.Widget.ButtonAppearance.Caption = "Submit";
- btnSubmit.Widget.Highlighting = HighlightingMode.Invert;
- btnSubmit.Widget.Page = page;
-
- // The URL for the submission:
- btnSubmit.Widget.Activate = new ActionSubmitForm("/Samples/HandleFormSubmitXml");
- doc.AcroForm.Fields.Add(btnSubmit);
-
- // Reset form button:
- var btnReset = new PushButtonField();
- btnReset.Widget.Rect = new RectangleF(ip.X + fldOffset + 72 * 1.5f, ip.Y, 72, fldHeight);
- btnReset.Widget.ButtonAppearance.Caption = "Reset";
- btnReset.Widget.Highlighting = HighlightingMode.Invert;
- btnReset.Widget.Page = page;
- btnReset.Widget.Activate = new ActionResetForm();
- doc.AcroForm.Fields.Add(btnReset);
- ip.Y += dY;
-
- // Done:
- doc.Save(stream);
- return doc.Pages.Count;
- }
-
- //
- // NOTE: the code below is used by the web sample browser controller when the form
- // prepared by this sample is submitted, it is not directly called by the CreatePDF() method.
- //
-
- // Creates a GcPdfDocument, loads an AcroForm PDF into it, and fills it with data
- // using the GcPdfDocument.ImportFormDataFromXML() method.
- //
- // This method is called by the samples controller when the form prepared by this sample
- // is submitted by the user. The samples controller parses the client response and builds
- // the 'values' collection filling it with the submitted field values, then calls
- // this method to prepare the XML, imports it into a newly created PDF, and returns
- // the resulting PDF to the controller, which sends it back to the client.
- public static Stream ImportFormData(List<FieldExportEntry> values)
- {
- var pdf = new GcPdfDocument();
- using var fs = File.OpenRead(Path.Combine("Resources", "PDFs", "ImportFormXML.pdf"));
- pdf.Load(fs);
- using (var ms = new MemoryStream())
- {
- SaveFieldsToXML(values, ms);
- ms.Seek(0, SeekOrigin.Begin);
- pdf.ImportFormDataFromXML(ms);
- }
- var outMs = new MemoryStream();
- pdf.Save(outMs);
- outMs.Seek(0, SeekOrigin.Begin);
- return outMs;
- }
-
- // Represents a form field and its value(s) for export to XML.
- public class FieldExportEntry
- {
- public string Name { get; set; }
- public List<string> Values { get; set; }
- // Note: this sample does not support child fields:
- // public List<FieldTreeNode> Children { get; set; }
- }
-
- // Saves the fields and their values to a stream.
- //
- // This method is similar to GcPdfDocument.ExportFormDataToXML(), with the following
- // important limitations:
- // - it does not support child fields (field.Children collection);
- // - it does not handle fields with names that are not valid XML names (xfdf:original).
- public static void SaveFieldsToXML(List<FieldExportEntry> values, Stream stream)
- {
- var xws = new XmlWriterSettings()
- {
- Indent = true,
- CloseOutput = false,
- Encoding = Encoding.UTF8,
- };
- using XmlWriter xw = XmlWriter.Create(stream, xws);
- xw.WriteStartElement("fields");
- xw.WriteAttributeString("xmlns", "xfdf", null, "http://ns.adobe.com/xfdf-transition/");
- foreach (var ftn in values)
- {
- xw.WriteStartElement(ftn.Name);
- foreach (var v in ftn.Values)
- {
- xw.WriteStartElement("value");
- // NOTE: the values in the array are formed by the client PDF viewer,
- // and it represents 'on' checkbox values as 'true', while ImportFormDataFromXML
- // expects 'on' values to be represented as "Yes" (that's how ExportFormDataToXML
- // works, similar to Acrobat). This here is a quick and dirty hack just for the
- // sake of this sample:
- xw.WriteString(v == "true" ? "Yes" : v);
- xw.WriteEndElement();
- }
- xw.WriteEndElement();
- }
- xw.WriteEndElement();
- }
- }
- }
-