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

PDF reporting using ASP.NET MVC3

, 5 Aug 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
A description and solution for creating PDF reports using ASP.NET MVC3.

ASP_MVC_Reporting/ASP_MVC3_PDF_Reporting_1.jpg

Contents

Introduction

Almost every web application (that I have built) needs some kind of reporting. Many times the client wants to generate a PDF report that corresponds with the web page he or she is viewing. Using iTextSharp, a free C# PDF library, this is possible. This article describes and includes a solution for creating reports using iTextSharp and ASP.NET MVC3.

Background

iTextSharp is a free C# PDF library that is ported from the Java-PDF library iText. iText was launched in 2000 and is a popular Open Source Java library for programmatic creation and manipulation of PDF. As with many successful Open-Source Java libraries, it was ported to C# under the name iTextSharp. iTextSharp has been under development since 2008 and is distributed under the GNU Affero General Public License version 3.

At its core, iTextSharp is an API to manipulate PDF creation. For a recent project, I was looking for a solution that would enable me to create PDF documents from existing HTML documents or Views used in an ASP.NET MVC3 project. The optimal solution for me would be to throw an existing ASP.NET MVC3 view at it and let it generate a PDF that is exactly the same as the HTML rendered by a browser.

The solution described here uses the HTMLWorker class from iTextSharp to generate a PDF from an HTML view. HTMLWorker is an iTextSharp class that is able to parse an HTML document and generate a PDF using what is called the SimpleParser of iTextSharp. Notice the name SimpleParser which indicates that not all HTML elements and CSS styles are supported. However, I was able to get good results using this solution.

To add reporting to your ASP.NET MVC3 project, first add the PDFReportGenerator project to your solution and add the iTextSharp.dll binary to your solution. PDFReportGenerator needs a reference to the binary. By adding the binary to the solution, you are able to build the project directly from source control. Check the demo source for an example.

Creating a report

Follow these steps to generate an actual report from your web application:

  1. Create a controller that derives from PdfViewController.
  2. Create a view that generates the HTML which should be translated to a PDF report.
  3. Create an action on a controller which calls the ViewPDF method on the PdfViewController.
  4. Create a link to trigger the action on the controller.

Below, these steps are described in more detail.

Create a controller that derives from PdfViewController

Create a new or reuse an existing controller and let it derive from PdfViewController from the PdfReportGenerator project. This enables your controller to call the ViewPDF method of the PDFViewController which generates the actual PDF. In the demo project, this is the HomeController.

Create a view that generates the HTML

Create a view that should be translated to a report. This could be an existing view or a new view specially for reporting. I usually create a new view as it lets me control the HTML markup for the report. As stated earlier, the report generator does not support all the HTML markup. In the demo project, this is the PrintDemo view.

Below, the PrintDemo view from the demo project is shown. As can be seen, this is just a simple ASP.NET Razor view with a table and some rows. It uses a strongly typed model but that is not necessary. A tip when trying to design your report is to add borders to your table or div. Using these borders, when looking at the generated PDF, you can clearly see the start and end of the areas of your report.

@using MvcReportGeneratorDemo.Models
@model CustomerList
<br />
<table cellpadding="3" cellspacing="3">
    <tr border="1" bgcolor="#777777" color="#ffffff">
        <td>Name</td>
        <td>Address</td>
        <td>Place</td>
    </tr>
    @foreach (Customer customer in Model)
    {
        <tr border="1">
            <td>@customer.Name</td>
            <td>@customer.Address</td>
            <td>@customer.Place</td>
        </tr>
    }
</table>

Create an action which calls the ViewPDF method

The PdfViewController class from which your controller derives contains a ViewPDF method. This method has the following signature:

protected ActionResult ViewPdf(string pageTitle, string viewName, object model)

Parameters

  • pageTitle
    • Type: System.String
    • The title of the report which appears on the header of the page.
  • viewName
    • Type: System.String
    • The name of the view which should be converted to a report.
  • model
    • Type: System.Object
    • The model that is rendered by the view.

This methods generates the HTML view and converts it into a PDF report and sends this PDF as a binary stream back to the client. This means that when the client has a PDF plug-in installed, the PDF is shown inside the browser.

From an action inside your controller, this method should be called to generate the report and send it to the client. The following action from the demo application generates the PDF. "Customer report" is the title of the report, "PrintDemo is the name of the view, and the model is returned by the CreateCustomerList() which as its name implies generates a dummy list with customers.

public ActionResult PrintCustomers()
{
   return this.ViewPdf("Customer report", "PrintDemo", CreateCustomerList());
}

The last step is to create a link on a page that calls this action to actually print the report.

Trigger the action on the controller

A simple method to create a link to trigger the action on the controller is by using an ActionLink. This link calls the action that we defined on the controller.

@Html.ActionLink("Print customers", "PrintCustomers", null,  new { target = "_blank" })

