How to Create a Xamarin PDF Generator
Creating PDF files in Xamarin.Forms can be tricky. Most .NET PDF libraries don't directly support mobile apps, and trying to generate PDF documents directly on a device often leads to errors or missing functionality. That's where IronPDF comes in. While it doesn't run natively in Xamarin, you can use a server-side approach to create PDF files, fill PDF forms, handle multiple pages, and include images, fonts, and custom layout, giving your mobile app a rich set of PDF generation features.
In this guide, we'll show you how to build a Xamarin PDF generator using IronPDF, including code examples, tips for saving PDF files, and ways to make your PDFs look professional.
Why a Server-Side Approach Works for Xamarin PDF Generation
IronPDF excels at creating PDF documents from HTML content with full support for CSS, JavaScript, and advanced layout features. Running it on a server allows your Xamarin.Forms app to send HTML content and receive fully rendered PDF files. This setup avoids the limitations of mobile devices while giving users access to professional PDF generation, including:
- PDF forms with editable fields
- Multiple pages with headers and footers
- Images, fonts, and custom layout
- Automatic styling for tables, graphics, and data
Using a server-side library also reduces app complexity and avoids errors related to missing fonts or rendering differences between Android and iOS. This approach gives you more control over the document output and maintains consistent quality across different mobile platforms.
Setting Up Your PDF Generation API
First, create an ASP.NET Core Web API project that will host IronPDF. Install the IronPDF NuGet package:
Install-Package IronPdf
Create a PDF controller to handle generation requests:
using IronPdf;
using Microsoft.AspNetCore.Mvc;
namespace PDFGenerationAPI.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
[HttpPost("generate")]
public async Task<IActionResult> GeneratePdf([FromBody] PdfRequest request)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 25;
renderer.RenderingOptions.MarginBottom = 25;
var pdf = await renderer.RenderHtmlAsPdfAsync(request.HtmlContent);
return File(pdf.BinaryData, "application/pdf", "document.pdf");
}
}
public class PdfRequest
{
public string HtmlContent { get; set; }
}
}using IronPdf;
using Microsoft.AspNetCore.Mvc;
namespace PDFGenerationAPI.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
[HttpPost("generate")]
public async Task<IActionResult> GeneratePdf([FromBody] PdfRequest request)
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
renderer.RenderingOptions.MarginTop = 25;
renderer.RenderingOptions.MarginBottom = 25;
var pdf = await renderer.RenderHtmlAsPdfAsync(request.HtmlContent);
return File(pdf.BinaryData, "application/pdf", "document.pdf");
}
}
public class PdfRequest
{
public string HtmlContent { get; set; }
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comThis controller accepts HTML content and returns a generated PDF. The ChromePdfRenderer handles the conversion, maintaining all CSS styling and JavaScript execution from your HTML. The rendering options allow customization of paper size, margins, page width, and other PDF properties. You can refer to the API documentation for additional configuration methods.
Output

Implementing the Xamarin Client
In your Xamarin.Forms application, create a service to communicate with the API. This code example demonstrates the client implementation:
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace XamarinFormsClient
{
public class PdfService
{
private readonly HttpClient _httpClient;
private const string ApiUrl = "https://your-api.com/api/pdf/generate"; // Replace with your API URL
public PdfService()
{
_httpClient = new HttpClient();
}
public async Task<byte[]> GeneratePdfAsync(string htmlContent)
{
var request = new { HtmlContent = htmlContent };
var json = JsonConvert.SerializeObject(request);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(ApiUrl, content);
if (response.IsSuccessStatusCode)
return await response.Content.ReadAsByteArrayAsync();
throw new Exception("PDF generation failed");
}
}
}using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace XamarinFormsClient
{
public class PdfService
{
private readonly HttpClient _httpClient;
private const string ApiUrl = "https://your-api.com/api/pdf/generate"; // Replace with your API URL
public PdfService()
{
_httpClient = new HttpClient();
}
public async Task<byte[]> GeneratePdfAsync(string htmlContent)
{
var request = new { HtmlContent = htmlContent };
var json = JsonConvert.SerializeObject(request);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(ApiUrl, content);
if (response.IsSuccessStatusCode)
return await response.Content.ReadAsByteArrayAsync();
throw new Exception("PDF generation failed");
}
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comThis functionality handles sending HTML to the server and receiving PDF files as byte arrays. Using JSON serialization guarantees proper data transmission between client and server. These code snippets provide a foundation you can extend with additional features like progress tracking or error handling.
Saving PDF Files on Mobile Devices
Once you receive the PDF, save it using platform-specific code. Implement proper file path handling and storage permission controls:
public interface ISaveFile
{
Task SavePdfAsync(string filename, byte[] pdfData);
}
// iOS Implementation
public class SaveFileIOS : ISaveFile
{
public async Task SavePdfAsync(string filename, byte[] pdfData)
{
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var filePath = Path.Combine(documents, filename);
await File.WriteAllBytesAsync(filePath, pdfData);
// Open PDF viewer
await Launcher.OpenAsync(new OpenFileRequest
{
File = new ReadOnlyFile(filePath)
});
}
}public interface ISaveFile
{
Task SavePdfAsync(string filename, byte[] pdfData);
}
// iOS Implementation
public class SaveFileIOS : ISaveFile
{
public async Task SavePdfAsync(string filename, byte[] pdfData)
{
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var filePath = Path.Combine(documents, filename);
await File.WriteAllBytesAsync(filePath, pdfData);
// Open PDF viewer
await Launcher.OpenAsync(new OpenFileRequest
{
File = new ReadOnlyFile(filePath)
});
}
}IRON VB CONVERTER ERROR developers@ironsoftware.comThis code example shows how to save PDF and write files using platform-specific APIs. The filePath location is determined by the system, and similar logic applies for Android with appropriate storage permissions. By handling files this way, you support PDF forms, multiple pages, and images without extra dependencies. You can download the generated document to the device's document center for easy access.
Output

Creating Professional PDF Documents
Generate professional PDFs by building HTML templates with embedded data. This method allows you to create PDF documents with structured content, including table rows and formatted elements:
public string GenerateInvoiceHtml(Invoice invoice)
{
return $@"
<html>
<head>
<style>
body {{ font-family: Arial; }}
.header {{ background-color: #f0f0f0; padding: 20px; }}
.invoice-details {{ margin: 20px 0; }}
table {{ width: 100%; border-collapse: collapse; }}
th, td {{ padding: 10px; border-bottom: 1px solid #ddd; }}
</style>
</head>
<body>
<div class='header'>
<h1>Invoice #{invoice.Number}</h1>
<p>Date: {invoice.Date:yyyy-MM-dd}</p>
</div>
<div class='invoice-details'>
<table>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
</tr>
{string.Join("", invoice.Items.Select(i =>
$"<tr><td>{i.Name}</td><td>{i.Quantity}</td><td>${i.Price}</td></tr>"
))}
</table>
<h3>Total: ${invoice.Total}</h3>
</div>
</body>
</html>";
}public string GenerateInvoiceHtml(Invoice invoice)
{
return $@"
<html>
<head>
<style>
body {{ font-family: Arial; }}
.header {{ background-color: #f0f0f0; padding: 20px; }}
.invoice-details {{ margin: 20px 0; }}
table {{ width: 100%; border-collapse: collapse; }}
th, td {{ padding: 10px; border-bottom: 1px solid #ddd; }}
</style>
</head>
<body>
<div class='header'>
<h1>Invoice #{invoice.Number}</h1>
<p>Date: {invoice.Date:yyyy-MM-dd}</p>
</div>
<div class='invoice-details'>
<table>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Price</th>
</tr>
{string.Join("", invoice.Items.Select(i =>
$"<tr><td>{i.Name}</td><td>{i.Quantity}</td><td>${i.Price}</td></tr>"
))}
</table>
<h3>Total: ${invoice.Total}</h3>
</div>
</body>
</html>";
}IRON VB CONVERTER ERROR developers@ironsoftware.comThis method creates structured HTML from your data models, with each row representing an invoice item. IronPDF preserves all styling, creating professional documents that match your brand guidelines. You can also add watermark stamps, PNG images, and other visual elements to enhance the document appearance.
Common Issues and Solutions
When implementing this architecture, you may encounter these challenges:
- Network timeouts: Increase
HttpClienttimeout for complex PDF documents - Large file handling: Stream PDF files over 10MB to avoid memory issues
- Offline scenarios: Queue PDF generation requests and set up a repository for pending operations
- Authentication: Secure endpoints with JWT tokens and user permission controls
- Rate limiting: Throttle API requests to prevent system overload
- Error handling: Implement proper error messages and comments in your code for troubleshooting
- File management: Handle file deletion after download to manage storage
When working with XML-based data or defined schemas, ensure proper serialization before sending content to the API. Add a link to your error logs for easier debugging, and register event handlers to track generation progress.
Important: Xamarin End-of-Support
Microsoft announced Xamarin's end-of-support in May 2024. For new projects, consider migrating to .NET MAUI, which IronPDF supports natively across multiple programming languages. This eliminates the need for a server-side API and enables direct PDF generation on mobile devices.
Deployment and Licensing Considerations
Deploy your API to cloud platforms like Azure App Service or AWS Lambda for scalability. Consider these factors:
- IronPDF licensing: Server deployments require appropriate IronPDF licenses
- Hosting costs: Factor in API hosting and bandwidth expenses
- Performance: Use caching for frequently generated PDFs to reduce load
- Security: Implement API authentication and HTTPS for all endpoints
Conclusion
While IronPDF doesn't directly support Xamarin, the server-side API approach provides a reliable solution for PDF generation in mobile applications. This architecture leverages IronPDF's powerful rendering engine while maintaining cross-platform compatibility for both iOS and Android platforms.
Ready to implement PDF generation in your Xamarin application? Start your free IronPDF trial and experience professional PDF creation capabilities. For production deployments, explore our licensing options to find the right fit for your needs.







