Rectangle 27 9

I have created a special ViewResult class that you can return as the result of an Action.

You can see the code on bitbucket (look at the PdfFromHtmlResult class).

So what it basically does is:

  • Render the view through the Razor engine (or any other registered engine) to Html
  • return the pdf as the ViewResult (with correct mimetype, etc).
public class PdfFromHtmlResult : ViewResult {

    public override void ExecuteResult(ControllerContext context) {
        if (context == null) {
            throw new ArgumentNullException("context");
        }
        if (string.IsNullOrEmpty(this.ViewName)) {
            this.ViewName = context.RouteData.GetRequiredString("action");
        }

        if (this.View == null) {
            this.View = this.FindView(context).View;
        }

        // First get the html from the Html view
        using (var writer = new StringWriter()) {
            var vwContext = new ViewContext(context, this.View, this.ViewData, this.TempData, writer);
            this.View.Render(vwContext, writer);

            // Convert to pdf

            var response = context.HttpContext.Response;

            using (var pdfStream = new MemoryStream()) {
                var pdfDoc = new Document(); 
                var pdfWriter = PdfWriter.GetInstance(pdfDoc, pdfStream);

                pdfDoc.Open();

                using (var htmlRdr = new StringReader(writer.ToString())) {

                    var parsed = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(htmlRdr, null);

                    foreach (var parsedElement in parsed) {
                        pdfDoc.Add(parsedElement);
                    }
                }

                pdfDoc.Close();

                response.ContentType = "application/pdf";
                response.AddHeader("Content-Disposition", this.ViewName + ".pdf");
                byte[] pdfBytes = pdfStream.ToArray();
                response.OutputStream.Write(pdfBytes, 0, pdfBytes.Length);
            }
        }
     }
 }

With the correct extension methods (see BitBucket), etc, the code in my controller is something like:

public ActionResult MyPdf(int id) {
       var myModel = findDataWithID(id);

       // this assumes there is a MyPdf.cshtml/MyPdf.aspx as the view
       return this.PdfFromHtml(myModel);
 }

Note: Your method does not work, because you will retrieve the Html on the server, thereby you loose all cookies (=session information) that are stored on the client.

would this work with a view not created using the Razor engine?

I didn't test without razor, but I also don't reference Razor. I expect that the ViewContext is intelligent enough to use another renderer when needed.

Ok, i'll give it a shot...I'm getting a compile error "Cannot implicitly convert iTextSharp.text.pdf.PdfWriter to System.IDisposable" on these 2 lines: using (var pdfDoc = new Document()) using (var pdfWriter = PdfWriter.GetInstance(pdfDoc, pdfStream))

Strange, maybe, you have another iTextSharp version? I'll change the code example to not use the using, since pdfDoc.Close is explicitly called, they are not 100% needed, just nicer.

Ok, great! One last issue: return this.PdfFromHtml(myModel); doesn't seem to work for some reason :( It doesn't resolve PdfFromHtml, i've got all references, using itextxharp 4.1.6, MyPdf in my case is an ascx or partial view...any ideas?

asp.net mvc 3 - Convert PartialView Html to String for ITextSharp Html...

asp.net-mvc-3 pdf itextsharp mvchtmlstring
Rectangle 27 3

I know this question is old but I thought I would share this as I could not find anything similar.

I wanted to create my views/models as normal using Razor and have them rendered as Pdfs.

This way I had control over the pdf presentation using standard html output rather than figuring out how to layout the document using iTextSharp.

The project and source code is available here with nuget installation instructions:

Install-Package MvcRazorToPdf

c# - How to return PDF to browser in MVC? - Stack Overflow

c# asp.net asp.net-mvc pdf itextsharp
Rectangle 27 3

I know this question is old but I thought I would share this as I could not find anything similar.

I wanted to create my views/models as normal using Razor and have them rendered as Pdfs.

This way I had control over the pdf presentation using standard html output rather than figuring out how to layout the document using iTextSharp.

The project and source code is available here with nuget installation instructions:

Install-Package MvcRazorToPdf

c# - How to return PDF to browser in MVC? - Stack Overflow

c# asp.net asp.net-mvc pdf itextsharp
Rectangle 27 118

First, HTML and PDF are not related although they were created around the same time. HTML is intended to convey higher level information such as paragraphs and tables. Although there are methods to control it, it is ultimately up to the browser to draw these higher level concepts. PDF is intended to convey documents and the documents must "look" the same wherever they are rendered.

In an HTML document you might have a paragraph that's 100% wide and depending on the width of your monitor it might take 2 lines or 10 lines and when you print it it might be 7 lines and when you look at it on your phone it might take 20 lines. A PDF file, however, must be independent of the rendering device, so regardless of your screen size it must always render exactly the same.