These are the steps you need to be able to create PDF reports from your ASP.NET MVC3 projects. Read the next part of the article if you are interested in the details of how the PdfReportGenerator actually converts the ASP.NET MVC3 view into a report.

Detailed Reporting Project overview

The PdfReportGenerator project consist of six classes which can be seen in the image below. The PdfReportGenerator assembly works by rendering the ASP.NET MVC3 view into a string and converting this string with HTML using the iTextSharp into a PDF report.

6 Classes that make up the PdfReportGenerator project

Rendering an ASP.NET MVC3 view into a string

The class HtmlViewRenderer is responsible for rendering the ASP.NET view into a string. The method RenderViewToString has the following signature.

public string RenderViewToString(Controller controller, string viewName, object viewData)

The first argument is viewName which is the name of the view that should get rendered to a string including the model viewData that is needed by the view. The controller is necessary to be able to use to render the view using the view engine of ASP.NET MVC.

Convert the HTML string into a PDF byte array

Once we have the HTML in a string, StandardPdfRenderer converts the HTML string into a PDF byte array. The class StandardPdfRenderer has a method Render with the following signature.

public byte[] Render(string htmlText, string reportTitle)

htmlText is the rendered view as a string that was produced by the HtmlViewRender; pageTitle is, as the name suggests, the title of the report.

Send the byte array back to the client as a stream

The last step is to convert the byte array into an instance of the BinaryContentResult class. The class BinaryContentResult derives from the ASP.NET MVC ActionResult. It overrides ExecuteResult and returns the content as a binary stream.

The class PdfViewController is the class that combines these classes. The method ViewPdf uses all the three previously mentioned classes to generate the PDF as shown in the code below:

protected ActionResult ViewPdf(string pageTitle, string viewName, object model)
{
    // Render the view html to a string.
    string htmlText = this.htmlViewRenderer.RenderViewToString(this, viewName, model);

    // Let the html be rendered into a PDF document through iTextSharp.
    byte[] buffer = standardPdfRenderer.Render(htmlText, pageTitle);

    // Return the PDF as a binary stream to the client.
    return new BinaryContentResult(buffer, "application/pdf");
}

Points of interest

Colors

iTextsharp supports colors out of the box; in the demo application, the background colors of the rows are alternated using different colors. These colors are visible in the report.

New page support

One thing that I needed with my project that was not supported by the HTML conversion in iTextSharp was functionality to force a page break. Most of the time, with reporting, you need to be able to force a page break, for example, if you want a graph to start always on a new page. The way I solved this was to add support for it to iTextSharp. As it is Open-Source, you are able to add new features to it. I added support for a non-existing HTML tag called <np /> which forces iTextSharp to create a new page. I created a patch so that it could be committed to the iTextSharp project. I do not know if it will be included in the main trunk of the project as it feels somewhat strange to invent new HTML tags just to support a page break. But if you need it, you can use the patch to compile iTextSharp with new page support.

Images

It is possible to add images to the report by using an <img src="" /> tag. I had no success with dynamically generated images. So I generate the images that I needed before the action conversion process takes place. A single static image can be seen in the report.  

ASP.NET support

It should be possible to use the same kind of solution using older versions of ASP.NET MVC. However, I have not tried it.

History

  • 26/09/2011
    • First version.
  • 06/08/2012
    • Added an image to the PDF report.  

License

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

Share

About the Author

Patrick Kalkman
Architect http://www.hinttech.nl
Netherlands Netherlands
Patrick Kalkman is a senior Software Architect with more than 20 years professional development experience. He works for Hinttech where he develops state of the art web applications.

Patrick enjoys writing his blog. It discusses software architectures using semantic web technologies. Patrick can be reached at pkalkie@gmail.com.
 
Published Windows 8 apps:
 
Published Windows Phone apps:
 
Awards:

Best Mobile article of March 2012
Best Mobile article of June 2012
Follow on   Twitter

