Come eseguire il rendering di una vista MVC ASP.NET in formato PDF

Sto lavorando con l’utilità di conversione Html-to-PDF di ExpertPDF per questa domanda (anche se sono aperto ad altre librerie se c’è una documentazione sufficiente).

In breve, ho una vista che è formattata in un modo specifico e mi piacerebbe renderla come un documento PDF che l’utente può salvare su disco.

Quello che ho finora è un PrintService (che implementa un’interfaccia IPrintService) e questa implementazione ha due overload per PrintToPDF (), uno che prende solo un URL e un altro che accetta una stringa HTML, ed entrambi restituiscono un byte []. Ho solo elaborato i dettagli del secondo overload che richiede la stringa HTML.

Quello che mi piacerebbe fare dal mio controller è qualcosa come:

public FileStreamResult Print(int id) { var model = _CustomRepository.Get(id); string renderedView = SomethingThatRendersMyViewAsAString(model); Stream byteStream = _PrintService.PrintToPdf(renderedView); HttpContext.Response.AddHeader("content-disposition", "attachment; filename=report.pdf"); return new FileStreamResult(byteStream, "application/pdf"); } 

che in teoria renderebbe un PDF alla pagina. È il “SomethingThatRendersMyViewAsAString” con cui cerco aiuto. C’è un modo rapido per ottenere la rappresentazione della stringa di una vista? O forse dovrei limitarmi a sovraccaricare l’URL e passare un URL alla vista … Qualche altra idea?

Grazie!

È ansible accedere alla risposta durante OnResultExecuting e sostituire la proprietà Filter con qualcosa che memorizza l’HTML risultante in un MemoryStream. Quindi è ansible cancellare la risposta durante OnResultExecuted e sostituirla con i risultati della conversione PDF. Non sono sicuro che sarebbe meglio che ottenere il codice HTML dall’URL, comunque.

  public FileStreamResult Print(int id) { var model = _CustomRepository.Get(id); this.ConvertToPDF = true; return View( "HtmlView" ); } public override OnResultExecuting( ResultExecutingContext context ) { if (this.ConvertToPDF) { this.PDFStream = new MemoryStream(); context.HttpContext.Response.Filter = new PDFStreamFilter( this.PDFStream ); } } public override OnResultExecuted( ResultExecutedContext context ) { if (this.ConvertToPDF) { context.HttpContext.Response.Clear(); this.PDFStream.Seek( 0, SeekOrigin.Begin ); Stream byteStream = _PrintService.PrintToPDF( this.PDFStream ); StreamReader reader = new StreamReader( byteStream ); context.HttpContext.Response.AddHeader( "content-disposition", "attachment; filename=report.pdf" ); context.HttpContext.Response.AddHeader( "content-type", "application/pdf" ); context.HttpContext.Response.Write( reader.ReadToEnd() ); } } 

Il PDFStreamFilter dovrebbe sostituire i metodi “Write” e inviare i dati allo stream di memoria.

Ho confezionato la mia soluzione in un pacchetto Nuget: Rotativa http://nuget.org/packages/Rotativa . È basato su wkhtmltopdf.

L’utilizzo è davvero semplice.

Avere un’azione che vorresti servire come Pdf, invece della pagina Html. È ansible definire un’azione che restituisca un ActionResult del tipo ActionAsPdf (anche RouteAsPdf è disponibile). Quindi il codice è solo:

 public ActionResult PrintIndex() { return new ActionAsPdf("Index", new { name = "Giorgio" }) { FileName = "Test.pdf" }; } 

Con nome = “Giorgio” è un parametro di percorso.

Funziona anche se l’azione da stampare è protetta dall’autenticazione dei moduli Web (attributo [Autorizza])

Sembra un problema simile a quello in cui volevo utilizzare Views come modelli di email. La migliore risposta che ho trovato per ottenere la rappresentazione in formato stringa di una vista era qui: Renderizza una vista come una stringa

Il miglior pacchetto che ho trovato è RazorPDF , disponibile come pacchetto su NuGet.org, basato su iTextSharp . Funziona su siti Web di Azure:

https://nuget.org/packages/RazorPDF