How I built the first PDF report for KlipTok using IronPDF

An important goal for me in building the KlipTok web application is to be able to deliver reports that can be downloaded and referenced by streamers and their support teams to help them learn how to grow their online presence.  I investigated a few tools and landed on IronPDF and started building an initial and simple report showing the dashboard content from KlipTok.  In this post, I’m going to show you how I took a Blazor Web Assembly page and re-used it so that the content could be printed with IronPDF.

Preparing the ASP.NET Core site to run Blazor

KlipTok runs as an Azure Static Website with a series of Azure Functions to support it.  While it is possible to run IronPDF on Azure Functions applications, in order to use and generate the a report based on the dashboard that is already present on KlipTok I would need to run Blazor content on a server.  Fortunately, I already have an ASP.NET Core website running on a Linux-based service with other features of KlipTok using Razor Pages.  With a server-side Blazor component, I could easily re-use this dashboard user-interface from the KlipTok front-end application.

Our architecture strategy will be to configure the existing ASP.NET Core website to run Blazor-Server pages that host the same content as appears in the Blazor-WebAssembly application that users typically interact with.  We will add a Minimal-API feature that will trigger IronPDF to render the HTML output of the new Blazor-Server dashboard page as a PDF and return that PDF to the user.

I started by adding Blazor-Server configuration to my existing ASP.NET Core by updating the Program.cs file to add services for Blazor Server:

builder.Services.AddServerSideBlazor();
builder.Services.AddTelerikBlazor();
...
app.MapBlazorHub();
...
// Listing to indicate relative position of the MapFallbackToPage statement
app.UseEndpoints(endpoints =>
{
  endpoints.MapRazorPages();
});
app.MapFallbackToPage("/_Host");

app.Run();

With this added to the website configuration, ASP.NET Core now knows how to work with Blazor content on the server.  I then brought over some Blazor files to run on the server.  This included:

  • a Shared folder with the Blazor page layout “MainLayout.razor”
  • _Imports.razor
  • App.razor
  • Pages/_Layout.cshtml to contain the HTML that would host the running Blazor application
  • I also created a ‘Blazor’ folder to contain the reports and content that I would build with server-side Blazor.

Solution Explorer with New Folders

Adding the Streamer Dashboard report content

Dashboard for the CSharpFritz channel

The Streamer Dashboard is a tab inside the Streamer page on KlipTok, and not currently managed in an isolated manner.  All of the code to render this content and interact with the data repository are mixed in to the larger Streamer page.  Yes, I have some spaghetti code to unwind and deploy. In this case, it wasn’t too bad as I was able to isolate the markup that made up the inside of the Dashboard and migrate it to StreamerDashboard.razor, and you can see it in the previous image of my Solution Explorer above.

I updated the path and dependencies that were injected to use server-side interactions with the datastore instead of HTTP fetch operations to Azure Function endpoints.

@page "/app/streamerdashboard/{DisplayName}"
@inject IKlipRepository Repo
@inject IChannelRepository ChannelRepo
...
@code {
  public StreamerRecord StreamerRecord { get; set; }

  protected override async Task OnInitializedAsync()
  {

    StreamerRecord = StreamerRecord ?? await Repo.GetChannelSummary(DisplayName, true, false);

  }
}

With this change, my StreamerDashboard.razor file could render HTML at `/app/streamerfashboard/csharpfritz` or similar location based on the Display Name of the Twitch channel sought.  Very cool

I also updated the razor Pages/_Layout.cshtml file to contain less flashy formatting and force a ‘light theme’ for the rendering of content.  For printing to a PDF and a piece of paper, we would want the lighter theme to ensure all content is visible when printed.

Adding the Report Features with IronPDF

I next put all of the configuration for IronPDF into a file I called ReportsExtensions.cs (you can see it in the Solution Explorer image above).  This file contains a single method that isolates all of the configuration for IronPDF and the reports that we will enable on the website.  The source of this file is as follows:

