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

Create PDF from html using C#, Nustache,Mustache and Pechkin

, 18 Aug 2013
Rate this:
Please Sign up or sign in to vote.
This article explains how to create a PDF file using C# object

Background

Recently, I had to work on a task where we need to create a PDF version of a Silverlight page.The data to the markup (xaml) was from a C# object (yes, you guessed it! we used MVVM pattern) and we wanted to use that object for the PDF file.Below are the components we used to create a PDF file.

Dependencies

As mentioned above you need

  • Nustache library
  • Pechkin

I have excluded these Dlls in the sample code because one of the dll,wkhtmltox0, of Pechkin package is about 29 MB resulting the attachment bigger.So, you will get build error if you just open and hit F5 (The source code can be opened in either VS 2010 or VS 2012).

Installing dependencies

Using Nuget package manager


Manual installation

You can also download the .zip version of these and manually add reference to your project.In this case you should do the following settings in order to make the code work

Add reference


Add these files to the root of the project and set 'copy if newer'


update web.config (or App.config in case you use it in Console)

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.1.2.0" newVersion="2.1.2.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

 

Using the code

The sample solution has three projects: 1.WCF service 2. Silverlight app 3. Web app


 

PDFService

 

The class PdfService offers two methods.

PdfBytes - accepts any string content and convert as a PDF bytes to the client.

EmployeePdf - specific to Employee object and it converts the employee data into a html string which then be passed to the PdfBytes method to get PDF bytes.

    public class PdfService : IPdfService
    {
        public PdfResult PdfBytes(string content)
        {
            var result = new PdfResult();
            try
            {
                var oc = new ObjectConfig();
                oc.SetPrintBackground(true); //to apply the background colors in the pdf
                var footer = oc.Footer;
                footer.SetFontSize(8);
                footer.SetTexts("For internal use only", string.Empty, string.Empty);
                result.Bytes = new SynchronizedPechkin(new GlobalConfig()).Convert(oc, content);
            }
            catch (Exception ex)
            {
                result.Error = ex.Message;
            }
            return result;
        }
 
        public PdfResult EmployeePdf(Employee employee)
        {
            string nustachTemplate = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, "App_Data", "EmployeeTemplate.html");
            var employeeHtml = Render.FileToString(nustachTemplate, employee);
            return PdfBytes(employeeHtml);
        }
    }

The Employee object's data are injected into the Mustache html template. You can apply styles (only inline styles, style sheets cannot be linked) to design the page output.

<html>
<head>
    <title>Employee Print</title>
    <style>
        body {
            margin: 5px;
        }
 
        h3 {
            text-align: center;
            border-radius: 10px;
        }
 
        h4 {
            background: silver;
            border-radius: 5px;
            padding-left: 10px;
        }
    </style>
</head>
<body>
 
    <h3>Employee {{Name}}</h3>
    <h4>Basic Details</h4>
    <div>
        <p>Name:</p>
        <p>{{Name}}</p>
    </div>
    <div>
        <p>Email:</p>
        <p>{{Email}}</p>
    </div>
    <div>
        <p>Address:</p>
        <p>{{Address}}</p>
    </div>
    <h4>Skills</h4>
 
    {{#Skills}}
  <p>{{Name}}</p>
    {{/Skills}}
    
    {{^Skills}}
  <p>No skills</p>
    {{/Skills}}
    <h4>Hobbies</h4>
 
    {{#Hobbies}}
  <p>{{Name}}</p>
    {{/Hobbies}}
 
      {{^Hobbies}}
  <p>No hobbies</p>
    {{/Hobbies}}
 
     <h4>Jobs</h4>
    {{#Jobs}}
  <p>{{Company}}: as a {{Role}} for {{NoOfYears}} years.</p>
    {{/Jobs}}
 
    {{^Jobs}}
  <p>No jobs</p>
    {{/Jobs}}
</body>
</html>

And the Employee class

    [DataContract]
    public class Employee
    {
        public Employee()
        {
            Hobbies = new List<Hobby>();
            Skills = new List<Skill>();
            Jobs = new List<Job>();
        }
 
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string Address { get; set; }
        [DataMember]
        public string Email { get; set; }
        [DataMember]
        public List<Hobby> Hobbies { get; set; }
        [DataMember]
        public List<Skill> Skills { get; set; }
        [DataMember]
        public List<Job> Jobs { get; set; }
    }

Here is the final PDF


SilverlightApplication1

A client application using the PDFService to generate Pdf. The code to call the service and save the file.

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            var dialog = new SaveFileDialog()
                {
                    DefaultExt = "Adobe PDF Files(*.pdf)",
                    Filter = "PDF (*.PDF)|*.PDF",
                    FilterIndex = 2
                };

            if (dialog.ShowDialog() == true)
            {
                var client = new PdfServiceClient();
                var emp = GetEmployee();
                client.EmployeePdfCompleted += (s, ea) =>
                {
                    if (ea.Error != null)
                    {
                        MessageBox.Show(string.Format("Error:{0}", ea.Error.Message));
                        return;
                    }
                    if (!string.IsNullOrWhiteSpace(ea.Result.Error))
                    {
                        MessageBox.Show(string.Format("Error:{0}", ea.Result.Error));
                        return;
                    }
                    using (System.IO.Stream stream = dialog.OpenFile())
                    {
                        stream.Write(ea.Result.Bytes, 0, ea.Result.Bytes.Length);

                    }
                    MessageBox.Show("Pdf saved");
                };
                client.EmployeePdfAsync(emp);
            }

        }

Pros and cons

Pros

  • Easy to build page content
  • We can CSS to style the output
  • No manual calculation of page count in PDF. Pages generated automatically based on the content
  • Free libraries

Cons

  • Dlls are big in size
  • Any other you may think of?

Points of Interest

The Nustache and Mustache template are not really a requirement for creating a PDF file. You can create without it just by passing a string or build your own html as far as it meets the requirement.I personally prefer Mustache as it is easy to build html,more importantly you can show or hide elements based on conditions while you have the full layout designed in HTML.

Before you download sample code

Again, the sample code will not work unless you follow the instructions mentioned in the Dependencies section in the top.

History

First version

Finally...

I wanted to share my work on creating PDF and I did now.If somebody finds this interesting and can be of help then I will feel worth of it. As always, comments/suggestions are welcome.

License

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

About the Author

Prabu ram
Technical Lead CGI
India India
No Biography provided
Follow on   LinkedIn

Comments and Discussions

 
Question"Cons: Any other you may think of?" PinmemberQuake2Player9-Dec-13 10:49 
AnswerRe: "Cons: Any other you may think of?" PinmemberPrabu ram9-Dec-13 17:37 
SuggestionMessage Automatically Removed PinmemberMember 99341021-Oct-13 23:08 

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 | Mobile
Web03 | 2.8.140721.1 | Last Updated 19 Aug 2013
Article Copyright 2013 by Prabu ram
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid