FormSubmitXml.cs
  1. //
  2. // This code is part of Document Solutions for PDF demos.
  3. // Copyright (c) MESCIUS inc. All rights reserved.
  4. //
  5. using System.Drawing;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Xml;
  9. using System.Text;
  10. using System.Collections.Generic;
  11. using GrapeCity.Documents.Pdf;
  12. using GrapeCity.Documents.Pdf.AcroForms;
  13. using GrapeCity.Documents.Pdf.Actions;
  14. using GrapeCity.Documents.Pdf.Annotations;
  15. using GrapeCity.Documents.Text;
  16.  
  17. namespace DsPdfWeb.Demos
  18. {
  19. // Note that the FormDataSubmit sample shows a better and easier solution for submitting form data.
  20. //
  21. // This sample creates an AcroForm PDF that can be submitted to the server.
  22. // It relies on the server to put the submitted data into an XML,
  23. // import that XML into a PDF containing a similar form,
  24. // and send the form with loaded data back to the client.
  25. // Note that the produced PDF with filled form fields
  26. // is shown in the client browser's default PDF viewer.
  27. // The code is similar to FormSubmit.
  28. public class FormSubmitXml
  29. {
  30. public int CreatePDF(Stream stream)
  31. {
  32. var doc = new GcPdfDocument();
  33. var page = doc.NewPage();
  34.  
  35. var rc = Common.Util.AddNote("Fill the fields in the form and click 'Submit' to send it back to the server. " +
  36. "The sample server will put the submitted data into an XML, feed that XML" +
  37. "to a PDF with a different but compatible form, and send the resulting form" +
  38. "filled with the submitted data back to your browser." +
  39. "Note that the form with the submitted data is opened in the browser's default PDF viewer," +
  40. "and does not have the 'Submit' and 'Reset' buttons.", page);
  41.  
  42. var g = page.Graphics;
  43. var tf = new TextFormat() { Font = StandardFonts.Times, FontSize = 14 };
  44. var ip = new PointF(72, rc.Bottom + 36);
  45. float fldOffset = 72 * 2 + 46;
  46. float fldHeight = tf.FontSize * 1.2f;
  47. float dY = 32;
  48.  
  49. // Text field:
  50. g.DrawString("First name:", tf, ip);
  51. var fldFirstName = new TextField() { Name = "FirstName", Value = "John" };
  52. fldFirstName.Widget.Page = page;
  53. fldFirstName.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight);
  54. fldFirstName.Widget.DefaultAppearance.Font = tf.Font;
  55. fldFirstName.Widget.DefaultAppearance.FontSize = tf.FontSize;
  56. doc.AcroForm.Fields.Add(fldFirstName);
  57. ip.Y += dY;
  58.  
  59. // Text field:
  60. g.DrawString("Last name:", tf, ip);
  61. var fldLastName = new TextField() { Name = "LastName", Value = "Smith" };
  62. fldLastName.Widget.Page = page;
  63. fldLastName.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight);
  64. fldLastName.Widget.DefaultAppearance.Font = tf.Font;
  65. fldLastName.Widget.DefaultAppearance.FontSize = tf.FontSize;
  66. doc.AcroForm.Fields.Add(fldLastName);
  67. ip.Y += dY;
  68.  
  69. // Checkbox:
  70. g.DrawString("Subscribe to Mailing List:", tf, ip);
  71. var fldCheckbox = new CheckBoxField() { Name = "Subscribe", Checked = true };
  72. fldCheckbox.Widget.Page = page;
  73. fldCheckbox.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, fldHeight, fldHeight);
  74. doc.AcroForm.Fields.Add(fldCheckbox);
  75. ip.Y += dY;
  76.  
  77. // Multiline TextBox:
  78. g.DrawString("Additional information:", tf, ip);
  79. var fldAdditionalInfo = new TextField() { Name = "AdditionalInfo", Multiline = true };
  80. fldAdditionalInfo.Widget.Page = page;
  81. fldAdditionalInfo.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72 * 3, fldHeight * 2);
  82. fldAdditionalInfo.Widget.DefaultAppearance.Font = tf.Font;
  83. fldAdditionalInfo.Widget.DefaultAppearance.FontSize = tf.FontSize;
  84. doc.AcroForm.Fields.Add(fldAdditionalInfo);
  85. ip.Y += dY * 2;
  86.  
  87. // Submit form button:
  88. var btnSubmit = new PushButtonField();
  89. btnSubmit.Widget.Rect = new RectangleF(ip.X + fldOffset, ip.Y, 72, fldHeight);
  90. btnSubmit.Widget.ButtonAppearance.Caption = "Submit";
  91. btnSubmit.Widget.Highlighting = HighlightingMode.Invert;
  92. btnSubmit.Widget.Page = page;
  93.  
  94. // The URL for the submission:
  95. btnSubmit.Widget.Activate = new ActionSubmitForm("/Samples/HandleFormSubmitXml");
  96. doc.AcroForm.Fields.Add(btnSubmit);
  97.  
  98. // Reset form button:
  99. var btnReset = new PushButtonField();
  100. btnReset.Widget.Rect = new RectangleF(ip.X + fldOffset + 72 * 1.5f, ip.Y, 72, fldHeight);
  101. btnReset.Widget.ButtonAppearance.Caption = "Reset";
  102. btnReset.Widget.Highlighting = HighlightingMode.Invert;
  103. btnReset.Widget.Page = page;
  104. btnReset.Widget.Activate = new ActionResetForm();
  105. doc.AcroForm.Fields.Add(btnReset);
  106. ip.Y += dY;
  107.  
  108. // Done:
  109. doc.Save(stream);
  110. return doc.Pages.Count;
  111. }
  112.  
  113. //
  114. // NOTE: the code below is used by the web sample browser controller when the form
  115. // prepared by this sample is submitted, it is not directly called by the CreatePDF() method.
  116. //
  117.  
  118. // Creates a GcPdfDocument, loads an AcroForm PDF into it, and fills it with data
  119. // using the GcPdfDocument.ImportFormDataFromXML() method.
  120. //
  121. // This method is called by the samples controller when the form prepared by this sample
  122. // is submitted by the user. The samples controller parses the client response and builds
  123. // the 'values' collection filling it with the submitted field values, then calls
  124. // this method to prepare the XML, imports it into a newly created PDF, and returns
  125. // the resulting PDF to the controller, which sends it back to the client.
  126. public static Stream ImportFormData(List<FieldExportEntry> values)
  127. {
  128. var pdf = new GcPdfDocument();
  129. using var fs = File.OpenRead(Path.Combine("Resources", "PDFs", "ImportFormXML.pdf"));
  130. pdf.Load(fs);
  131. using (var ms = new MemoryStream())
  132. {
  133. SaveFieldsToXML(values, ms);
  134. ms.Seek(0, SeekOrigin.Begin);
  135. pdf.ImportFormDataFromXML(ms);
  136. }
  137. var outMs = new MemoryStream();
  138. pdf.Save(outMs);
  139. outMs.Seek(0, SeekOrigin.Begin);
  140. return outMs;
  141. }
  142.  
  143. // Represents a form field and its value(s) for export to XML.
  144. public class FieldExportEntry
  145. {
  146. public string Name { get; set; }
  147. public List<string> Values { get; set; }
  148. // Note: this sample does not support child fields:
  149. // public List<FieldTreeNode> Children { get; set; }
  150. }
  151.  
  152. // Saves the fields and their values to a stream.
  153. //
  154. // This method is similar to GcPdfDocument.ExportFormDataToXML(), with the following
  155. // important limitations:
  156. // - it does not support child fields (field.Children collection);
  157. // - it does not handle fields with names that are not valid XML names (xfdf:original).
  158. public static void SaveFieldsToXML(List<FieldExportEntry> values, Stream stream)
  159. {
  160. var xws = new XmlWriterSettings()
  161. {
  162. Indent = true,
  163. CloseOutput = false,
  164. Encoding = Encoding.UTF8,
  165. };
  166. using XmlWriter xw = XmlWriter.Create(stream, xws);
  167. xw.WriteStartElement("fields");
  168. xw.WriteAttributeString("xmlns", "xfdf", null, "http://ns.adobe.com/xfdf-transition/");
  169. foreach (var ftn in values)
  170. {
  171. xw.WriteStartElement(ftn.Name);
  172. foreach (var v in ftn.Values)
  173. {
  174. xw.WriteStartElement("value");
  175. // NOTE: the values in the array are formed by the client PDF viewer,
  176. // and it represents 'on' checkbox values as 'true', while ImportFormDataFromXML
  177. // expects 'on' values to be represented as "Yes" (that's how ExportFormDataToXML
  178. // works, similar to Acrobat). This here is a quick and dirty hack just for the
  179. // sake of this sample:
  180. xw.WriteString(v == "true" ? "Yes" : v);
  181. xw.WriteEndElement();
  182. }
  183. xw.WriteEndElement();
  184. }
  185. xw.WriteEndElement();
  186. }
  187. }
  188. }
  189.