FO.NET vs IronPDF: Technical Comparison Guide
When .NET developers look at PDF generation solutions, FO.NET stands out as a specialized tool for converting XSL-FO documents to PDF. However, its dependence on the outdated XSL-FO language, lack of HTML/CSS support, and discontinued maintenance status lead many teams to consider alternatives. IronPDF offers a modern solution using HTML/CSS web standards that most developers are already familiar with, featuring a Chromium rendering engine and regular monthly updates.
This comparison reviews both libraries across relevant technical aspects to assist professional developers and architects in making informed decisions for their .NET PDF needs.
Understanding FO.NET
FO.NET (also known as FoNet) is an open-source library designed for converting XSL Formatting Object (XSL-FO) documents into PDFs using C#. The library operates under the Apache 2.0 license and directly maps the XSL-FO language into PDF format.
FO.NET uses FonetDriver as its primary class, with the Make() factory method creating driver instances and Render() methods processing XSL-FO input streams to produce PDF output streams. Configuration happens within the XSL-FO markup itself using elements like fo:simple-page-master, fo:layout-master-set, and formatting attributes for margins, page sizes, and fonts.
A significant limitation is that FO.NET requires XSL-FO knowledge—an XML-based language that is a W3C specification from 2001 with no updates since 2006. The library does not support HTML or CSS and cannot directly render web pages. XSL-FO is largely considered obsolete in today's technology field, with less than 1% of developers having expertise in it compared to over 98% who know HTML/CSS.
The original CodePlex repository is defunct, and GitHub forks are no longer actively maintained. FO.NET has internal dependencies on System.Drawing that prevent it from working on Linux/macOS, limiting it to Windows-only deployment.
Understanding IronPDF
IronPDF is a .NET PDF library that uses HTML/CSS for document styling and layout, using web standards that are common in development. The library uses a Chromium rendering engine, providing full CSS3 support including Flexbox and Grid layouts, plus JavaScript execution.
IronPDF uses ChromePdfRenderer as its primary rendering class, with RenderingOptions providing programmatic configuration for page size, margins, headers, footers, and other PDF settings. The library supports direct URL rendering, HTML string rendering, and HTML file rendering, producing PdfDocument objects that can be saved, merged, secured, or further manipulated.
IronPDF is actively maintained with monthly releases, supports true cross-platform deployment (Windows, Linux, macOS), and provides thorough documentation and tutorials.
Architecture and Technology Comparison
The fundamental difference between these .NET PDF libraries lies in their input format and technology foundation.
| Aspect | FO.NET | IronPDF |
|---|---|---|
| Input Format | XSL-FO (obsolete XML) | HTML/CSS (modern web standards) |
| Learning Curve | Steep (XSL-FO expertise) | Gentle (HTML/CSS knowledge) |
| Maintenance | Abandoned | Actively maintained monthly |
| Platform Support | Windows only | True cross-platform |
| CSS Support | None | Full CSS3 (Flexbox, Grid) |
| JavaScript | None | Full JavaScript support |
| URL Rendering | Not supported | Built-in |
| Modern Features | Limited | Headers, footers, watermarks, security |
| Documentation | Outdated | Comprehensive tutorials |
FO.NET was designed when XSL-FO was expected to become a standard for document formatting. That didn't happen—HTML/CSS became the universal document format. Most XSL-FO resources are from 2005-2010, making it increasingly difficult to find current information or community support.
Code Comparison: Common PDF Operations
HTML to PDF Conversion
The most fundamental operation demonstrates the model difference between XSL-FO and HTML approaches.
FO.NET:
// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;
using System.Xml;
class Program
{
static void Main()
{
// FoNet requires XSL-FO format, not HTML
// First convert HTML to XSL-FO (manual process)
string xslFo = @"<?xml version='1.0' encoding='utf-8'?>
<fo:root xmlns:fo='http://www.w3.org/1999/XSL/Format'>
<fo:layout-master-set>
<fo:simple-page-master master-name='page'>
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference='page'>
<fo:flow flow-name='xsl-region-body'>
<fo:block>Hello World</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>";
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("output.pdf", FileMode.Create));
}
}// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;
using System.Xml;
class Program
{
static void Main()
{
// FoNet requires XSL-FO format, not HTML
// First convert HTML to XSL-FO (manual process)
string xslFo = @"<?xml version='1.0' encoding='utf-8'?>
<fo:root xmlns:fo='http://www.w3.org/1999/XSL/Format'>
<fo:layout-master-set>
<fo:simple-page-master master-name='page'>
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference='page'>
<fo:flow flow-name='xsl-region-body'>
<fo:block>Hello World</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>";
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("output.pdf", FileMode.Create));
}
}IronPDF:
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<h1>Hello World</h1><p>This is HTML content.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
string html = "<h1>Hello World</h1><p>This is HTML content.</p>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}The contrast is clear. FO.NET requires verbose XSL-FO markup with XML namespace declarations, fo:root, fo:layout-master-set, fo:simple-page-master, fo:page-sequence, fo:flow, and fo:block elements—all before producing a simple "Hello World" text. The code comment explicitly notes: "FoNet requires XSL-FO format, not HTML."
IronPDF creates a renderer, passes standard HTML, renders to PDF, and saves—four simple lines using syntax developers already know.
For advanced HTML rendering options, explore the HTML to PDF conversion guide.
URL to PDF Conversion
Converting web pages to PDF reveals a critical capability gap.
FO.NET:
// NuGet: Install-Package Fonet
using Fonet;
using System.IO;
using System.Net;
class Program
{
static void Main()
{
// FoNet does not support URL rendering directly
// Must manually download, convert HTML to XSL-FO, then render
string url = "https://example.com";
string html = new WebClient().DownloadString(url);
// Manual conversion from HTML to XSL-FO required (complex)
string xslFo = ConvertHtmlToXslFo(html); // Not built-in
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("webpage.pdf", FileMode.Create));
}
static string ConvertHtmlToXslFo(string html)
{
// Custom implementation required
throw new System.NotImplementedException();
}
}// NuGet: Install-Package Fonet
using Fonet;
using System.IO;
using System.Net;
class Program
{
static void Main()
{
// FoNet does not support URL rendering directly
// Must manually download, convert HTML to XSL-FO, then render
string url = "https://example.com";
string html = new WebClient().DownloadString(url);
// Manual conversion from HTML to XSL-FO required (complex)
string xslFo = ConvertHtmlToXslFo(html); // Not built-in
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("webpage.pdf", FileMode.Create));
}
static string ConvertHtmlToXslFo(string html)
{
// Custom implementation required
throw new System.NotImplementedException();
}
}IronPDF:
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}FO.NET explicitly does not support URL rendering. The code comments state: "FoNet does not support URL rendering directly" and "Manual conversion from HTML to XSL-FO required (complex)." The ConvertHtmlToXslFo() method throws NotImplementedException because this conversion is not built-in and would require custom implementation.
IronPDF provides native RenderUrlAsPdf() functionality that handles URL fetching, JavaScript execution, and rendering in a single method call—three lines of code versus a complex, unimplemented workflow.
Learn more about URL rendering in the URL to PDF documentation.
PDF with Custom Settings
Configuring page dimensions and margins demonstrates the configuration approach differences.
FO.NET:
// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;
class Program
{
static void Main()
{
// FoNet settings are configured in XSL-FO markup
string xslFo = @"<?xml version='1.0' encoding='utf-8'?>
<fo:root xmlns:fo='http://www.w3.org/1999/XSL/Format'>
<fo:layout-master-set>
<fo:simple-page-master master-name='A4'
page-height='297mm' page-width='210mm'
margin-top='20mm' margin-bottom='20mm'
margin-left='25mm' margin-right='25mm'>
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference='A4'>
<fo:flow flow-name='xsl-region-body'>
<fo:block font-size='14pt'>Custom PDF</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>";
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("custom.pdf", FileMode.Create));
}
}// NuGet: Install-Package Fonet
using Fonet;
using Fonet.Render.Pdf;
using System.IO;
class Program
{
static void Main()
{
// FoNet settings are configured in XSL-FO markup
string xslFo = @"<?xml version='1.0' encoding='utf-8'?>
<fo:root xmlns:fo='http://www.w3.org/1999/XSL/Format'>
<fo:layout-master-set>
<fo:simple-page-master master-name='A4'
page-height='297mm' page-width='210mm'
margin-top='20mm' margin-bottom='20mm'
margin-left='25mm' margin-right='25mm'>
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference='A4'>
<fo:flow flow-name='xsl-region-body'>
<fo:block font-size='14pt'>Custom PDF</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>";
FonetDriver driver = FonetDriver.Make();
driver.Render(new StringReader(xslFo),
new FileStream("custom.pdf", FileMode.Create));
}
}IronPDF:
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Engines.Chrome;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 25;
renderer.RenderingOptions.MarginRight = 25;
string html = "<h1 style='font-size:14pt'>Custom PDF</h1>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Engines.Chrome;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
renderer.RenderingOptions.MarginLeft = 25;
renderer.RenderingOptions.MarginRight = 25;
string html = "<h1 style='font-size:14pt'>Custom PDF</h1>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom.pdf");
}
}The code comment in FO.NET explicitly states: "FoNet settings are configured in XSL-FO markup." Page size, margins, and formatting are embedded within the XML structure as attributes on fo:simple-page-master. This means configuration is intertwined with content in a verbose XML format.
IronPDF separates configuration from content using programmatic RenderingOptions properties. Settings like PaperSize, MarginTop, MarginBottom, MarginLeft, and MarginRight are set on the renderer object, while content remains clean HTML.
API Mapping Reference
For developers evaluating FO.NET migration or comparing capabilities, this mapping shows equivalent operations:
Core Class Mapping
| FO.NET | IronPDF |
|---|---|
FonetDriver.Make() | new ChromePdfRenderer() |
driver.Render(inputStream, outputStream) | renderer.RenderHtmlAsPdf(html) |
driver.Render(inputFile, outputStream) | renderer.RenderHtmlFileAsPdf(path) |
driver.BaseDirectory | RenderingOptions.BaseUrl |
driver.OnError += handler | Try/catch around render |
XSL-FO to RenderingOptions Mapping
| XSL-FO Attribute | IronPDF RenderingOptions |
|---|---|
page-height/page-width | PaperSize |
margin-top | MarginTop |
margin-bottom | MarginBottom |
margin-left | MarginLeft |
margin-right | MarginRight |
reference-orientation | PaperOrientation |
XSL-FO Elements to HTML Mapping
| XSL-FO Element | HTML Equivalent |
|---|---|
<fo:root> | <html> |
<fo:layout-master-set> | CSS @page rule |
<fo:simple-page-master> | CSS @page |
<fo:page-sequence> | <body> or <div> |
<fo:flow> | <main> or <div> |
<fo:static-content> | HtmlHeaderFooter |
<fo:block> | <p>, <div>, <h1>-<h6> |
<fo:table> | <table> |
<fo:list-block> | <ul>, <ol> |
<fo:external-graphic> | <img> |
<fo:page-number/> | {page} placeholder |
Feature Comparison Summary
| Feature | FO.NET | IronPDF |
|---|---|---|
| HTML to PDF | ❌ (requires manual XSL-FO conversion) | ✅ |
| URL to PDF | ❌ (not supported) | ✅ |
| XSL-FO to PDF | ✅ | N/A |
| CSS3 Support | ❌ | ✅ (Flexbox, Grid) |
| JavaScript | ❌ | ✅ |
| Headers/Footers | XSL-FO static-content | HTML-based |
| Page Numbering | fo:page-number | {page} placeholder |
| Cross-Platform | ❌ (Windows only) | ✅ |
| Active Maintenance | ❌ (abandoned) | ✅ (monthly) |
When Teams Consider Moving from FO.NET to IronPDF
Development teams evaluate transitioning from FO.NET to IronPDF for several reasons:
Obsolete Technology: XSL-FO is a W3C specification from 2001 that has seen no updates since 2006 and is largely considered obsolete. Most resources and documentation are from 2005-2010, making it increasingly difficult to find current information or hire developers with XSL-FO expertise.
Steep Learning Curve: XSL-FO requires learning complex XML-based markup with specialized formatting objects (fo:block, fo:table, fo:page-sequence, etc.). Less than 1% of developers know XSL-FO compared to over 98% who know HTML/CSS.
No HTML/CSS Support: FO.NET cannot render HTML or CSS—it requires manual conversion from HTML to XSL-FO markup, which is not built into the library. Teams with web content or HTML templates must implement custom conversion logic.
Abandoned Maintenance: The original CodePlex repository is defunct, and GitHub forks are no longer actively maintained. Security patches, bug fixes, and new features are not being developed.
Platform Limitations: FO.NET has internal dependencies on System.Drawing that prevent it from working on Linux/macOS, limiting deployment to Windows-only environments. Modern applications increasingly require cross-platform deployment.
Missing Modern Features: No JavaScript support, no CSS3 features (Flexbox, Grid), no modern web fonts, and no direct URL rendering capability.
Strengths and Considerations
FO.NET Strengths
- Direct XSL-FO Conversion: Optimized specifically for XSL-FO to PDF conversion
- Open Source: Apache 2.0 license—free to use, modify, and distribute
- Precise Control: XSL-FO provides detailed control over document layout
FO.NET Considerations
- Obsolete Technology: XSL-FO specification has no updates since 2006
- Requires XSL-FO Knowledge: Less than 1% of developers have expertise
- No HTML Support: Cannot render HTML or CSS content
- Abandoned: No active maintenance or security updates
- Windows Only: System.Drawing dependencies prevent cross-platform use
- No URL Rendering: Cannot directly convert web pages
- Limited Documentation: Resources are outdated
IronPDF Strengths
- HTML/CSS Standard: Uses web technologies over 98% of developers already know
- Modern Rendering: Chromium engine with full CSS3 and JavaScript support
- Active Development: Monthly releases with new features and security patches
- Cross-Platform: True support for Windows, Linux, and macOS
- Direct URL Rendering: Native
RenderUrlAsPdf()capability - Professional Features: Headers, footers, watermarks, security—all built-in
- Comprehensive Resources: Extensive tutorials and documentation
IronPDF Considerations
- Commercial License: Requires license for production use
- Different Paradigm: XSL-FO templates need conversion to HTML
Conclusion
FO.NET and IronPDF represent fundamentally different approaches to PDF generation in .NET. FO.NET serves the niche use case of XSL-FO to PDF conversion, but its reliance on obsolete technology, abandoned maintenance, Windows-only limitation, and lack of HTML support make it increasingly difficult to justify for new projects.
IronPDF provides a modern approach using HTML/CSS web standards that aligns with current developer skills and technologies. The ability to directly render HTML, URLs, and use full CSS3 with a Chromium engine makes it suitable for contemporary PDF generation requirements.
As organizations plan for .NET 10, C# 14, and application development through 2026, the technology foundation matters. Teams maintaining legacy XSL-FO systems may continue using FO.NET, but the path forward for modern PDF generation clearly points toward HTML-based solutions like IronPDF that leverage existing web development expertise.
Start evaluating IronPDF with a free trial and explore the comprehensive documentation to assess fit for your specific requirements.