public static WebApplication MapKlipTokReports(this WebApplication app, IWebHostEnvironment host)
{

// Configure IronPDF rendering at startup
AppContext.SetSwitch("System.Drawing.EnableUnixSupport", true);
IronPdf.License.LicenseKey = app.Configuration["IronPdfKey"];
IronPdf.Installation.TempFolderPath = $@"{host.ContentRootPath}/irontemp/";
IronPdf.Installation.Initialize();
IronPdf.Installation.LinuxAndDockerDependenciesAutoConfig = true;
var Renderer = new ChromePdfRenderer();

// Warm up the renderer with simple HTML content
using var PDF = Renderer.RenderHtmlAsPdf("<h2>Hello World<h1>");

// Map the endpoint the report creator will listen to
app.MapGet("/reports/StreamerDashboard/{channel}", 
async (HttpContext ctx, string channel) =>
{

var url = ctx.Request.GetDisplayUrl();
url = url.Substring(0, url.IndexOf("/reports"));

// Format the page
var ironPdfRender = new IronPdf.ChromePdfRenderer();
ironPdfRender.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;
ironPdfRender.RenderingOptions.RenderDelay = 2500;
ironPdfRender.RenderingOptions.ViewPortWidth = 1080;
ironPdfRender.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Screen;
ironPdfRender.RenderingOptions.MarginTop = 10;
ironPdfRender.RenderingOptions.MarginLeft = 10;
ironPdfRender.RenderingOptions.MarginRight = 10;
ironPdfRender.RenderingOptions.MarginBottom = 10;
ironPdfRender.RenderingOptions.TextFooter = new TextHeaderFooter
{
RightText = $"As of {DateTime.UtcNow.ToString()} "
};
ironPdfRender.RenderingOptions.UseMarginsOnHeaderAndFooter = UseMargins.Bottom;
ironPdfRender.RenderingOptions.Title = $"Dashboard for Twitch.tv/{channel}";
ironPdfRender.RenderingOptions.FitToPaperMode = IronPdf.Engines.Chrome.FitToPaperModes.AutomaticFit;

// Instruct IronPDF to load the HTML from the Blazor Dashboard page
var pdf = await ironPdfRender.RenderUrlAsPdfAsync($"{url}/app/StreamerDashboard/{channel}");

// Set the Http Context and return the PDF
ctx.Response.ContentType = "application/pdf";
ctx.Response.Headers.Add("Content-Disposition", $"filename={channel.ToLowerInvariant()}.pdf");
await ctx.Response.BodyWriter.WriteAsync(pdf.Stream.ToArray());

});

return app;

}

This is a great little method that shows how you can isolate business processes that configure various endpoints for APIs in your web application.  In this case, we extended the WebApplication object with this static method so that our Program.cs can reference this with a very readable command like:

app.MapKlipTokReports(app.Environment);

The configuration for IronPDF at the top of the MapKlipTokReports method grabs a license key from the server configuration and activates Linux-based rendering for this application.  Additionally, there is a request to warm-up the PDF renderer with a simple bit of HTML that is discarded after its rendered.

The API address for this report generator is defined in the app.MapGet command.  It’s listening on /reports/StreamerDashboard and captures the last bit of the directories requested and converts that to a Twitch channel name that will be sought for the report.

The renderer is then configured with the information about the destination page size, headers and footers to be added.  I placed a nice ‘As Of’ timestamp in the footer of all pages rendered by using the TextFooter property and added a title using the Title property of the renderer.  Finally, the PDF is rendered with a call to the appropriate /api/StreamerDashboard/channelName location and returned as a stream with the appropriate application/pdf content type.

Now that I have the simple configuration for IronPDF built, I can evolve this method in the future so that the IronPDF rendering capabilities are isolated in their own method and my new reports are built to inject the URL of the page to render.  The configuration and presentation of this content is great, and you can check out a sample instance of this report:

Sample PDF report

Wrap-up

I added a ‘Print’ button to the dashboard page of KlipTok that opens a new tab in the browser and links to this report generated by my ASP.NET Core server and IronPDF.  This has been a great experience to build and generate a simple PDF that can be printed and shared with my stream promotion team.  I’ve got a few more ideas that I want to try with IronPDF and will share another blog post in a few days as I add some more advanced PDF features to this report.

What do you think?  Would you use a tool like IronPDF to build PDF exports for your application?