Comments and Discussions

 
QuestionArabic letters support PinmemberNasir Taha25-Nov-14 23:17 
GeneralMy vote of 1 PinmemberAnchal Singh28-Sep-14 21:11 
GeneralMy Vote Of 5 Pinmemberdiponsust15-Aug-14 21:59 
GeneralPoints PinmemberMember 1081583413-May-14 11:40 
GeneralMy vote of 5 PinmemberMember 42253394-Mar-14 3:18 
GeneralRe: My vote of 5 PinmemberPatrick Kalkman15-Apr-14 21:42 
QuestionAccess error Pinmembernataliaps3-Jan-14 0:48 
AnswerRe: Access error Pinmemberhandersonmarinho23-Jan-14 6:17 
GeneralRe: Access error Pinmembernataliaps24-Jan-14 12:40 
AnswerRe: Access error PinmemberPatrick Kalkman2-Feb-14 21:33 
GeneralRe: Access error Pinmembernataliaps18-Mar-14 2:14 
QuestionHow can I change the width of my cell? PinmemberAlexanderBlade28-Nov-13 17:46 
QuestionIs there a way to specify bordercolor? Pinmemberkungsalo8-Nov-13 3:33 
QuestionReport with Times New Roman or new Font ?? Pinmemberhulahula0116-Aug-13 20:55 
QuestionServer Error in '/' Application. PinmemberBorgan Fofanov29-Jul-13 23:46 
GeneralMy vote of 1 Pinmemberdave_dv1-Jun-13 6:41 
GeneralMy vote of 5 PinmemberBronek31-May-13 7:48 
GeneralRe: My vote of 5 PinmemberPatrick Kalkman15-Apr-14 21:40 
GeneralMy vote of 5 PinmemberPrasaad SJ30-May-13 23:50 
GeneralRe: My vote of 5 PinmemberPatrick Kalkman15-Apr-14 21:40 
GeneralMy vote of 5 PinmemberMember 39753851-May-13 5:09 
GeneralRe: My vote of 5 PinmemberPatrick Kalkman15-Apr-14 21:40 
QuestionBorder with style? PinmemberChaitanya Kolla26-Mar-13 21:09 
AnswerRe: Border with style? PinmemberPatrick Kalkman15-Apr-14 21:41 
QuestionMy vote of 5 PinmemberJamesPChadwick21-Feb-13 5:24 
AnswerRe: My vote of 5 PinmemberJamesPChadwick21-Feb-13 7:25 
GeneralRe: My vote of 5 PinmemberPatrick Kalkman21-Feb-13 9:07 
Questiondon't take my css Pinmemberwgir12-Feb-13 9:40 
AnswerRe: don't take my css PinmemberPatrick Kalkman21-Feb-13 9:06 
Answerit can't display Chinese,do you have any methods to handle it ? Pinmemberabclanyong29-Jul-14 20:12 
QuestionChange char to polish Pinmemberand1_836-Feb-13 23:52 
Questionsupport for css? PinmemberKalpana Volety11-Jan-13 12:03 
AnswerRe: support for css? PinmemberPatrick Kalkman15-Jan-13 21:05 
QuestioniTextSharp changes source code Pinmembersilvia.stanila9-Jan-13 9:25 
AnswerRe: iTextSharp changes source code PinmemberPatrick Kalkman15-Jan-13 21:40 
Hi Silvia,
 
I can't access the patch I created for iTextSharp anymore. There has been some changes to the sourceforge website and I guess they do not have migrated the unaccepted patches.
 
I will try to recreate the changes into the current iTextSharp library but I cannot give you an estimate when it will be done. It will probably take some time due to my other activities.
 
If you are up to it you can try to recreate them yourself. I changed the HtmlTags.cs and the HTMLWorker.cs classes in the simpleparser folder. You can use reflector and open the iTextSharp.dll in the download with this article to see the changes. You then could try to reimplement them on the current version of iTextSharp.
 
Another possibility is to look at the remark Scott Kersey made below. He suggested a solution that uses a pagebreak class to force a page break in a report.
<div class="pagebreak"></div>
 
Maybe you can contact him and ask if he managed to create a solution for it.
Patrick Kalkman
 
My latest article: Weekly Thai Recipe! for Windows Phone
My Blog: SemanticArchitecture.net

GeneralRe: iTextSharp changes source code Pinmembersilvia.stanila16-Jan-13 3:41 
QuestionLandscape PinmemberRodrigo De Freitas Oliveira21-Dec-12 2:19 
AnswerRe: Landscape PinmemberPatrick Kalkman15-Jan-13 21:22 
GeneralRe: Landscape PinmemberLeon Amarant8-Feb-13 9:19 
SuggestionRe: Landscape PinmemberLeon Amarant8-Feb-13 9:46 
GeneralRe: Landscape PinmemberPatrick Kalkman20-Feb-13 8:08 
Questiondoes not always open the pdf PinmemberMember 969576820-Dec-12 4:36 
AnswerRe: does not always open the pdf PinmemberPatrick Kalkman15-Jan-13 21:15 
QuestionRe: does not always open the pdf PinmemberJoerjo31-Jan-13 17:45 
SuggestionRe: does not always open the pdf Pinmemberrlibotti12-Mar-14 12:17 
Questionerror Pinmembermilon_bd10-Dec-12 23:32 
AnswerRe: error PinmemberPatrick Kalkman15-Jan-13 21:08 
QuestionGreat stuff! Pinmembersilvia.stanila6-Dec-12 23:54 
AnswerRe: Great stuff! PinmemberPatrick Kalkman15-Jan-13 21:07 
QuestionPagebreak functionality in itextsharp PinmemberScott Kersey3-Dec-12 6:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141216.1 | Last Updated 6 Aug 2012
Article Copyright 2011 by Patrick Kalkman
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid