How to Migrate from SSRS to IronPDF in C#
Migrating from SQL Server Reporting Services (SSRS) to IronPDF transforms your PDF generation workflow from a heavyweight server-based infrastructure to a lightweight, in-process library that can be embedded directly into any .NET application. This guide provides a complete, step-by-step migration path that eliminates SQL Server dependencies, report server overhead, and Microsoft ecosystem lock-in.
Why Migrate from SSRS to IronPDF
Understanding SSRS
SQL Server Reporting Services (SSRS) is Microsoft's enterprise reporting platform that requires significant infrastructure investment. SSRS is a comprehensive reporting platform from Microsoft that provides a complete suite for creating, deploying, and managing reports, offering both feature-rich and interactive report features. Developed as part of the SQL Server ecosystem, SSRS is tightly integrated with Microsoft's database solutions.
However, for many PDF generation scenarios, SSRS infrastructure is excessive. Key reasons to migrate include:
- Heavy Infrastructure: Requires SQL Server, Report Server, and IIS configuration
- Microsoft Ecosystem Lock-in: Tied to SQL Server licensing and Windows Server
- Complex Deployment: Report deployment, security configuration, and subscription management
- Expensive Licensing: SQL Server licenses, especially for enterprise features
- Limited Web Support: Difficult to integrate with modern SPA frameworks
- Maintenance Overhead: Server patching, database maintenance, report management
- No Cloud-Native Option: Designed for on-premises, cloud support is awkward
When SSRS is Overkill
| Your Need | SSRS Overhead |
|---|---|
| Generate invoices | Full report server |
| Export data tables | SQL Server license |
| Create PDFs from data | Windows Server |
| Simple document generation | Report subscriptions |
IronPDF provides in-process PDF generation without any server infrastructure.
SSRS vs IronPDF Comparison
| Feature | SSRS | IronPDF |
|---|---|---|
| Dependency | Requires SQL Server | No specific database dependency |
| Deployment | Server-based | Library (embedded in applications) |
| Integration | Tight integration with Microsoft | Works with any data source |
| Data Visualization | Extensive native options | PDF-focused visualizations |
| Complexity | High (server setup required) | Moderate to low (library setup) |
| Cost | SQL Server licensing costs | Per developer licensing cost |
| HTML to PDF | No | Full Chromium |
| URL to PDF | No | Yes |
| CSS Support | Limited | Full CSS3 |
| JavaScript | No | Full ES2024 |
IronPDF, unlike SSRS, is not tied to any specific database or server ecosystem. It provides developers with a flexible library to dynamically create, edit, and manipulate PDF documents directly in C#. This decoupling from a server-based infrastructure offers a noticeable advantage—it is straightforward and adaptable, suitable for a wide array of applications beyond reporting.
For teams planning .NET 10 and C# 14 adoption through 2025 and 2026, IronPDF provides a modern Chromium rendering engine that eliminates the infrastructure complexity of SSRS.
Before You Start
Prerequisites
- .NET Environment: .NET Framework 4.6.2+ or .NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet Access: Ability to install NuGet packages
- IronPDF License: Obtain your license key from ironpdf.com
NuGet Package Changes
# SSRS has no direct NuGet - it's server-based
# Remove any ReportViewer controls
dotnet remove package Microsoft.ReportingServices.ReportViewerControl.WebForms
dotnet remove package Microsoft.ReportingServices.ReportViewerControl.WinForms
# Install IronPDF
dotnet add package IronPdf# SSRS has no direct NuGet - it's server-based
# Remove any ReportViewer controls
dotnet remove package Microsoft.ReportingServices.ReportViewerControl.WebForms
dotnet remove package Microsoft.ReportingServices.ReportViewerControl.WinForms
# Install IronPDF
dotnet add package IronPdfLicense Configuration
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";Complete API Reference
Namespace Changes
// Before: SSRS
using Microsoft.Reporting.WebForms;
using Microsoft.Reporting.WinForms;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;// Before: SSRS
using Microsoft.Reporting.WebForms;
using Microsoft.Reporting.WinForms;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;Core API Mappings
| SSRS Concept | IronPDF Equivalent | Notes |
|---|---|---|
LocalReport | ChromePdfRenderer | Core rendering |
ServerReport | RenderUrlAsPdf() | URL-based rendering |
.rdlc files | HTML/CSS templates | Template format |
ReportParameter | String interpolation | Parameters |
ReportDataSource | C# data + HTML | Data binding |
LocalReport.Render("PDF") | RenderHtmlAsPdf() | PDF output |
SubReport | Merged PDFs | Nested reports |
Report Server URL | Not needed | No server required |
ReportViewer control | Not needed | Direct PDF generation |
| Export formats | PDF is native | Focused output |
Code Migration Examples
Example 1: HTML to PDF Conversion
Before (SSRS):
// SSRS - SQL Server Reporting Services
using System;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Reporting.WebForms;
using System.IO;
class SSRSHtmlToPdf
{
static void Main()
{
// Create a ReportViewer instance
var reportViewer = new ReportViewer();
reportViewer.ProcessingMode = ProcessingMode.Local;
// Load RDLC report definition
reportViewer.LocalReport.ReportPath = "Report.rdlc";
// Add HTML content as a parameter or dataset
var htmlContent = "<h1>Hello World</h1><p>This is HTML content.</p>";
var param = new ReportParameter("HtmlContent", htmlContent);
reportViewer.LocalReport.SetParameters(param);
// Render the report to PDF
string mimeType, encoding, fileNameExtension;
string[] streams;
Warning[] warnings;
byte[] bytes = reportViewer.LocalReport.Render(
"PDF",
null,
out mimeType,
out encoding,
out fileNameExtension,
out streams,
out warnings);
File.WriteAllBytes("output.pdf", bytes);
}
}// SSRS - SQL Server Reporting Services
using System;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Reporting.WebForms;
using System.IO;
class SSRSHtmlToPdf
{
static void Main()
{
// Create a ReportViewer instance
var reportViewer = new ReportViewer();
reportViewer.ProcessingMode = ProcessingMode.Local;
// Load RDLC report definition
reportViewer.LocalReport.ReportPath = "Report.rdlc";
// Add HTML content as a parameter or dataset
var htmlContent = "<h1>Hello World</h1><p>This is HTML content.</p>";
var param = new ReportParameter("HtmlContent", htmlContent);
reportViewer.LocalReport.SetParameters(param);
// Render the report to PDF
string mimeType, encoding, fileNameExtension;
string[] streams;
Warning[] warnings;
byte[] bytes = reportViewer.LocalReport.Render(
"PDF",
null,
out mimeType,
out encoding,
out fileNameExtension,
out streams,
out warnings);
File.WriteAllBytes("output.pdf", bytes);
}
}After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class IronPdfHtmlToPdf
{
static void Main()
{
// Create a ChromePdfRenderer instance
var renderer = new ChromePdfRenderer();
// Convert HTML string to PDF
var htmlContent = "<h1>Hello World</h1><p>This is HTML content.</p>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
// Save the PDF file
pdf.SaveAs("output.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class IronPdfHtmlToPdf
{
static void Main()
{
// Create a ChromePdfRenderer instance
var renderer = new ChromePdfRenderer();
// Convert HTML string to PDF
var htmlContent = "<h1>Hello World</h1><p>This is HTML content.</p>";
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
// Save the PDF file
pdf.SaveAs("output.pdf");
}
}This example demonstrates the fundamental architectural difference. SSRS requires creating a ReportViewer instance, loading an .rdlc report definition file, setting parameters, and then calling LocalReport.Render("PDF") with multiple out parameters for metadata.
IronPDF uses a ChromePdfRenderer with RenderHtmlAsPdf() in just three lines of code. No report definition files, no parameter objects, no metadata handling required. See the HTML to PDF documentation for comprehensive examples.
Example 2: URL to PDF with Headers and Footers
Before (SSRS):
// SSRS - SQL Server Reporting Services
using System;
using System.IO;
using System.Net;
using Microsoft.Reporting.WebForms;
class SSRSUrlToPdf
{
static void Main()
{
// Download HTML content from URL
string url = "https://example.com";
string htmlContent;
using (var client = new WebClient())
{
htmlContent = client.DownloadString(url);
}
// Create RDLC report with header/footer configuration
var reportViewer = new ReportViewer();
reportViewer.ProcessingMode = ProcessingMode.Local;
reportViewer.LocalReport.ReportPath = "WebReport.rdlc";
// Set parameters for header and footer
var parameters = new ReportParameter[]
{
new ReportParameter("HeaderText", "Company Report"),
new ReportParameter("FooterText", "Page " + DateTime.Now.ToString()),
new ReportParameter("HtmlContent", htmlContent)
};
reportViewer.LocalReport.SetParameters(parameters);
// Render to PDF
string mimeType, encoding, fileNameExtension;
string[] streams;
Warning[] warnings;
byte[] bytes = reportViewer.LocalReport.Render(
"PDF", null, out mimeType, out encoding,
out fileNameExtension, out streams, out warnings);
File.WriteAllBytes("webpage.pdf", bytes);
}
}// SSRS - SQL Server Reporting Services
using System;
using System.IO;
using System.Net;
using Microsoft.Reporting.WebForms;
class SSRSUrlToPdf
{
static void Main()
{
// Download HTML content from URL
string url = "https://example.com";
string htmlContent;
using (var client = new WebClient())
{
htmlContent = client.DownloadString(url);
}
// Create RDLC report with header/footer configuration
var reportViewer = new ReportViewer();
reportViewer.ProcessingMode = ProcessingMode.Local;
reportViewer.LocalReport.ReportPath = "WebReport.rdlc";
// Set parameters for header and footer
var parameters = new ReportParameter[]
{
new ReportParameter("HeaderText", "Company Report"),
new ReportParameter("FooterText", "Page " + DateTime.Now.ToString()),
new ReportParameter("HtmlContent", htmlContent)
};
reportViewer.LocalReport.SetParameters(parameters);
// Render to PDF
string mimeType, encoding, fileNameExtension;
string[] streams;
Warning[] warnings;
byte[] bytes = reportViewer.LocalReport.Render(
"PDF", null, out mimeType, out encoding,
out fileNameExtension, out streams, out warnings);
File.WriteAllBytes("webpage.pdf", bytes);
}
}After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class IronPdfUrlToPdf
{
static void Main()
{
// Create a ChromePdfRenderer instance
var renderer = new ChromePdfRenderer();
// Configure rendering options with header and footer
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter()
{
HtmlFragment = "<div style='text-align:center'>Company Report</div>"
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter()
{
HtmlFragment = "<div style='text-align:center'>Page {page} of {total-pages} - " + DateTime.Now.ToString("MM/dd/yyyy") + "</div>"
};
// Convert URL to PDF
string url = "https://example.com";
var pdf = renderer.RenderUrlAsPdf(url);
// Save the PDF file
pdf.SaveAs("webpage.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class IronPdfUrlToPdf
{
static void Main()
{
// Create a ChromePdfRenderer instance
var renderer = new ChromePdfRenderer();
// Configure rendering options with header and footer
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter()
{
HtmlFragment = "<div style='text-align:center'>Company Report</div>"
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter()
{
HtmlFragment = "<div style='text-align:center'>Page {page} of {total-pages} - " + DateTime.Now.ToString("MM/dd/yyyy") + "</div>"
};
// Convert URL to PDF
string url = "https://example.com";
var pdf = renderer.RenderUrlAsPdf(url);
// Save the PDF file
pdf.SaveAs("webpage.pdf");
}
}SSRS cannot directly convert URLs to PDF. You must manually download HTML content with WebClient.DownloadString(), create a separate .rdlc report file, pass the HTML and header/footer text as ReportParameter arrays, then render with the complex Render() method signature.
IronPDF's RenderUrlAsPdf() handles the entire process in a single call. Headers and footers are configured with HtmlHeaderFooter objects that support full HTML/CSS and placeholders like {page} and {total-pages}. Learn more in our tutorials.
Example 3: Database-Driven Report
Before (SSRS):
// SSRS - SQL Server Reporting Services
using System;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Reporting.WebForms;
using System.IO;
class SSRSDatabaseReport
{
static void Main()
{
// Create a ReportViewer instance
var reportViewer = new ReportViewer();
reportViewer.ProcessingMode = ProcessingMode.Local;
reportViewer.LocalReport.ReportPath = "SalesReport.rdlc";
// Create database connection and fetch data
string connString = "Server=localhost;Database=SalesDB;Integrated Security=true;";
using (var connection = new SqlConnection(connString))
{
var adapter = new SqlDataAdapter("SELECT * FROM Sales", connection);
var dataSet = new DataSet();
adapter.Fill(dataSet, "Sales");
// Bind data to report
var dataSource = new ReportDataSource("SalesDataSet", dataSet.Tables[0]);
reportViewer.LocalReport.DataSources.Clear();
reportViewer.LocalReport.DataSources.Add(dataSource);
}
// Render to PDF
string mimeType, encoding, fileNameExtension;
string[] streams;
Warning[] warnings;
byte[] bytes = reportViewer.LocalReport.Render(
"PDF", null, out mimeType, out encoding,
out fileNameExtension, out streams, out warnings);
File.WriteAllBytes("sales-report.pdf", bytes);
}
}// SSRS - SQL Server Reporting Services
using System;
using System.Data;
using System.Data.SqlClient;
using Microsoft.Reporting.WebForms;
using System.IO;
class SSRSDatabaseReport
{
static void Main()
{
// Create a ReportViewer instance
var reportViewer = new ReportViewer();
reportViewer.ProcessingMode = ProcessingMode.Local;
reportViewer.LocalReport.ReportPath = "SalesReport.rdlc";
// Create database connection and fetch data
string connString = "Server=localhost;Database=SalesDB;Integrated Security=true;";
using (var connection = new SqlConnection(connString))
{
var adapter = new SqlDataAdapter("SELECT * FROM Sales", connection);
var dataSet = new DataSet();
adapter.Fill(dataSet, "Sales");
// Bind data to report
var dataSource = new ReportDataSource("SalesDataSet", dataSet.Tables[0]);
reportViewer.LocalReport.DataSources.Clear();
reportViewer.LocalReport.DataSources.Add(dataSource);
}
// Render to PDF
string mimeType, encoding, fileNameExtension;
string[] streams;
Warning[] warnings;
byte[] bytes = reportViewer.LocalReport.Render(
"PDF", null, out mimeType, out encoding,
out fileNameExtension, out streams, out warnings);
File.WriteAllBytes("sales-report.pdf", bytes);
}
}After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
using System.Data;
using System.Data.SqlClient;
using System.Text;
class IronPdfDatabaseReport
{
static void Main()
{
// Create database connection and fetch data
string connString = "Server=localhost;Database=SalesDB;Integrated Security=true;";
var dataTable = new DataTable();
using (var connection = new SqlConnection(connString))
{
var adapter = new SqlDataAdapter("SELECT * FROM Sales", connection);
adapter.Fill(dataTable);
}
// Build HTML table from data
var htmlBuilder = new StringBuilder();
htmlBuilder.Append("<h1>Sales Report</h1><table border='1'><tr>");
foreach (DataColumn column in dataTable.Columns)
htmlBuilder.Append($"<th>{column.ColumnName}</th>");
htmlBuilder.Append("</tr>");
foreach (DataRow row in dataTable.Rows)
{
htmlBuilder.Append("<tr>");
foreach (var item in row.ItemArray)
htmlBuilder.Append($"<td>{item}</td>");
htmlBuilder.Append("</tr>");
}
htmlBuilder.Append("</table>");
// Convert to PDF
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlBuilder.ToString());
pdf.SaveAs("sales-report.pdf");
}
}// NuGet: Install-Package IronPdf
using IronPdf;
using System;
using System.Data;
using System.Data.SqlClient;
using System.Text;
class IronPdfDatabaseReport
{
static void Main()
{
// Create database connection and fetch data
string connString = "Server=localhost;Database=SalesDB;Integrated Security=true;";
var dataTable = new DataTable();
using (var connection = new SqlConnection(connString))
{
var adapter = new SqlDataAdapter("SELECT * FROM Sales", connection);
adapter.Fill(dataTable);
}
// Build HTML table from data
var htmlBuilder = new StringBuilder();
htmlBuilder.Append("<h1>Sales Report</h1><table border='1'><tr>");
foreach (DataColumn column in dataTable.Columns)
htmlBuilder.Append($"<th>{column.ColumnName}</th>");
htmlBuilder.Append("</tr>");
foreach (DataRow row in dataTable.Rows)
{
htmlBuilder.Append("<tr>");
foreach (var item in row.ItemArray)
htmlBuilder.Append($"<td>{item}</td>");
htmlBuilder.Append("</tr>");
}
htmlBuilder.Append("</table>");
// Convert to PDF
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlBuilder.ToString());
pdf.SaveAs("sales-report.pdf");
}
}SSRS requires a pre-designed .rdlc report file ("SalesReport.rdlc"), filling a DataSet, creating a ReportDataSource with a specific name ("SalesDataSet") that must match the report definition, clearing existing data sources, adding the new data source, then rendering.
IronPDF uses your existing data access code (same SqlDataAdapter pattern), then builds HTML dynamically with StringBuilder. You have full control over the layout using standard HTML/CSS—no proprietary report definition files required.
Feature Comparison
| Feature | SSRS | IronPDF |
|---|---|---|
| Infrastructure | ||
| Server Required | Yes (Report Server) | No |
| SQL Server License | Required | Not needed |
| Windows Server | Required | Any platform |
| Database Required | Yes (ReportServer DB) | No |
| Development | ||
| Visual Designer | Yes (.rdlc) | HTML editors |
| Template Format | RDLC/RDL | HTML/CSS/Razor |
| Data Sources | Built-in DSN | Any C# data |
| Rendering | ||
| HTML to PDF | No | Full Chromium |
| URL to PDF | No | Yes |
| CSS Support | Limited | Full CSS3 |
| JavaScript | No | Full ES2024 |
| Charts | Built-in | Via JS libraries |
| Deployment | ||
| Report Deployment | To server | With app |
| Configuration | Complex | Simple |
| Maintenance | High | Low |
Common Migration Issues
Issue 1: RDLC Report Definitions
SSRS: Uses proprietary .rdlc XML format.
Solution: Convert to HTML templates:
- Open .rdlc in Visual Studio
- Document the layout structure
- Recreate in HTML/CSS
- Use Razor for data binding
Issue 2: Shared Data Sources
SSRS: Connection strings in Report Server.
Solution: Use your application's data access layer:
var data = await _dbContext.Sales.ToListAsync();
// Then bind to HTML templatevar data = await _dbContext.Sales.ToListAsync();
// Then bind to HTML templateIssue 3: Report Parameters UI
SSRS: Built-in parameter prompts.
Solution: Build parameter UI in your application:
// Your own parameter form, then:
var pdf = GenerateReport(startDate, endDate, region);// Your own parameter form, then:
var pdf = GenerateReport(startDate, endDate, region);Issue 4: Subscriptions/Scheduled Reports
SSRS: Built-in subscription engine.
Solution: Use background job framework:
// Using Hangfire or similar
RecurringJob.AddOrUpdate("weekly-report",
() => GenerateAndEmailReport(), Cron.Weekly);// Using Hangfire or similar
RecurringJob.AddOrUpdate("weekly-report",
() => GenerateAndEmailReport(), Cron.Weekly);Migration Checklist
Pre-Migration
- Inventory all SSRS reports (
.rdlcfiles) - Document data sources and connections
- Screenshot report layouts for visual reference
- List report parameters for each report
- Note subscription schedules
- Obtain IronPDF license key from ironpdf.com
Code Updates
- Remove ReportViewer packages
- Install
IronPdfNuGet package - Convert
.rdlcfiles to HTML templates - Replace
LocalReportwithChromePdfRenderer - Replace
ReportDataSourcewith C# data + HTML templates - Replace
ReportParameterwith string interpolation - Replace
LocalReport.Render("PDF")withRenderHtmlAsPdf() - Implement headers/footers with
HtmlHeaderFooter - Add license initialization at application startup
Infrastructure
- Plan Report Server decommission
- Migrate subscriptions to job scheduler (Hangfire, etc.)
- Update deployment scripts
Testing
- Compare PDF output visually
- Verify data accuracy
- Test pagination
- Check all parameters
- Performance testing






