A DinkToPdf alternative that keeps your code.
wkhtmltopdf is archived, and DinkToPdf hasn't had a release since 2017. SelectPdf.Compat.DinkToPdf keeps the DinkToPdf API, so your converter code builds as it is, and renders with Chromium instead of Qt WebKit.
Free for commercial use · up to 5 pages per document · MIT licensed
dotnet remove package DinkToPdf dotnet add package SelectPdf.Compat.DinkToPdf dotnet add package SelectPdf.Universal.Native.linux-x64
Swap the package, add the engine for your platform. Your code stays as it is.
Why move off DinkToPdf.
- wkhtmltopdf, the engine under DinkToPdf, is no longer maintained: its GitHub repository is archived, and its last release, 0.12.6, dates from June 2020. Source
- DinkToPdf's last NuGet release, 1.0.8, is from April 2017. Source
- wkhtmltopdf renders with an old Qt WebKit, so flexbox, grid and current JavaScript don't work, and layouts have to work around it.
- You ship and load the native
libwkhtmltoxlibrary yourself, one file per platform, plus the system packages it needs on Linux.
Migrate in three steps.
-
1Swap the package
dotnet remove package DinkToPdf dotnet add package SelectPdf.Compat.DinkToPdf
-
2Add the engine for your platform
Add
SelectPdf.Universal.Native.<rid>, where<rid>iswin-x64,win-x86,linux-x64,linux-arm64orosx-arm64. Reference one engine package per build, because they all install into the same folder.dotnet add package SelectPdf.Universal.Native.linux-x64
A project developed on Windows and deployed to a Linux container can pick the engine by platform in the project file:
<PropertyGroup> <SelectPdfRid>$(RuntimeIdentifier)</SelectPdfRid> <SelectPdfRid Condition="'$(SelectPdfRid)' == '' And $([MSBuild]::IsOSPlatform('Windows'))">win-x64</SelectPdfRid> <SelectPdfRid Condition="'$(SelectPdfRid)' == ''">linux-x64</SelectPdfRid> </PropertyGroup> <ItemGroup> <PackageReference Include="SelectPdf.Universal.Native.$(SelectPdfRid)" Version="26.5.0" /> </ItemGroup> -
3Delete the native wkhtmltopdf files
Remove the
libwkhtmltoxfiles from your project and theCustomAssemblyLoadContextcode that loaded them. Your converter code stays as it is:using DinkToPdf; using DinkToPdf.Contracts; services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools())); byte[] pdf = converter.Convert(new HtmlToPdfDocument { GlobalSettings = { PaperSize = PaperKind.A4, Orientation = Orientation.Portrait, Margins = new MarginSettings { Top = 10 } }, Objects = { new ObjectSettings { HtmlContent = html, FooterSettings = { Center = "Page [page] of [toPage]" } } } });
How DinkToPdf settings map.
Your settings are translated into SelectPdf's. Settings with no equivalent, such as Copies, DPI and MinimumFontSize, are ignored, and each one raises the Warning event so you can see it.
| DinkToPdf | SelectPdf |
|---|---|
PaperSize and Orientation | The exact page size in points |
Margins (mm, cm or in) | Margins in points; 10 mm on each side by default, as in wkhtmltopdf |
HeaderSettings / FooterSettings text, font, line and spacing | Text sections placed inside the margin, where wkhtmltopdf placed them |
[page], [topage], [date], [title] and the other variables | Page number, page count or the value itself (case-insensitive, so [toPage] works) |
ObjectSettings.Page / HtmlContent | Converting a URL or local file / an HTML string |
Several Objects | One PDF with page breaks between them; page numbering runs across all of them |
EnableIntelligentShrinking, ZoomFactor | The scale of the content, as wkhtmltopdf applied it |
PrintMediaType, EnableJavascript, Background, UserStyleSheet | CSS media type, JavaScript, backgrounds, custom CSS |
Username/Password, JSDelay, Proxy, CustomHeaders, Cookies | HTTP authentication, conversion delay (rounded up to whole seconds), proxy, headers, cookies |
Outline, DocumentTitle, ColorMode.Grayscale | Bookmarks from the headings, document title, grayscale output |
PhaseChanged, ProgressChanged, Finished, Error, Warning | Raised at the same points as before |
The full list is in the package README.
What behaves differently.
CSS sizes are scaled the way wkhtmltopdf's smart shrinking scaled them, so existing templates keep their size. A few things do change:
The engine
Chromium lays pages out like a current browser. Layouts that worked around WebKit's missing flexbox and grid now render as written, and text metrics differ slightly. Control page breaks with CSS break-before, break-after and break-inside: avoid.
Wide content
With smart shrinking turned off, content wider than the page is shrunk to fit instead of being cut at the right edge.
HTML header and footer URLs
They no longer receive wkhtmltopdf's ?page= and ?topage= parameters. Use text headers and footers for page numbers.
Several objects
The first object's header, footer and web settings apply to the whole document.
Concurrency
SynchronizedConverter no longer runs every conversion on one thread. SelectPdf converts in parallel, so a singleton converter serves concurrent requests.
Failures
A failed conversion returns an empty array and raises Error, as before. Set SelectPdfCompat.ThrowOnError = true to throw instead.
Run it on Linux and in Docker.
The engine package bundles the Chromium libraries, so the image is built from the official .NET images with no apt-get lines:
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /src COPY . . RUN dotnet publish -c Release -o /app FROM mcr.microsoft.com/dotnet/aspnet:8.0 WORKDIR /app COPY --from=build /app . ENTRYPOINT ["dotnet", "YourApp.dll"]
Linux needs glibc 2.30 or later (Debian 11+, Ubuntu 20.04+, RHEL 9+), which the official .NET images have. For ARM64 hosts, use SelectPdf.Universal.Native.linux-arm64. Linux images often have no fonts installed: the engine has built-in fonts for Latin scripts, and SelectPdf.Universal.Fonts adds every other script.
Free up to 5 pages, then licensed.
The free package renders through the SelectPdf Community Edition. The .Licensed package is the same code on SelectPdf.Universal, so moving up means changing the package reference.
| SelectPdf.Compat.DinkToPdf | SelectPdf.Compat.DinkToPdf.Licensed | |
|---|---|---|
| Price | Free for commercial use | Needs a SelectPdf license |
| Pages per document | Up to 5. A longer document throws an error that says how many pages it had | No limit |
| Several objects with a URL among them | Not supported (needs PDF merging) | Converted one by one and merged |
| Your code | Identical | Identical |
To accept the first 5 pages of a longer document instead of an error, set SelectPdfCompat.FailOnPageLimit = false; the Warning event then reports the cut.
Using WkHtmlToPdfDotNet instead?
There is a package for Haukcode.WkHtmlToPdfDotNet too, with its WkHtmlToPdfDotNet namespace and its extra members such as CoverSettings. The steps are the same, and the apt-get lines its Dockerfile needed can go:
dotnet remove package Haukcode.WkHtmlToPdfDotNet dotnet add package SelectPdf.Compat.WkHtmlToPdfDotNet dotnet add package SelectPdf.Universal.Native.linux-x64
Questions, answered.
Something else? Write to support@selectpdf.com with your settings and, if you can, the HTML.