Because of the musts above, PDF doesn't support abstract things like "tables" or "paragraphs". There are three basic things that PDF supports: text, lines/shapes and images. (There are other things like annotations and movies but I'm trying to keep it simple here.) In a PDF you don't say "here's a paragraph, browser do your thing!". Instead you say, "draw this text at this exact X,Y location using this exact font and don't worry, I've previously calculated the width of the text so I know it will all fit on this line". You also don't say "here's a table" but instead you say "draw this text at this exact location and then draw a rectangle at this other exact location that I've previously calculated so I know it will appear to be around the text".

Second, iText and iTextSharp parse HTML and CSS. That's it. ASP.Net, MVC, Razor, Struts, Spring, etc, are all HTML frameworks but iText/iTextSharp is 100% unaware of them. Same with DataGridViews, Repeaters, Templates, Views, etc. which are all framework-specific abstractions. It is your responsibility to get the HTML from your choice of framework, iText won't help you. If you get an exception saying The document has no pages or you think that "iText isn't parsing my HTML" it is almost definite that you don't actually have HTML, you only think you do.

Third, the built-in class that's been around for years is the HTMLWorker however this has been replaced with XMLWorker (Java / .Net). Zero work is being done on HTMLWorker which doesn't support CSS files and has only limited support for the most basic CSS properties and actually breaks on certain tags. If you do not see the HTML attribute or CSS property and value in this file then it probably isn't supported by HTMLWorker. XMLWorker can be more complicated sometimes but those complications also make it more extensible.

Below is C# code that shows how to parse HTML tags into iText abstractions that get automatically added to the document that you are working on. C# and Java are very similar so it should be relatively easy to convert this. Example #1 uses the built-in HTMLWorker to parse the HTML string. Since only inline styles are supported the class="headline" gets ignored but everything else should actually work. Example #2 is the same as the first except it uses XMLWorker instead. Example #3 also parses the simple CSS example.

//Create a byte array that will eventually hold our final PDF
Byte[] bytes;

//Boilerplate iTextSharp setup here
//Create a stream that we can write to, in this case a MemoryStream
using (var ms = new MemoryStream()) {

    //Create an iTextSharp Document which is an abstraction of a PDF but **NOT** a PDF
    using (var doc = new Document()) {

        //Create a writer that's bound to our PDF abstraction and our stream
        using (var writer = PdfWriter.GetInstance(doc, ms)) {

            //Open the document for writing
            doc.Open();

            //Our sample HTML and CSS
            var example_html = @"<p>This <em>is </em><span class=""headline"" style=""text-decoration: underline;"">some</span> <strong>sample <em> text</em></strong><span style=""color: red;"">!!!</span></p>";
            var example_css = @".headline{font-size:200%}";

            /**************************************************
             * Example #1                                     *
             *                                                *
             * Use the built-in HTMLWorker to parse the HTML. *
             * Only inline CSS is supported.                  *
             * ************************************************/

            //Create a new HTMLWorker bound to our document
            using (var htmlWorker = new iTextSharp.text.html.simpleparser.HTMLWorker(doc)) {

                //HTMLWorker doesn't read a string directly but instead needs a TextReader (which StringReader subclasses)
                using (var sr = new StringReader(example_html)) {

                    //Parse the HTML
                    htmlWorker.Parse(sr);
                }
            }

            /**************************************************
             * Example #2                                     *
             *                                                *
             * Use the XMLWorker to parse the HTML.           *
             * Only inline CSS and absolutely linked          *
             * CSS is supported                               *
             * ************************************************/

            //XMLWorker also reads from a TextReader and not directly from a string
            using (var srHtml = new StringReader(example_html)) {

                //Parse the HTML
                iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml);
            }

            /**************************************************
             * Example #3                                     *
             *                                                *
             * Use the XMLWorker to parse HTML and CSS        *
             * ************************************************/

            //In order to read CSS as a string we need to switch to a different constructor
            //that takes Streams instead of TextReaders.
            //Below we convert the strings into UTF8 byte array and wrap those in MemoryStreams
            using (var msCss = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_css))) {
                using (var msHtml = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_html))) {

                    //Parse the HTML
                    iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msHtml, msCss);
                }
            }


            doc.Close();
        }
    }

    //After all of the PDF "stuff" above is done and closed but **before** we
    //close the MemoryStream, grab all of the active bytes from the stream
    bytes = ms.ToArray();
}

//Now we just need to do something with those bytes.
//Here I'm writing them to disk but if you were in ASP.Net you might Response.BinaryWrite() them.
//You could also write the bytes to a database in a varbinary() column (but please don't) or you
//could pass them to another function for further PDF processing.
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
System.IO.File.WriteAllBytes(testFile, bytes);

