
.NET Maui で PDF ファイルを表示する方法
RotativaからIronPDFへの移行は、PDF生成のワークフローを近代化すると同時に、重要なセキュリティの脆弱性に対処します。 このガイドは、放棄されたwkhtmltopdf依存性を排除し、最新のCSSとJavaScriptのサポートを可能にし、ASP.NET MVCを超えるクロスプラットフォームの互換性を提供する、完全で段階的な移行パスを提供します。
なぜRotativaからIronPDFへ移行するのか
Rotativaについて
Rotativaは、C#でPDFを生成するための開発者の間で長い間人気のある選択肢です。 HTMLコンテンツをPDF形式に変換するためにwkhtmltopdfツールを活用します。 Rotativaは、ASP.NET MVCアプリケーションのために特別に設計されたオープンソースのライブラリです。 しかし、Rotativaは多くの読者を惹きつける一方で、時代遅れの技術スタックに依存しているため、すべての開発者がすぐに理解できるとは限らないという課題があります。
Rotativaはそのバックエンド機能にwkhtmltopdfを活用し、ASP.NET MVCプロジェクトにPDF生成を統合する簡単な方法を提供します。
重要なセキュリティ勧告
Rotativaはwkhtmltopdfをラップしていますが、これはCRITICAL UNPATCHED SECURITY VULNERABILITIES.を持っています。
| 属性 | 価値 |
|---|---|
| CVE ID | CVE-2022-35583 |
| 厳しさ | クリティカル (9.8/10) |
| アタックベクター | ネットワーク |
| ステータス | 固定バージョンなし (wkhtmltopdf バイナリアーカイブ済み) |
| 影響を受ける言語 | wkhtmltopdf 0.12.6をバンドルしたすべてのRotativaバージョン |
wkhtmltopdf GitHubリポジトリは、2023年1月2日にアーカイブ(読み取り専用)されました。ステータスページには、プロジェクトがQt 4に依存している(2015年からサポートされていない)ことや、2012年以降のWebKitブランチから成り、信頼できないHTMLの使用を明示的に警告しています。 CVE-2022-35583には固定バージョンがないため、Rotativaを使用しているアプリケーションはHTML入力が上流で完全にサニタイズされない限り暴露されています。
攻撃の仕組み
<!-- Attacker submits this content via your MVC model -->
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin" />
インパクト:
- AWS/Azure/GCPクラウドメタデータエンドポイントへのアクセス
- 内部APIデータと認証情報を盗む
- 内部ネットワークのポートスキャン
- 機密設定の流出
テクノロジーの危機
Rotativaは、wkhtmltopdfをラップしています:
- Qt WebKit 4.8 (2012年から)
- Flexboxをサポートしていません
- CSSグリッドのサポートなし
- 壊れたJavaScriptの実行
- ES6+はサポートしません。
RotativaとIronPDFの比較
| フィーチャー | ロータティバ | IronPDF |
|---|---|---|
| プロジェクトの互換性 | ASP.NET MVCのみ | あらゆる.NETプロジェクトタイプ(MVC、Blazor Pages、Blazorなど) |
| メンテナンス | 中止 | 積極的にメンテナンス |
| セキュリティ。 | wkhtmltopdfの依存関係による脆弱性 (CVE-2022-35583) | 定期的なアップデートとセキュリティパッチ |
| HTMLレンダリング。 | 時代遅れのWebKit | モダンChromium |
| CSS3について | 部分的 | サポート対象 |
| フレックスボックス/グリッド | サポートされていません | サポート対象 |
| JavaScript(JavaScript | 信頼できない | 完全なES6 |
| Razorページ | サポートされていません | サポート対象 |
| Blazor。 | サポートされていません | サポート対象 |
| PDF操作 | 不可 | フル |
| デジタル署名。 | 不可 | フル |
| PDF/Aコンプライアンス | 不可 | フル |
| 非同期/待機 | 同期のみ | 完全な非同期 |
| オープンソース。 | はい、MITライセンス | いいえ、商用ライセンス |
現在 for .NETバージョンをターゲットとするチームには、IronPDFはRoativaが提供できない現代のChromiumレンダリングとクロスプラットフォームサポートを提供します。
始める前に
前提条件
- .NET環境: .NET Framework 4.6.2+ または.NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGetアクセス: NuGetパッケージをインストールする機能
- IronPDFライセンス: IronPDFからライセンスキーを取得します。
NuGetパッケージの変更
元のRotativaパッケージはクラシックASP.NET MVC 5を対象としています(最終リリースv1.7.3、2017-09-29)。 コミュニティフォークRotativa.AspNetCore(webgio)は2024-11-06にv1.4.0に達し、.NET Core 3.1から.NET 8をサポートしています。ただし、どちらのパッケージもwkhtmltopdf 0.12.6のバイナリを still 同梱しています(最終上流リリース2020年6月)。
# Remove Rotativa
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore
# Install IronPDF
dotnet add package IronPdf
wkhtmltopdfバイナリの削除
プロジェクトからこれらのファイルを削除してください:
wkhtmltopdf.exewkhtmltox.dll- 任意の
Rotativa/フォルダー
これらはCVE-2022-35583のソースです。IronPDFはネイティブバイナリを必要としません。
ライセンス構成
// Add in Program.cs or Startup.cs
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";' Add in Program.vb or Startup.vb
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"' Add in Program.vb or Startup.vb
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"完全な API リファレンス
名前空間の変更
// Before: Rotativa
using Rotativa;
using Rotativa.Options;
using Rotativa.AspNetCore;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;// Before: Rotativa
using Rotativa;
using Rotativa.Options;
using Rotativa.AspNetCore;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;' Before: Rotativa
Imports Rotativa
Imports Rotativa.Options
Imports Rotativa.AspNetCore
' After: IronPDF
Imports IronPdf
Imports IronPdf.Rendering' Before: Rotativa
Imports Rotativa
Imports Rotativa.Options
Imports Rotativa.AspNetCore
' After: IronPDF
Imports IronPdf
Imports IronPdf.Renderingコア クラス マッピング
| Rotativa クラス | IronPDF 同等物 |
|---|---|
ViewAsPdf | ChromePdfRenderer |
ActionAsPdf | ChromePdfRenderer.RenderUrlAsPdf() |
UrlAsPdf | ChromePdfRenderer.RenderUrlAsPdf() |
Orientation 列挙型 | PdfPaperOrientation 列挙型 |
Size 列挙型 | PdfPaperSize 列挙型 |
ページのプレースホルダーの変換
| Rotativa プレースホルダ | IronPDF プレースホルダー |
|---|---|
[page] | {page} |
[topage] | {total-pages} |
[date] | {date} |
[time] | {time} |
[title] | {html-title} |
[sitepage] | {url} |
コード移行の例
例1: HTMLからPDFへの変換
翻訳前(Rotativa):
// NuGet: Install-Package Rotativa.AspNetCore
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;
namespace RotativaExample
{
public class PdfController : Controller
{
public async Task<IActionResult> GeneratePdf()
{
var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";
//ロータティバrequires returning a ViewAsPdf result from MVC controller
return new ViewAsPdf()
{
ViewName = "PdfView",
PageSize = Rotativa.AspNetCore.Options.Size.A4
};
}
}
}// NuGet: Install-Package Rotativa.AspNetCore
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;
namespace RotativaExample
{
public class PdfController : Controller
{
public async Task<IActionResult> GeneratePdf()
{
var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";
//ロータティバrequires returning a ViewAsPdf result from MVC controller
return new ViewAsPdf()
{
ViewName = "PdfView",
PageSize = Rotativa.AspNetCore.Options.Size.A4
};
}
}
}Imports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports System.Threading.Tasks
Namespace RotativaExample
Public Class PdfController
Inherits Controller
Public Async Function GeneratePdf() As Task(Of IActionResult)
Dim htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>"
' Rotativa requires returning a ViewAsPdf result from MVC controller
Return New ViewAsPdf() With {
.ViewName = "PdfView",
.PageSize = Rotativa.AspNetCore.Options.Size.A4
}
End Function
End Class
End NamespaceImports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports System.Threading.Tasks
Namespace RotativaExample
Public Class PdfController
Inherits Controller
Public Async Function GeneratePdf() As Task(Of IActionResult)
Dim htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>"
' Rotativa requires returning a ViewAsPdf result from MVC controller
Return New ViewAsPdf() With {
.ViewName = "PdfView",
.PageSize = Rotativa.AspNetCore.Options.Size.A4
}
End Function
End Class
End Namespace翻訳後(IronPDF):。
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF generated successfully!");
}
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var htmlContent = "<h1>Hello World</h1><p>This is a PDF document.</p>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF generated successfully!");
}
}
}' NuGet: Install-Package IronPdf
Imports IronPdf
Imports System
Module IronPdfExample
Sub Main()
Dim renderer As New ChromePdfRenderer()
Dim htmlContent As String = "<h1>Hello World</h1><p>This is a PDF document.</p>"
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("output.pdf")
Console.WriteLine("PDF generated successfully!")
End Sub
End Module' NuGet: Install-Package IronPdf
Imports IronPdf
Imports System
Module IronPdfExample
Sub Main()
Dim renderer As New ChromePdfRenderer()
Dim htmlContent As String = "<h1>Hello World</h1><p>This is a PDF document.</p>"
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("output.pdf")
Console.WriteLine("PDF generated successfully!")
End Sub
End Moduleこの例は、基本的なアーキテクチャの違いを示しています。 RotativaはMVCコントローラーアクションからViewAsPdf結果を返す必要があり、ASP.NET MVCフレームワークに結びつけられます。 このパターンはMVCリクエストパイプライン内でのみ動作し、レンダリングにはRazorビューが必要です。
IronPDFはコンソールアプリケーション、ウェブAPI、Blazor、Razor Pages、.NETプロジェクトのどのタイプでも動作します。 HTML文字列とともにRenderHtmlAsPdf()を呼び出し、結果を保存します。 MVCコントローラ不要、ビュー依存なし。 包括的な例については、HTML to PDF documentationを参照してください。
例2: URLからPDFへの変換
翻訳前(Rotativa):
// NuGet: Install-Package Rotativa.AspNetCore
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;
namespace RotativaExample
{
public class UrlPdfController : Controller
{
public async Task<IActionResult> ConvertUrlToPdf()
{
//ロータティバworks within MVC framework and returns ActionResult
return new UrlAsPdf("https://www.example.com")
{
FileName = "webpage.pdf",
PageSize = Rotativa.AspNetCore.Options.Size.A4,
PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
};
}
}
}// NuGet: Install-Package Rotativa.AspNetCore
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using System.Threading.Tasks;
namespace RotativaExample
{
public class UrlPdfController : Controller
{
public async Task<IActionResult> ConvertUrlToPdf()
{
//ロータティバworks within MVC framework and returns ActionResult
return new UrlAsPdf("https://www.example.com")
{
FileName = "webpage.pdf",
PageSize = Rotativa.AspNetCore.Options.Size.A4,
PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
};
}
}
}Imports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports System.Threading.Tasks
Namespace RotativaExample
Public Class UrlPdfController
Inherits Controller
Public Async Function ConvertUrlToPdf() As Task(Of IActionResult)
Return New UrlAsPdf("https://www.example.com") With {
.FileName = "webpage.pdf",
.PageSize = Rotativa.AspNetCore.Options.Size.A4,
.PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
}
End Function
End Class
End NamespaceImports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports System.Threading.Tasks
Namespace RotativaExample
Public Class UrlPdfController
Inherits Controller
Public Async Function ConvertUrlToPdf() As Task(Of IActionResult)
Return New UrlAsPdf("https://www.example.com") With {
.FileName = "webpage.pdf",
.PageSize = Rotativa.AspNetCore.Options.Size.A4,
.PageOrientation = Rotativa.AspNetCore.Options.Orientation.Portrait
}
End Function
End Class
End Namespace翻訳後(IronPDF):。
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("URL converted to PDF successfully!");
}
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("URL converted to PDF successfully!");
}
}
}' NuGet: Install-Package IronPdf
Imports IronPdf
Imports System
Module IronPdfExample
Sub Main()
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
pdf.SaveAs("webpage.pdf")
Console.WriteLine("URL converted to PDF successfully!")
End Sub
End Module' NuGet: Install-Package IronPdf
Imports IronPdf
Imports System
Module IronPdfExample
Sub Main()
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
pdf.SaveAs("webpage.pdf")
Console.WriteLine("URL converted to PDF successfully!")
End Sub
End ModuleRotativaのActionResultを返す必要があります。 IronPDFのPdfDocumentオブジェクトを返します。 URLレンダリングには、wkhtmltopdfの脆弱で時代遅れのWebKitエンジンではなく、最新のChromiumを使用しています。詳しくはチュートリアルをご覧ください。
例3:ページ番号を含むヘッダーとフッター
翻訳前(Rotativa):
// NuGet: Install-Package Rotativa.AspNetCore
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using Rotativa.AspNetCore.Options;
using System.Threading.Tasks;
namespace RotativaExample
{
public class HeaderFooterController : Controller
{
public async Task<IActionResult> GeneratePdfWithHeaderFooter()
{
return new ViewAsPdf("Report")
{
PageSize = Size.A4,
// Margins(top, right, bottom, left)
PageMargins = new Margins(20, 10, 20, 10),
CustomSwitches = "--header-center \"Page Header\" --footer-center \"Page [page] of [topage]\""
};
}
}
}// NuGet: Install-Package Rotativa.AspNetCore
using Microsoft.AspNetCore.Mvc;
using Rotativa.AspNetCore;
using Rotativa.AspNetCore.Options;
using System.Threading.Tasks;
namespace RotativaExample
{
public class HeaderFooterController : Controller
{
public async Task<IActionResult> GeneratePdfWithHeaderFooter()
{
return new ViewAsPdf("Report")
{
PageSize = Size.A4,
// Margins(top, right, bottom, left)
PageMargins = new Margins(20, 10, 20, 10),
CustomSwitches = "--header-center \"Page Header\" --footer-center \"Page [page] of [topage]\""
};
}
}
}Imports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports Rotativa.AspNetCore.Options
Imports System.Threading.Tasks
Namespace RotativaExample
Public Class HeaderFooterController
Inherits Controller
Public Async Function GeneratePdfWithHeaderFooter() As Task(Of IActionResult)
Return New ViewAsPdf("Report") With {
.PageSize = Size.A4,
' Margins(top, right, bottom, left)
.PageMargins = New Margins(20, 10, 20, 10),
.CustomSwitches = "--header-center ""Page Header"" --footer-center ""Page [page] of [topage]"""
}
End Function
End Class
End NamespaceImports Microsoft.AspNetCore.Mvc
Imports Rotativa.AspNetCore
Imports Rotativa.AspNetCore.Options
Imports System.Threading.Tasks
Namespace RotativaExample
Public Class HeaderFooterController
Inherits Controller
Public Async Function GeneratePdfWithHeaderFooter() As Task(Of IActionResult)
Return New ViewAsPdf("Report") With {
.PageSize = Size.A4,
' Margins(top, right, bottom, left)
.PageMargins = New Margins(20, 10, 20, 10),
.CustomSwitches = "--header-center ""Page Header"" --footer-center ""Page [page] of [topage]"""
}
End Function
End Class
End Namespace翻訳後(IronPDF):。
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
CenterText = "Page Header",
DrawDividerLine = true
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
{
CenterText = "Page {page} of {total-pages}",
DrawDividerLine = true
};
var htmlContent = "<h1>Report Title</h1><p>Report content goes here.</p>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("report.pdf");
Console.WriteLine("PDF with headers and footers created successfully!");
}
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
namespace IronPdfExample
{
class Program
{
static void Main(string[] args)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.TextHeader = new TextHeaderFooter()
{
CenterText = "Page Header",
DrawDividerLine = true
};
renderer.RenderingOptions.TextFooter = new TextHeaderFooter()
{
CenterText = "Page {page} of {total-pages}",
DrawDividerLine = true
};
var htmlContent = "<h1>Report Title</h1><p>Report content goes here.</p>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("report.pdf");
Console.WriteLine("PDF with headers and footers created successfully!");
}
}
}' NuGet: Install-Package IronPdf
Imports IronPdf
Imports IronPdf.Rendering
Imports System
Module IronPdfExample
Sub Main(args As String())
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.TextHeader = New TextHeaderFooter() With {
.CenterText = "Page Header",
.DrawDividerLine = True
}
renderer.RenderingOptions.TextFooter = New TextHeaderFooter() With {
.CenterText = "Page {page} of {total-pages}",
.DrawDividerLine = True
}
Dim htmlContent As String = "<h1>Report Title</h1><p>Report content goes here.</p>"
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("report.pdf")
Console.WriteLine("PDF with headers and footers created successfully!")
End Sub
End Module' NuGet: Install-Package IronPdf
Imports IronPdf
Imports IronPdf.Rendering
Imports System
Module IronPdfExample
Sub Main(args As String())
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.TextHeader = New TextHeaderFooter() With {
.CenterText = "Page Header",
.DrawDividerLine = True
}
renderer.RenderingOptions.TextFooter = New TextHeaderFooter() With {
.CenterText = "Page {page} of {total-pages}",
.DrawDividerLine = True
}
Dim htmlContent As String = "<h1>Report Title</h1><p>Report content goes here.</p>"
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("report.pdf")
Console.WriteLine("PDF with headers and footers created successfully!")
End Sub
End ModuleRotativaはコマンドライン引数をwkhtmltopdfに渡すために[topage]といったプレースホルダーを含めて設定します。 この文字列ベースのアプローチは、エラーが発生しやすく、コンパイル時に検証するのが困難です。
IronPDFはCenterTextオブジェクトを使用します。 プレースホルダー構文が{total-pages}に変更されます。 型付きプロパティはインテリセンス、コンパイル時チェックを提供し、タイプミスのリスクはありません。
MVCのみのアーキテクチャ問題
Rotativaは、ASP.NET MVC 5以前向けに設計されています:
// ❌ロータティバ- Only works with classic MVC pattern
public class InvoiceController : Controller
{
public ActionResult InvoicePdf(int id)
{
var model = GetInvoice(id);
return new ViewAsPdf("Invoice", model); // Tied to MVC Views
}
}
// Problems:
// - No Razor Pages support
// - No Blazor support
// - No minimal APIs support
// - No ASP.NET Core native integration// ❌ロータティバ- Only works with classic MVC pattern
public class InvoiceController : Controller
{
public ActionResult InvoicePdf(int id)
{
var model = GetInvoice(id);
return new ViewAsPdf("Invoice", model); // Tied to MVC Views
}
}
// Problems:
// - No Razor Pages support
// - No Blazor support
// - No minimal APIs support
// - No ASP.NET Core native integrationImports System.Web.Mvc
Public Class InvoiceController
Inherits Controller
Public Function InvoicePdf(id As Integer) As ActionResult
Dim model = GetInvoice(id)
Return New ViewAsPdf("Invoice", model) ' Tied to MVC Views
End Function
End Class
' Problems:
' - No Razor Pages support
' - No Blazor support
' - No minimal APIs support
' - No ASP.NET Core native integrationImports System.Web.Mvc
Public Class InvoiceController
Inherits Controller
Public Function InvoicePdf(id As Integer) As ActionResult
Dim model = GetInvoice(id)
Return New ViewAsPdf("Invoice", model) ' Tied to MVC Views
End Function
End Class
' Problems:
' - No Razor Pages support
' - No Blazor support
' - No minimal APIs support
' - No ASP.NET Core native integrationIronPDFはビューのレンダリングとPDFの生成を分離しており、MVCビューだけでなくあらゆるHTMLをレンダリングすることができます。
非同期パターンの移行
Rotativa はスレッドをブロックします; IronPDFは完全なasync/awaitをサポートしています:
// ❌ロータティバ- Blocks the thread
public ActionResult GeneratePdf()
{
return new ViewAsPdf("Report");
// This blocks the request thread until PDF is complete
// Poor scalability under load
}
// ✅IronPDF-完全な非同期support
public async Task<IActionResult> GeneratePdf()
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return File(pdf.BinaryData, "application/pdf");
// Non-blocking, better scalability
}// ❌ロータティバ- Blocks the thread
public ActionResult GeneratePdf()
{
return new ViewAsPdf("Report");
// This blocks the request thread until PDF is complete
// Poor scalability under load
}
// ✅IronPDF-完全な非同期support
public async Task<IActionResult> GeneratePdf()
{
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync(html);
return File(pdf.BinaryData, "application/pdf");
// Non-blocking, better scalability
}' ❌ロータティバ- Blocks the thread
Public Function GeneratePdf() As ActionResult
Return New ViewAsPdf("Report")
' This blocks the request thread until PDF is complete
' Poor scalability under load
End Function
' ✅IronPDF-完全な非同期support
Public Async Function GeneratePdf() As Task(Of IActionResult)
Dim renderer As New ChromePdfRenderer()
Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
Return File(pdf.BinaryData, "application/pdf")
' Non-blocking, better scalability
End Function' ❌ロータティバ- Blocks the thread
Public Function GeneratePdf() As ActionResult
Return New ViewAsPdf("Report")
' This blocks the request thread until PDF is complete
' Poor scalability under load
End Function
' ✅IronPDF-完全な非同期support
Public Async Function GeneratePdf() As Task(Of IActionResult)
Dim renderer As New ChromePdfRenderer()
Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
Return File(pdf.BinaryData, "application/pdf")
' Non-blocking, better scalability
End Function移行後の新機能
IronPDFに移行した後、Rotativaでは提供できない機能を得ることができます:
PDFマージ
var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("complete.pdf");var merged = PdfDocument.Merge(pdf1, pdf2, pdf3);
merged.SaveAs("complete.pdf");Dim merged = PdfDocument.Merge(pdf1, pdf2, pdf3)
merged.SaveAs("complete.pdf")Dim merged = PdfDocument.Merge(pdf1, pdf2, pdf3)
merged.SaveAs("complete.pdf")デジタル署名
var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);var signature = new PdfSignature("certificate.pfx", "password");
pdf.Sign(signature);Dim signature = New PdfSignature("certificate.pfx", "password")
pdf.Sign(signature)Dim signature = New PdfSignature("certificate.pfx", "password")
pdf.Sign(signature)パスワード保護
pdf.SecuritySettings.UserPassword = "secret";pdf.SecuritySettings.UserPassword = "secret";pdf.SecuritySettings.UserPassword = "secret"pdf.SecuritySettings.UserPassword = "secret"ウォーターマーク
pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");pdf.ApplyWatermark("<h1 style='color:red; opacity:0.3;'>DRAFT</h1>");IRON VB CONVERTER ERROR developers@ironsoftware.comIRON VB CONVERTER ERROR developers@ironsoftware.comPDF/Aアーカイブ準拠
pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b);pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b)pdf.SaveAsPdfA("archive.pdf", PdfAVersions.PdfA3b)最新の CSS サポート
// This now works (broke in Rotativa)
var html = @"
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>
<div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
<div>Col 1</div><div>Col 2</div><div>Col 3</div>
</div>";
var pdf = renderer.RenderHtmlAsPdf(html); // Works!// This now works (broke in Rotativa)
var html = @"
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>
<div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
<div>Col 1</div><div>Col 2</div><div>Col 3</div>
</div>";
var pdf = renderer.RenderHtmlAsPdf(html); // Works!' This now works (broke in Rotativa)
Dim html As String = "
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>
<div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
<div>Col 1</div><div>Col 2</div><div>Col 3</div>
</div>"
Dim pdf = renderer.RenderHtmlAsPdf(html) ' Works!' This now works (broke in Rotativa)
Dim html As String = "
<div style='display: flex; justify-content: space-between;'>
<div>Left</div>
<div>Right</div>
</div>
<div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'>
<div>Col 1</div><div>Col 2</div><div>Col 3</div>
</div>"
Dim pdf = renderer.RenderHtmlAsPdf(html) ' Works!移行チェックリスト
移行前
- コードベースでロータティバの使用箇所をすべて特定する
- RenderingOptions への変換に使用されるドキュメント CustomSwitches
- 変換用のヘッダー/フッタープレースホルダー構文に注意してください(
[page]→{page}) - IronPDFからIronPDFライセンスキーを取得します
パッケージの変更
Rotativa.AspNetCoreNuGetパッケージを削除します- wkhtmltopdfバイナリを削除します(
wkhtmltopdf.exe,wkhtmltox.dll) IronPdfNuGetパッケージをインストールします
コードの変更
- 名前空間インポートを更新します(
using Rotativa;→using IronPdf;) ChromePdfRenderer+RenderHtmlAsPdf()に置き換えますRenderUrlAsPdf()に置き換えますRenderingOptionsプロパティに変換します- プレースホルダー構文を更新します(
[page]→{page},[topage]→{total-pages}) MarginRightに置き換えます- 必要に応じて非同期パターンに変更する
- アプリケーションの起動時にライセンスの初期化を追加
移行後
- すべてのPDF生成が正しく機能することを確認する
- PDF出力品質の比較(Chromiumの方が正確にレンダリングされる)
- CSS レンダリングの改善を検証 (Flexbox/Grid が動作するようになりました)
- JavaScript実行をテストする (Chromium で信頼性が向上)
- セキュリティスキャンのパスを検証する(CVE-2022-35583フラグはなくなりました)
- Docker構成を更新してwkhtmltopdfのインストールを削除します
Curtis Chauは、カールトン大学でコンピュータサイエンスの学士号を取得し、Node.js、TypeScript、JavaScript、およびReactに精通したフロントエンド開発を専門としています。直感的で美しいユーザーインターフェースを作成することに情熱を持ち、Curtisは現代のフレームワークを用いた開発や、構造の良い視覚的に魅力的なマニュアルの作成を楽しんでいます。
関連する記事


