How to Convert HTML to PDF with Winnovative in C#
Convert HTML strings or web URLs to PDF in C# with Winnovative, including ASP.NET Core, deployment, troubleshooting, and ScreenshotNeo.
Short answer: install the Winnovative generation that matches your operating system, create an HtmlToPdfConverter, convert an HTML string or URL, then save the returned bytes or file. Winnovative Classic and PDF Next use different packages, namespaces, runtime files, and rendering engines, so choose one before copying code.
1. Choose Classic or PDF Next
| Decision | Classic | PDF Next |
|---|---|---|
| Namespace | Winnovative |
Winnovative.Pdf.Next |
| Package scope | Windows package with a .NET Standard assembly | Platform-specific packages for Windows, Linux, and macOS/ARM variants |
| Rendering notes | Use the Classic documentation for Classic behavior | Documentation describes a bundled Chromium engine with HTML5, CSS3, JavaScript, web fonts, and SVG support |
| Async API | Reviewed examples are synchronous | Async methods follow TAP and can accept cancellation tokens |
| Deployment | NuGet brings dependencies; include the required wnvinternal.dat resource |
Native runtime packages are platform-specific; Linux may require system dependencies |
These distinctions come from the Winnovative package and product documentation. Do not transfer PDF Next rendering or platform claims to Classic.
2. Install Winnovative Classic
The NuGet listing currently shows version 20.0.2. Check the package listing for the version available when you publish.
dotnet add package Winnovative.HtmlToPdf --version 20.0.2
NuGet is the recommended installation route for the .NET Standard assembly because it brings in dependencies. If you deploy manually, make sure the package’s required wnvinternal.dat conversion resource is present in the published output.
3. Convert an HTML string to a PDF file
using Winnovative;
var converter = new HtmlToPdfConverter();
string html = "<h1>Hello, PDF</h1><p>Generated from C#.</p>";
byte[] pdfBytes = converter.ConvertHtml(html, null);
File.WriteAllBytes("output.pdf", pdfBytes);
The second argument is the base URL in the vendor’s HTML-string example. Supply a suitable base URL when your HTML uses relative stylesheets, images, scripts, or fonts, then verify that those resources resolve from the production environment.
4. Convert a web URL directly
using Winnovative;
var converter = new HtmlToPdfConverter();
converter.ConvertUrlToFile("https://example.com", "page.pdf");
The deployed server must be able to reach the URL. Test redirects, authentication, external assets, and JavaScript-dependent content from the same network environment used in production.
5. Return a PDF from ASP.NET Core
using Microsoft.AspNetCore.Mvc;
using Winnovative;
public class ReportsController : Controller
{
[HttpGet("reports/invoice.pdf")]
public IActionResult DownloadPdf()
{
var converter = new HtmlToPdfConverter();
byte[] pdfBytes = converter.ConvertHtml(
"<h1>Invoice</h1><p>Amount due: $125.00</p>",
null);
return File(pdfBytes, "application/pdf", "invoice.pdf");
}
}
For larger documents, keep conversion work bounded and apply your application’s normal cancellation and error-handling policy. The reviewed Classic examples are synchronous.
6. Build HTML that converts reliably
Use an explicit base URL
Relative references such as css/site.css or images/logo.png need a resolvable base. Without one, the converter may produce a PDF with missing styles or images.
using Winnovative;
var converter = new HtmlToPdfConverter();
var html = "<html><head><link rel=\"stylesheet\" href=\"css/site.css\"></head>" +
"<body><h1>Report</h1><img src=\"images/chart.png\"></body></html>";
byte[] pdf = converter.ConvertHtml(html, "https://reports.example/");
File.WriteAllBytes("report.pdf", pdf);
Make resources available to the converter
- Use absolute HTTPS URLs or a correct base URL.
- Ensure the conversion host can resolve DNS and establish outbound connections.
- Check that protected assets do not require browser-only authentication state.
- Use representative fonts, SVGs, images, and long tables during acceptance testing.
Plan for pagination
Validate page size, margins, headers, footers, page breaks, and table behavior with real documents. The reviewed sources establish conversion APIs but do not provide a complete reference for every layout property, so consult the generation-specific Winnovative documentation for the exact setting names.
7. PDF Next: when to use it and how the API differs
Choose PDF Next when your deployment requires the documented Windows, Linux, or macOS/ARM packages, or when you need the documented Chromium-based rendering and asynchronous methods. Install the platform-specific PDF Next package for your operating system and architecture, then use its Winnovative.Pdf.Next namespace. Package names and native runtime files vary by target; follow the product’s package instructions rather than substituting Classic assemblies.
// Shape of the PDF Next workflow (use the package and exact type for your target)
using Winnovative.Pdf.Next;
var converter = new HtmlToPdfConverter();
// PDF Next provides synchronous and Async variants.
// Use the exact overload documented for your installed package.
// byte[] pdf = await converter.ConvertHtmlAsync(html, cancellationToken);
PDF Next documents TAP-style async overloads and optional cancellation tokens. That API does not by itself establish a safe concurrency level or throughput figure; measure with your document sizes and hosting limits.
8. Linux and container deployment checklist
- Confirm the PDF Next package matches Linux distribution, CPU architecture, and .NET target.
- Use Winnovative’s publish guidance for native runtime files.
- Install any Linux system dependencies required by your exact distribution and image.
- Run a conversion inside the final container image, not only on a development workstation.
- Verify writable output paths, outbound network access, fonts, certificates, and resource URLs.
System dependencies can vary by distribution and version. Treat the real deployment image as the compatibility test.
9. Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| Missing styles or images | Relative URLs have no usable base URL | Pass the correct base URL or use absolute resource URLs; verify network access. |
| Conversion type cannot be found | Classic and PDF Next packages or namespaces were mixed | Use Winnovative for Classic and Winnovative.Pdf.Next for PDF Next. |
| Works locally, fails after publish | Native files or wnvinternal.dat were omitted |
Inspect publish output and copy required package resources. |
| Linux startup or native-load failure | Wrong runtime package or missing distribution dependencies | Install the platform-specific PDF Next package and required system libraries for the exact image. |
| Blank or incomplete URL PDF | Redirect, authentication, blocked asset, or JavaScript timing issue | Open the URL from the conversion host, check response paths and protected resources, and test a stable server-rendered version. |
| Request times out | Large page, slow external resource, or unbounded workload | Reduce input size, fix slow dependencies, bound concurrent jobs, and use cancellation where PDF Next exposes it. |
| Unexpected page breaks | Content was not tested against the selected paper and margins | Use print-specific CSS and test long tables, images, and headings with production-like data. |
10. Performance, reliability, and cost planning
- Performance: conversion time depends on HTML complexity, external resources, scripts, fonts, and page count. The reviewed sources provide no independent throughput benchmark.
- Reliability: make inputs deterministic where possible, self-host critical assets, record conversion failures, and retry only failures that are safe to repeat.
- Concurrency: PDF Next’s async methods help avoid blocking request threads, but choose concurrency limits from measurements in your environment.
- Memory: byte-array conversion keeps the whole PDF in memory. For large reports, use an output method or background job pattern supported by your selected generation.
- Licensing: the Classic NuGet listing summarizes a free evaluation and perpetual licenses for a product version with first-year maintenance. Review current license terms for your deployment before shipping.
11. Test before production
- HTML string with inline CSS and no external assets.
- HTML string with relative CSS, images, and web fonts.
- Public URL with redirects and client-side rendering.
- Authenticated URL or protected assets, if your application needs them.
- Long tables, page breaks, SVG, transparent images, and non-Latin text.
- Final Windows, Linux, or macOS/ARM deployment image.
Or skip the browser setup
If your input is a public web page and you need an image or PDF capture rather than a locally rendered Winnovative document, ScreenshotNeo provides a single HTTP request. Cookie banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP server lets Claude, Cursor, and other MCP clients call take_screenshot, get_page_info, and capture_pdf.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the ScreenshotNeo API documentation for options such as PDF paper size and margins, full-page capture, custom CSS and JavaScript, waits, blocking, headers, cookies, caching, signed links, async jobs, bulk capture, and usage reporting. The Free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account.
FAQ
Can I use the Classic package on Linux?
The reviewed package listing describes Classic as a Windows package. For Linux, evaluate the platform-specific PDF Next packages instead.
Should I pass HTML or a URL?
Use an HTML string when your application already owns the markup and data. Use URL conversion for a reachable page whose rendering should be captured as served.
Does async conversion guarantee higher throughput?
No. PDF Next documents async methods and cancellation, but capacity still depends on document complexity and your deployment resources.
Why is my PDF missing a relative image?
Provide a correct base URL or change the image reference to an absolute URL, then verify that the conversion host can access it.
Where should I verify license terms?
Use the current Winnovative package and product documentation for the license applicable to your version, hosting model, and deployment.


