How do I display a PDF using PdfSharp in ASP.Net MVC?
Asked Answered
S

2

9

We're making an ASP.Net MVC app that needs to be able to generate a PDF and display it to the screen or save it somewhere easy for the user to access. We're using PdfSharp to generate the document. Once it's finished, how do we let the user save the document or open it up in a reader? I'm especially confused because the PDF is generated server-side but we want it to show up client-side.


Here is the MVC controller to create the report that we have written so far:

public class ReportController : ApiController
{
    private static readonly string filename = "report.pdf";

    [HttpGet]
    public void GenerateReport()
    {
        ReportPdfInput input = new ReportPdfInput()
        {
            //Empty for now
        };

        var manager = new ReportPdfManagerFactory().GetReportPdfManager();
        var documentRenderer = manager.GenerateReport(input);
        documentRenderer.PdfDocument.Save(filename); //Returns a PdfDocumentRenderer
        Process.Start(filename);
    }
}

When this runs, I get an UnauthorizedAccessException at documentRenderer.PdfDocument.Save(filename); that says, Access to the path 'C:\Program Files (x86)\Common Files\Microsoft Shared\DevServer\10.0\report.pdf' is denied. I'm also not sure what will happen when the line Process.Start(filename); is executed.

This is the code in manager.GenerateReport(input):

public class ReportPdfManager : IReportPdfManager
{
    public PdfDocumentRenderer GenerateReport(ReportPdfInput input)
    {
        var document = CreateDocument(input);
        var renderer = new PdfDocumentRenderer(true, PdfSharp.Pdf.PdfFontEmbedding.Always);
        renderer.Document = document;
        renderer.RenderDocument();

        return renderer;
    }

    private Document CreateDocument(ReportPdfInput input)
    {
        //Put content into the document
    }
}
Seditious answered 27/2, 2013 at 20:36 Comment(0)
B
8

I'm not familar with PDF sharp but for MVC is mostly done via built in functionality. You need to get your pdf document represented as an array of bytes. Then you'd simply use MVC's File method to return it to the browser and let it handle the download. Are there any methods on their class to do that?

public class PdfDocumentController : Controller
{
    public ActionResult GenerateReport(ReportPdfInput input)
    {
        //Get document as byte[]
        byte[] documentData;

        return File(documentData, "application/pdf");
    }

}
Baecher answered 27/2, 2013 at 22:2 Comment(2)
There is a web sample that shows how to get the byte array and return it to the user without MVC. With MVC you only need the code to get the byte array (from the memory stream, no file required). Sample: pdfsharp.net/wiki/Clock-sample.ashxSidedress
For new users, it becomes a little confusing so would you(NickAlbrecht) bother to update the answer to do the exact thing like @PDFsharpTeam added an helper link. [ MemoryStream stream = new MemoryStream(); //// document.Save(stream, false); //// Byte[] documentBytes = stream.ToArray(); //// return File(documentBytes, "application/pdf"); ] (It helped me a lot. Thank You!!!)Jaime
S
13

Using Yarx's suggestion and PDFsharp Team's tutorial, this is the code we ended up with:

Controller:

[HttpGet]
public ActionResult GenerateReport(ReportPdfInput input)
{
    using (MemoryStream stream = new MemoryStream())
    {
        var manager = new ReportPdfManagerFactory().GetReportPdfManager();
        var document = manager.GenerateReport(input);
        document.Save(stream, false);
        return File(stream.ToArray(), "application/pdf");
    }
}

ReportPdfManager:

public PdfDocument GenerateReport(ReportPdfInput input)
{
    var document = CreateDocument(input);
    var renderer = new PdfDocumentRenderer(true,
        PdfSharp.Pdf.PdfFontEmbedding.Always);
    renderer.Document = document;
    renderer.RenderDocument();

    return renderer.PdfDocument;
}

private Document CreateDocument(ReportPdfInput input)
{
    //Creates a Document and puts content into it
}
Seditious answered 28/2, 2013 at 20:34 Comment(3)
FYI: The line document.Save(stream, false) takes the parameter false to indicate that stream should not be closed as a side-effect of calling Save. This behavior is necessary so we can call stream.ToArray in the next line, and so that the using block we used can work as expected.Seditious
I've downloaded and referenced the DLL but it says it can't find ReportPdfInput..?Elidiaelie
@Elidiaelie ReportPdfInput was a class we wrote that contained all the information necessary to render the PDF we wanted. It is not part of the library. Sorry for the confusion!Seditious
B
8

I'm not familar with PDF sharp but for MVC is mostly done via built in functionality. You need to get your pdf document represented as an array of bytes. Then you'd simply use MVC's File method to return it to the browser and let it handle the download. Are there any methods on their class to do that?

public class PdfDocumentController : Controller
{
    public ActionResult GenerateReport(ReportPdfInput input)
    {
        //Get document as byte[]
        byte[] documentData;

        return File(documentData, "application/pdf");
    }

}
Baecher answered 27/2, 2013 at 22:2 Comment(2)
There is a web sample that shows how to get the byte array and return it to the user without MVC. With MVC you only need the code to get the byte array (from the memory stream, no file required). Sample: pdfsharp.net/wiki/Clock-sample.ashxSidedress
For new users, it becomes a little confusing so would you(NickAlbrecht) bother to update the answer to do the exact thing like @PDFsharpTeam added an helper link. [ MemoryStream stream = new MemoryStream(); //// document.Save(stream, false); //// Byte[] documentBytes = stream.ToArray(); //// return File(documentBytes, "application/pdf"); ] (It helped me a lot. Thank You!!!)Jaime

© 2022 - 2024 — McMap. All rights reserved.