There are good news for HTML-to-PDF demands. As this answer showed, the W3C standard css-break-3 will solve the problem... It is a Candidate Recommendation with plan to turn into definitive Recommendation this year, after tests.

As not-so-standard there are solutions, with plugins for C#, as showed by print-css.rocks.

The code declares a "new Document()" and comments that this Document type is an "iTextSharp Document." This reference should be namespaced completely as "iTextSharp.text.Document()". The project where I'm using iTextSharp already had a Document class and I had to dig through the iTextSharp namespace to correct the reference.

the line with "iTextSharp.text.html.simpleparser.HTMLWorker(doc))" says 'htmlWorker' is obsolete with 5.5.10. What should this be changed to?

iTextSharp.tool
iTextSharp.text.html.simpleparser.HTMLWorker(doc)) is obsolete

c# - How to convert HTML to PDF using iTextSharp - Stack Overflow

c# pdf-generation itextsharp xmlworker
Rectangle 27 0

Here is how you implement this solution using the Razor engine NOT with the weird <itext.. markup.

This way you have full control over the pdf presentation using standard html output.

The project with an example solution and source code is available here with nuget installation instructions:

Install-Package MvcRazorToPdf

This also uses the new itextsharp licence, so does not suffer from any of the negatives mentioned in the other answers.

Man, you rock, thanks. Can i change the page orientation somehow?

@EdgarSalazar No problem. As it uses the iTextXmlWorker underneath, I think you should be able to resolve this by styling a div to your landscape proportions.

And how am i supposed to do that? I'm lost man.

does it work well with tables?

asp.net - Convert HTML to PDF in MVC with iTextSharp in MVC Razor - St...

asp.net asp.net-mvc asp.net-mvc-4 itextsharp html-to-pdf
Rectangle 27 0

here you can find a different approach in case you want to write plain xml, i find it much simpler and lighter.

asp.net - Convert HTML to PDF in MVC with iTextSharp in MVC Razor - St...

asp.net asp.net-mvc asp.net-mvc-4 itextsharp html-to-pdf
Rectangle 27 0

You can use it for very basic html to pdf, but even their site says that the xml worker is really meant to be a template system. itext functionality comparison. It really has no support for advanced layouts, etc... I ran up against this recently on a project that I'm part of and why I started investigating different tools such as the one below.

If you have the ability to use a different tool, you could try using a library like TuesPechkin which is a .net wrapper for wkhtmltopdf. Wkhtmltopdf uses the QT Webkit rendering engine and has robust support for html5/css3.

css - itextsharp "razor to html" works fine but "to pdf" ignores style...

html css asp.net-mvc razor itextsharp
Rectangle 27 0

There's a detailed and step-by-step tutorial on CodeProject you might follow. It illustrates how you could serve an ASP.NET MVC View as PDF file using iTextSharp for the conversion. Bear in mind though that iTextSharp was not meant for converting HTML to PDF so it might not cope very well with complex HTML pages and CSS styles.

I want to know that if iTextSharp was not meant for converting HTML to PDF, which one with free source?

asp.net - Convert HTML to PDF in MVC with iTextSharp in MVC Razor - St...

asp.net asp.net-mvc asp.net-mvc-4 itextsharp html-to-pdf
Rectangle 27 0

Hi Rosdi Kasim. Appearantly the latest iTextSharp version (5.4.4) is not working properly with RazorPDF and has rendered it useless.

@real_yggdrasil Be careful.. latest iTextSharp (starting from 5.x) has different license. Also 'rendered useless' is not helpful.. try submit your question with some example or detailed description..

I disagree. It has been rendered useless in that it does nothing and has not been updated since 2012.

asp.net - Convert HTML to PDF in MVC with iTextSharp in MVC Razor - St...

asp.net asp.net-mvc asp.net-mvc-4 itextsharp html-to-pdf
Rectangle 27 0

public virtual void printpdf(string html)    
{
     String htmlText = html.ToString();
     Document document = new Document();
     string filePath = HostingEnvironment.MapPath("~/Content/Pdf/");
     PdfWriter.GetInstance(document, new FileStream(filePath + "\\pdf-"+Filename+".pdf", FileMode.Create));

     document.Open();    
     iTextSharp.text.html.simpleparser.HTMLWorker hw = new iTextSharp.text.html.simpleparser.HTMLWorker(document);       
     hw.Parse(new StringReader(htmlText));    
     document.Close();    
}

just pass html string in to parameter that string you will get by renderpartialview text = viewname....

asp.net - Convert HTML to PDF in MVC with iTextSharp in MVC Razor - St...

asp.net asp.net-mvc asp.net-mvc-4 itextsharp html-to-pdf