How to use wkhtmltopdf Rotativa ViewAsPdf in Blazor Server

176 Views Asked by At

I would like to use Rotativa.AspNetCore.ViewAsPdf("~/Views/MyView/PDF.cshtml", model) in Blazor Server the same way I do in regular ASP.NET CORE MVC apps.

  1. I installed the "Rotativa.AspNetCore" nuget in my Blazor server project in .NET 8

  2. Added RotativaConfiguration.Setup(app.Environment.WebRootPath); app.UseRotativa(); in Program.cs

  3. Created a "Views" folder with a PDF.cshtml view

  4. Created a Controller I am calling via httpClient from my razor component to generate the PDF

[HttpPost("exportPDF")]
public ActionResult ExportPDF(PDFModel model)
{

    return new Rotativa.AspNetCore.ViewAsPdf("~/Views/MyView/PDF.cshtml", model)
    {
        FileName = "MyFile" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".pdf",
        PageSize = Rotativa.AspNetCore.Options.Size.A4,
        PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait,
        PageMargins = { Left = 15, Right = 15, Top = 15 },
        CustomSwitches = "--footer-center \"MyDocument + "\" --footer-right \"Page: [page]/[toPage]\" --footer-font-size \"6\""
    };
}

And I am getting an "Object reference not set to an instance of an object." exception from the "Rotativa.AspNetCore" source.

Has anyone got this working in Blazor?

2

There are 2 best solutions below

0
Ondrej Sevcak On BEST ANSWER

I got it working by myself. It is totally possible to use rotativa.exe and Rotativa.AspNetCore nuget to generate PDFs in Blazor using the "ViewAsPdf" method. My initial setup was good and I added following two controller methods:

public async Task<FileResult> ReturnPDF(int modelId)
{
    PDFModel model = new PDFModel(); //or load from db

    byte[] pdfBytes = await GetPDFBytes(model);

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

which calls following that creates the pdf using rotativa:

public async Task<byte[]> GetPDFBytes(PDFModel model)
{

   var pdf =  new Rotativa.AspNetCore.ViewAsPdf("~/Views/PDF.cshtml", model)
   {
       FileName = "Export_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".pdf",
       PageSize = Rotativa.AspNetCore.Options.Size.A4,
       PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait,
       PageMargins = { Left = 15, Right = 15, Top = 15 },
       CustomSwitches = "--footer-center \"ID_" + model.Id + "\" --footer-right \"Page: [page]/[toPage]\" --footer-font-size \"6\""
};

   byte[] pdfBytes = await pdf.BuildFile(this.ControllerContext);
   return pdfBytes;

}

and calling it from .razor component via:

<a href="@(_navManager.BaseUri + "mypage/ReturnPDF")" class="btn btn-danger" target="_blank">PDF_TEST_FileResult</a>

I have also tried creating an API controller and send it a post request with whole PDF model, but the PDF never displayed in the browser, but got returned to the calling object in razor code.

3
Jason Pan On

Here is the official sample project.

It using window.triggerFileDownload to download the PDF files, we just need to invoke it like below.

<NavLink class="nav-link" @onclick="@( e => DownloadFileFromURL("pdf-view-name"))">

It works fine in my local, and here is the test result.

enter image description here

And the Program.cs file should like below.

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Rotativaio.AspNetCore;
using RotativaIoBlazorSample.Data;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();

var rotativaIoUrl = "https://eunorth.rotativa.io";
var rotativaApiKey = "18d28****c52d383bf53d24d"; 

builder.Services.AddRotativaIo(rotativaIoUrl, rotativaApiKey);

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.MapControllerRoute("mvc", "{controller}/{action}");

app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

Tips: You should register an account, it's important. Then use it like above.