Click here to Skip to main content
Click here to Skip to main content

Using PDF Forms to Improve User Interaction with DotPdf

, 31 Jul 2014 CPOL
Use Atalasoft's DotPdf SDK to improve workflow processes with external customers.

Editorial Note

This article is in the Product Showcase section for our sponsors at CodeProject. These reviews are intended to provide you with information on products and services that we consider useful and of value to developers.

Introduction

This article will walk through the steps to programmatically create a PDF file using DotPdf, stream it to a client computer, then parse the data upon the client’s submission.

What you will need

  • Atalasoft DotPdf

    If you do not have DotPdf you can download the installer here. http://www.atalasoft.com/products/dotpdf/

  • Atalasoft DotPdf License

    Use the Activate DotPdf application in your start menu to generate a DotPdf license. If you deploy your application to IIS you will need to get a server license and put it in your bin folder of the application.

  • Visual Studio Standard C# IDE

Create a Web Project with handler

Open Visual Studio and create a new project. Select .ASP web application as the project type. Add two New Items to your project, a HTML page and a Generic Handler named PdfHandler.ashx. Set the HTML page as the start page for your application. The PdfHandler.ashx is where you will put all of the backend code for this project.

Generating a PDF form

First we will need to generate the PDF form. DotPdf has a class called PdfGeneratedDocument it is the starting point to generate a document. The document will also be storing our PdfForm object and contains any number of PdfPage objects. Using the following three method calls we will initialize the document to have a page and a form:

            PdfGeneratedDocument doc = new PdfGeneratedDocument();
            doc.Form = new Atalasoft.PdfDoc.Generating.Forms.PdfForm();
            PdfGeneratedPage page = doc.AddPage(PdfDefaultPages.Letter);

Next, we will create a data field for the client to submit text data. This is done with a TextWidgetAnnotation. To label the field we will use a PdfTextLine. Remember that PDF coordinates are drawn from the bottom left of the page with each inch being represented by 72 PDF points. To put the text annotation near the top of the document, I chose 700 for the Y component and generated the following code:

           TextWidgetAnnotation name = new TextWidgetAnnotation(
               new PdfBounds(72, 700, 200, 20), "name", null);
           PdfTextLine nameLabel = new PdfTextLine(
               "Helvetica", 22.0, "Name:", new PdfPoint(72, 730));

Note: Using Helvetica for the PdfTextLine’s font allows you to not have to create a PdfFontResource. If you wish to have a custom font, you will need to create a PdfFontResource and add it to the document.

Once the objects are created, they will need to be added to the appropriate rendering lists. The PdfTextLine will need to be added to the page’s drawing list. Because the TextWidgetAnnotation is an annotation and part of our form, we will need to add it to both the annotation list and the form object.

page.DrawingList.Add(nameLabel);
page.Annotations.Add(name);
doc.Form.Fields.Add(name);

The other form element is the submit button. When the client clicks the submit button, we want the PDF form to send a post request to our webhandler. Just like the other annotation, we need to give it a position. To make this a submit button we must give it a PdfSubmitFormAction initialized with URL that it will post to, and SubmitAsHtml set to true. Then we add it to the Form and Annotations collections:

            PushButtonWidgetAnnotation button = new PushButtonWidgetAnnotation(
                new PdfBounds(72, 550, 60, 20), "submit");
            PdfSubmitFormAction submit = new PdfSubmitFormAction(context.Request.Url);
            submit.SubmitAsHtml = true;
            button.ClickActions.Add(submit);
            page.Annotations.Add(button);
            doc.Form.Fields.Add(button);

I recommend then wrapping all the PDF generation code in a method call CreatePdf(context).

Streaming the PDF to the client

To then stream the generated PDF to the client, we write the document out to the Context.Response.OutputStream. The following code will allow for the document to be streamed to the client and automatically opened in the adobe plugin or chromes PDF viewer:

            private void SendPdfForm(HttpContext context)
        {
            context.Response.Clear();
            context.Response.ContentType = "application/pdf";
            context.Response.AddHeader("Content-Disposition", "inline; filename=" + "PDFForm");

            PdfGeneratedDocument doc = CreatePdf(context);

            MemoryStream mem = new MemoryStream();
            doc.Save(mem);
            mem.Seek(0, SeekOrigin.Begin);
            byte[] pdfBytes = new byte[mem.Length];
            mem.Read(pdfBytes, 0, (int)(mem.Length));
            context.Response.AddHeader("Content-Length", pdfBytes.Length.ToString());
            context.Response.BinaryWrite(pdfBytes);
            context.Response.Flush();
            context.Response.End();
        }

Routing the requests to the proper functions

In the ashx file, when it was generated, there is a method stub for ProcessRequest. This is where all of the requests to PdfHandler.ashx will be routed to. Due to the nature of our application, two different requests will be made of the handler: one to request the programmatically generated PDF and one to handle the PDF form submission. PDF form submission will always have information in the input stream. To distinguish when one of these calls is made I use the following code:

        if (context.Request.InputStream.Length !=0)
                HandleFormSubmission(context);

To distinguish a request for the PDF we can access a hidden form value though the query string like this:

            if(context.Request.QueryString["pdf"]!=null)
                SendPdfForm(context);

Requesting the PDF though HTML

In your HTML document, sending a request to the server for the dynamically generated PDF is simple. Make a HTML form with a submit button and a hidden data value (this will get consumed as a query string):

<body>
<form action="PdfHandler.ashx">
<input type="hidden" name="pdf" value="request" />
<input type="submit" id="Button1" value="Get Pdf Form" /> 
</form>
</body>

If you were to debug your application at this point, place a breakpoint on the SendPdfForm method call in your ProcessRequest method. If you press the button on your HTML page you should cause the breakpoint to trigger. After continuing you should be presented with a PDF document (assuming you are using Chrome or have Adobe Acrobat installed and plugged into your browser).

Handling the PdfForm POST request

Once the PDF is successfully streaming to the client, submit a form with the name field filled in and the InputStream of the resulting request to your webserver will contain an HTML query string style data pairing string (e.g. "name=Jeff&DOB=12021985"). There is a built in static .NET method to parse this style of return data into a NameValueCollection: it is HttpUtility.ParseQueryString(string). That data can then be processed into your solution in whatever way your workflow is designed.

History

Version 1.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Kevin_Hulse

United States United States
Kevin Hulse is the Solutions Enablement Specialist for Atalasoft. While at Atalasoft he has done Support, Product Development, and now finds himself in Marketing. His hobbies include playing team sports and convincing fellow engineers to play team sports with him.

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411022.1 | Last Updated 31 Jul 2014
Article Copyright 2014 by Kevin_Hulse
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid