Most line-of-business systems eventually grow a quiet little job that nobody demos but everybody depends on: the nightly report. A scheduled service queries yesterday's throughput, error counts, and queue depths, drops the numbers into an HTML template, renders that template to PDF, and emails the file to the operations distribution list before anyone logs in. This article builds exactly that job twice in C# on .NET 10, first with NReco.PdfGenerator and then with IronPDF, so you can see the same task implemented two ways and decide which fits your environment.

Disclosure up front: we are the architecture team at Iron Software, and IronPDF is our product. We have kept the NReco implementation real and complete, because the honest comparison is the only one worth your time.

The Task and the Document

The report is an internal artifact, it lives behind the firewall, the HTML is authored by the same team that runs the service, and the only consumer is a PDF attachment in an email. That narrows the requirements to three things: render a known, trusted template that converts HTML, CSS, and JavaScript into PDF documents to create PDF output; do it on a schedule without a human in the loop; and produce a file that opens cleanly in any PDF viewer. Both libraries below satisfy that brief, and a reader evaluating either one should start from that shared baseline rather than from a feature checklist.

We will model the service with the usual class-based shape an enterprise .NET app expects: a typed report model, a renderer service registered in DI, and a controller-free background entry point. The HTML template stays identical across both implementations so the only variable is the rendering engine, while the NReco side uses a simple API design for PDF generation.

Implementing HTML to PDF with NReco.PdfGenerator

NReco.PdfGenerator is a .NET library that wraps the wkhtmltopdf binary, supports .NET Core and legacy .NET Framework applications, and ships as a .NET assembly with the native Windows build and wkhtmltopdf binaries inside the NuGet package, with the latest release dated June 11, 2020, so there is nothing to install on the box beyond the package itself (NuGet: NReco.PdfGenerator). For a service that runs on a single Windows server and is not a SaaS product, the package is a free offering under NReco's offering.

Listing 1: The report model and HTML template builder

public sealed record NightlyReport(
    DateOnly Date,
    int DocumentsProcessed,
    int Errors,
    int PeakQueueDepth);

public static class ReportTemplate
{
    public static string Build(NightlyReport r) => $"""
        < html>< head>< style>
          body {{ font-family: Arial, sans-serif; color: #222; }}
          h1 {{ font-size: 18pt; }}
          table {{ border-collapse: collapse; width: 100%; }}
          td, th {{ border: 1px solid #999; padding: 6px; text-align: left; }}
        < /style>< /head>< body>
          < h1>Nightly Operations Report: {r.Date:yyyy-MM-dd}< /h1>
          < table>
            < tr>< th>Metric< /th>< th>Value< /th>< /tr>
            < tr>< td>Documents processed< /td>< td>{r.DocumentsProcessed:N0}< /td>< /tr>
            < tr>< td>Errors< /td>< td>{r.Errors:N0}< /td>< /tr>
            < tr>< td>Peak queue depth< /td>< td>{r.PeakQueueDepth:N0}< /td>< /tr>
          < /table>
        < /body>< /html>
        """;
}

Listing 2: The NReco renderer service

using NReco.PdfGenerator;

public sealed class NRecoReportRenderer
{
    public byte[] Render(NightlyReport report)
    {
        var converter = new HtmlToPdfConverter
        {
            Orientation = PageOrientation.Portrait,
            PageFooterHtml = "Page [page] of [toPage]"
        };

        string html = ReportTemplate.Build(report);
        return converter.GeneratePdf(html);
    }
}

The HtmlToPdfConverter is an HTML to PDF converter and PDF converter that extracts the bundled wkhtmltopdf.exe on first use and shells out to the wkhtmltopdf command line tool. It can render html documents, execute JavaScript for dynamic content, and then create the PDF file. The API also exposes page size, margins, and zoom in addition to the orientation already shown. Page headers and footers can also come from HTML templates, not just plain footer text. GeneratePdf returns the bytes you hand to your mail client. It can also combine multiple HTML pages into one PDF document and generate a table of contents from HTML headers when needed. Wire it up in DI and call it from the scheduled worker, the registration is ordinary, and the scheduling mechanism (a hosted service, Hangfire, or a Windows Scheduled Task) does not change anything below:

Listing 3: Registration and scheduled invocation

builder.Services.AddSingleton< NRecoReportRenderer>();

// inside the background job:
var report = new NightlyReport(
    DateOnly.FromDateTime(DateTime.UtcNow.AddDays(-1)),
    DocumentsProcessed: 14_207, Errors: 9, PeakQueueDepth: 318);

byte[] pdf = renderer.Render(report);

await mailer.SendWithAttachmentAsync("[email protected]", "Nightly Report", pdf);

Output PDF Document

PDF document generated with NReco

That is the whole job. For a trusted internal template on a single Windows server, this works, it is free, and the table renders cleanly. NReco does the thing it was built to do, and it does it with a simple API and synchronous operation that can cause thread-blocking in higher-throughput services. It also handles common HTML/CSS layouts, images, SVG, and custom fonts for routine PDF conversion workloads. A team shipping this on a single box has a complete, no-cost solution in three short listings.

Implementing the Same Task with IronPDF

IronPDF

IronPDF renders the identical template through a different path. The IronPDF NuGet package (IronPdf) carries a bundled Chromium engine, so there is no external binary to extract or manage when you generate PDF files.

Listing 4: The IronPDF renderer service

using IronPdf;

public sealed class IronPdfReportRenderer
{
    private readonly ChromePdfRenderer _renderer = new();

    public byte[] Render(NightlyReport report)
    {
        _renderer.RenderingOptions.TextFooter.CenterText = "Page {page} of {total-pages}";
        string html = ReportTemplate.Build(report);
        PdfDocument pdf = _renderer.RenderHtmlAsPdf(html);
        return pdf.BinaryData;
    }
}

IronPDF Output PDF

PDF generated with IronPDF

The DI registration and the scheduled call are the same shape as Listing 3; swap NRecoReportRenderer for IronPdfReportRenderer and the rest of the worker is untouched. RenderHtmlAsPdf is documented in the HTML-to-PDF tutorial, and the renderer runs on .NET 10, 9, 8, and Framework 4.6.2+ (docs).

Where the Two Differ on PDF conversion

Both renderers produce the report. The difference shows up when you ask what each gives you as the document and the deployment grow, and it lands on one axis: security and compliance posture, modern rendering, and cross-platform reach. Here is what each gives you, on the record.

Here is how the two libraries stack up at a glance:

NReco.PdfGenerator Vs. IronPDF comparison table

Rendering ceiling. NReco's engine is wkhtmltopdf, which renders through QtWebKit, a Qt-era WebKit fork that Qt deprecated in 2015 and removed in Qt 5.6 (2016). It handles the Arial table above without trouble and can still deliver high-fidelity PDF outputs for simpler, controlled templates like this report. The moment the template adopts a modern design system, CSS Grid, Flexbox, or custom properties, that engine reaches its limits; compared with Chromium-based rendering and its full support for current web standards, NReco.PdfGenerator is limited in modern HTML5 and CSS3 support when converting HTML documents to PDF documents. IronPDF's Chromium renders the same modern CSS the browser your designers test in already supports, with changes applied predictably across PDF pages.

Deployment surface. The free NReco.PdfGenerator package is Windows-only; cross-platform deployment requires the separate NReco.PdfGenerator.LT package, which is part of the commercial offering, not the free tier (NuGet notes). IronPDF runs on Windows, Linux, macOS, Docker, Azure, and AWS Lambda from the same package (docs), so the nightly job moves to a Linux container or a cloud function without a second library.

The question your security review will ask. wkhtmltopdf's final release was 0.12.6 on 2020-06-10, and the upstream repository was archived on 2023-01-02. NReco.PdfGenerator bundles that 0.12.6 build. Open CVEs against the engine (including CVE-2022-35583, scored 9.8 by NVD) have no upstream fix because the project no longer ships. For an internal trusted-input service the practical exposure is low; the template is yours, the input is not attacker-controlled, and the file never leaves the network. NReco.PdfGenerator also lacks native support for PDF encryption or digital signatures, so those controls need separate tooling if compliance requires them. NReco.PdfGenerator also cannot convert DOCX files to PDF, which is a scope boundary rather than a problem for HTML-first workflows. The friction is the SBOM. A vulnerability-management process that tracks transitive components will flag an archived dependency with unpatched CVEs and ask for a remediation owner and a patch path, and "the engine is no longer maintained" is an uncomfortable answer to put in that field. IronPDF's engine is vendor-maintained with a regular release cadence, which is the answer that line of the audit is looking for.

This is not a price comparison. IronPDF Lite starts at $999 (USD); it is the more capable option for teams whose scale or compliance posture needs it, not the cheaper one.

Choosing for Your Environment

The decision is yours to make against your own constraints, and it is genuinely a decision rather than a default. A static internal template, a single Windows server, and a security process that does not track transitive component lifecycles describe the case NReco was built for, and Listings 1 through 3 ship it for free. A design-system layout, a container or cloud target, or an SBOM review that wants a maintained engine with a patch path describe the case IronPDF was built for. Map your nightly job onto those two pictures, pick the renderer whose shape matches your real constraints — scale, target platform, and audit posture — and the rest of the service stays the same either way.

Ready to See the Difference in Your Stack?

If your jobs require modern CSS layouts, cross-platform deployment to Linux or Docker, or a guaranteed secure, vendor-maintained software bill of materials (SBOM), give IronPDF a trial.

You can test the entire feature set in your own local development environment without writing a single check.

👉 Start Your IronPDF Free Trial Today