Como criar um serviço centralizado de geração de PDFs com ASP.NET Core e IronPDF
Crie uma API .NET PDF pronta para produção usando ASP.NET Core e IronPDF para centralizar a lógica de geração de PDFs, permitindo a criação consistente de documentos em todos os seus aplicativos com endpoints RESTful para conversão de HTML para PDF, mesclagem, marca d'água e processamento dinâmico de modelos.
Ao trabalhar com aplicações modernas, os desenvolvedores .NET frequentemente precisam criar um serviço centralizado de geração de PDFs. Seja para gerar faturas, relatórios, certificados ou contratos, ter uma API .NET dedicada para PDFs melhora o fluxo de trabalho de geração de PDFs. Como isso ajuda? Proporciona consistência, facilidade de manutenção e escalabilidade em seus aplicativos para desktop e web. Gerenciar o conteúdo de documentos, páginas PDF e campos de formulário PDF torna-se simples.
Neste tutorial, você aprenderá como criar uma API de PDF pronta para produção usando ASP.NET Core e IronPDF , uma poderosa biblioteca de PDF for .NET . Criaremos endpoints RESTful que geram PDFs a partir de HTML, mesclam documentos , adicionam marcas d'água e lidam com diversos cenários reais de PDF em sua API Web.
Por que criar uma API dedicada para PDFs?

Antes de analisarmos o código, vamos entender por que criar uma API dedicada para PDFs faz sentido:
- Lógica centralizada : Toda a lógica de geração de PDFs reside em um único local, simplificando a manutenção e as atualizações.
- Arquitetura de microsserviços : Perfeita para arquiteturas orientadas a serviços, onde diferentes aplicativos precisam de recursos de PDF.
- Otimização de desempenho : Facilita a escalabilidade e a otimização de um serviço dedicado para PDFs grandes, várias páginas e dados dinâmicos usando operações assíncronas e técnicas de desempenho .
- Independente de linguagem : Qualquer aplicação cliente pode consumir a API, independentemente da linguagem de programação.
- Saída consistente : Garante que todos os PDFs em sua organização mantenham layout, formatação e conteúdo consistentes.
Pronto para começar a construir? Baixe a versão de avaliação gratuita do IronPDF e siga este tutorial para criar arquivos PDF programaticamente em seus projetos .NET Framework .
O que torna o IronPDF a biblioteca PDF .NET completa?

O IronPDF se destaca como a principal biblioteca de PDF para desenvolvedores .NET , oferecendo um conjunto abrangente de recursos que tornam a geração de PDFs em projetos de API Web simples e confiável. Baseado no mecanismo de renderização do Chrome , ele garante conversões perfeitas de HTML para PDF em apenas algumas linhas de código, mantendo todo o estilo, a execução de JavaScript e os layouts responsivos .
Principais funcionalidades que tornam o IronPDF ideal para o desenvolvimento de APIs PDF em .NET :
- Renderização baseada no Chrome : Utiliza o mecanismo do Google Chrome para conversão precisa de HTML em PDF, com suporte completo para imagens incorporadas e recursos da web.
- Conjunto de recursos avançados : edite documentos com assinaturas digitais , formulários PDF , anotações , criptografia , compressão e muito mais.
- Crie PDFs seguros : gerencie conteúdo confidencial com criptografia , assinaturas digitais e proteção de documentos.
- Vários formatos de entrada : Use HTML, URLs, imagens e documentos do Office para criar PDFs.
- Manipulação avançada : Mesclar páginas , dividir documentos , aplicar marcas d'água , criar formulários interativos e manipular PDFs programaticamente.
- Suporte multiplataforma : Funciona em Windows , Linux , macOS , Docker e plataformas em nuvem .
- Desempenho otimizado : operações assíncronas , gerenciamento eficiente de memória e renderização rápida com opções de atraso de renderização .
Como configurar seu projeto de API de documentos PDF?
Vamos começar criando um novo projeto de API Web ASP.NET Core e instalando os pacotes necessários.
Quais são os pré-requisitos?
- SDK do .NET 6.0 ou posterior
- Visual Studio 2022 ou Visual Studio Code
- Utilize o Postman ou ferramenta similar para testar a sua API REST de PDF.
Como faço para criar o projeto?
Primeiro, vamos criar o projeto onde construiremos nossa ferramenta de geração de PDFs.
dotnet new webapi -n PdfApiService
cd PdfApiService
dotnet new webapi -n PdfApiService
cd PdfApiService
Como faço para instalar o IronPDF?
Em seguida, adicione o IronPDF ao seu projeto via NuGet:
dotnet add package IronPDF
dotnet add package IronPDF
Ou, utilizando o Console do Gerenciador de Pacotes NuGet no Visual Studio:
Install-Package IronPDF
Para opções avançadas de instalação, incluindo pacotes específicos da plataforma , configuração do Docker ou configurações do Linux , consulte a documentação de instalação do IronPDF .
Que estrutura de projeto devo usar?
Um bom desenvolvimento em C# exige a manutenção de uma pasta de projeto limpa e bem estruturada. Por exemplo:

Como criar seu primeiro endpoint de PDF?
Vamos criar um endpoint simples que converta HTML para o formato PDF. Primeiro, crie a interface de serviço e a implementação:
Como faço para criar um serviço em PDF?
Primeiro, adicione o seguinte ao seu arquivo IPdfService.cs:
public interface IPdfService
{
byte[] GeneratePdfFromHtml(string htmlContent);
byte[] GeneratePdfFromUrl(string url);
}
public interface IPdfService
{
byte[] GeneratePdfFromHtml(string htmlContent);
byte[] GeneratePdfFromUrl(string url);
}
Public Interface IPdfService
Function GeneratePdfFromHtml(htmlContent As String) As Byte()
Function GeneratePdfFromUrl(url As String) As Byte()
End Interface
No arquivo PdfService.cs, adicione o seguinte:
using IronPdf;
public class PdfService : IPdfService
{
private readonly ChromePdfRenderer _renderer;
public PdfService()
{
_renderer = new ChromePdfRenderer();
// Configure rendering options for optimal PDF generation in .NET
_renderer.RenderingOptions.MarginTop = 20;
_renderer.RenderingOptions.MarginBottom = 20;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GeneratePdfFromHtml(string htmlContent)
{
// Generate PDF from HTML using the .NET PDF API
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
}
public byte[] GeneratePdfFromUrl(string url)
{
// Convert URL to PDF in the REST API
var pdf = _renderer.RenderUrlAsPdf(url);
return pdf.BinaryData;
}
}
using IronPdf;
public class PdfService : IPdfService
{
private readonly ChromePdfRenderer _renderer;
public PdfService()
{
_renderer = new ChromePdfRenderer();
// Configure rendering options for optimal PDF generation in .NET
_renderer.RenderingOptions.MarginTop = 20;
_renderer.RenderingOptions.MarginBottom = 20;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GeneratePdfFromHtml(string htmlContent)
{
// Generate PDF from HTML using the .NET PDF API
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
}
public byte[] GeneratePdfFromUrl(string url)
{
// Convert URL to PDF in the REST API
var pdf = _renderer.RenderUrlAsPdf(url);
return pdf.BinaryData;
}
}
Imports IronPdf
Public Class PdfService
Implements IPdfService
Private ReadOnly _renderer As ChromePdfRenderer
Public Sub New()
_renderer = New ChromePdfRenderer()
' Configure rendering options for optimal PDF generation in .NET
_renderer.RenderingOptions.MarginTop = 20
_renderer.RenderingOptions.MarginBottom = 20
_renderer.RenderingOptions.PrintHtmlBackgrounds = True
End Sub
Public Function GeneratePdfFromHtml(htmlContent As String) As Byte()
' Generate PDF from HTML using the .NET PDF API
Dim pdf = _renderer.RenderHtmlAsPdf(htmlContent)
Return pdf.BinaryData
End Function
Public Function GeneratePdfFromUrl(url As String) As Byte()
' Convert URL to PDF in the REST API
Dim pdf = _renderer.RenderUrlAsPdf(url)
Return pdf.BinaryData
End Function
End Class
O PdfService lida com a conversão de HTML em PDF. Utilizando o ChromePdfRenderer do IronPDF, esta classe configura valores padrão como margens de página e renderização de fundo para resultados profissionais. Para configurações de renderização avançadas, explore as opções de renderização do IronPDF .
Quando o controlador envia HTML bruto, o serviço o renderiza em um PDF de alta qualidade e retorna os dados em bytes para download. Ele também converte páginas da web inteiras diretamente em PDFs usando a conversão de URL para PDF .
Como faço para criar o controlador?
Agora crie o controlador para sua API. Isso fornece um endpoint que gera arquivos PDF a partir de HTML e permite que você baixe e salve documentos PDF em seu sistema.
// Controllers/PdfController.cs
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
private readonly IPdfService _pdfService;
public PdfController(IPdfService pdfService)
{
_pdfService = pdfService;
}
[HttpPost("html-to-pdf")]
public IActionResult ConvertHtmlToPdf([FromBody] HtmlRequest request)
{
try
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
// Return as downloadable file
return File(pdfBytes, "application/pdf", "document.pdf");
}
catch (Exception ex)
{
return BadRequest($"Error generating PDF: {ex.Message}");
}
}
}
// Controllers/PdfController.cs
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
private readonly IPdfService _pdfService;
public PdfController(IPdfService pdfService)
{
_pdfService = pdfService;
}
[HttpPost("html-to-pdf")]
public IActionResult ConvertHtmlToPdf([FromBody] HtmlRequest request)
{
try
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
// Return as downloadable file
return File(pdfBytes, "application/pdf", "document.pdf");
}
catch (Exception ex)
{
return BadRequest($"Error generating PDF: {ex.Message}");
}
}
}
Imports Microsoft.AspNetCore.Mvc
<ApiController>
<Route("api/[controller]")>
Public Class PdfController
Inherits ControllerBase
Private ReadOnly _pdfService As IPdfService
Public Sub New(pdfService As IPdfService)
_pdfService = pdfService
End Sub
<HttpPost("html-to-pdf")>
Public Function ConvertHtmlToPdf(<FromBody> request As HtmlRequest) As IActionResult
Try
Dim pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent)
' Return as downloadable file
Return File(pdfBytes, "application/pdf", "document.pdf")
Catch ex As Exception
Return BadRequest($"Error generating PDF: {ex.Message}")
End Try
End Function
End Class
Em seguida, no arquivo HtmlRequest.cs, adicione o seguinte:
// Models/HtmlRequest.cs
public class HtmlRequest
{
public string HtmlContent { get; set; }
public string FileName { get; set; } = "document.pdf";
}
// Models/HtmlRequest.cs
public class HtmlRequest
{
public string HtmlContent { get; set; }
public string FileName { get; set; } = "document.pdf";
}
' Models/HtmlRequest.vb
Public Class HtmlRequest
Public Property HtmlContent As String
Public Property FileName As String = "document.pdf"
End Class
Isso configura um endpoint de API que converte HTML em um PDF para download. Quando alguém envia HTML para api/pdf/html-to-pdf, o PdfController delega a conversão para o serviço.
Uma vez criado, o controlador retorna o PDF como um arquivo para download. A requisição utiliza o modelo HtmlRequest, contendo o HTML e um nome de arquivo opcional. Isso facilita para os clientes o envio de HTML e o recebimento de um PDF bem elaborado.
Como faço para registrar os serviços?
Atualize seu Program.cs para registrar o serviço de PDF:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Register PDF service
builder.Services.AddSingleton<IPdfService, PdfService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// Register PDF service
builder.Services.AddSingleton<IPdfService, PdfService>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
Imports Microsoft.AspNetCore.Builder
Imports Microsoft.Extensions.DependencyInjection
Dim builder = WebApplication.CreateBuilder(args)
builder.Services.AddControllers()
builder.Services.AddEndpointsApiExplorer()
builder.Services.AddSwaggerGen()
' Register PDF service
builder.Services.AddSingleton(Of IPdfService, PdfService)()
Dim app = builder.Build()
If app.Environment.IsDevelopment() Then
app.UseSwagger()
app.UseSwaggerUI()
End If
app.UseHttpsRedirection()
app.MapControllers()
app.Run()
Como lidar com diferentes tipos de resposta?
Sua API deve suportar diferentes maneiras de retornar PDFs com base nas necessidades do cliente:
[HttpPost("generate")]
public IActionResult GeneratePdf([FromBody] PdfRequest request)
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
switch (request.ResponseType?.ToLower())
{
case "base64":
return Ok(new
{
data = Convert.ToBase64String(pdfBytes),
filename = request.FileName
});
case "inline":
return File(pdfBytes, "application/pdf");
default: // download
return File(pdfBytes, "application/pdf", request.FileName);
}
}
[HttpPost("generate")]
public IActionResult GeneratePdf([FromBody] PdfRequest request)
{
var pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent);
switch (request.ResponseType?.ToLower())
{
case "base64":
return Ok(new
{
data = Convert.ToBase64String(pdfBytes),
filename = request.FileName
});
case "inline":
return File(pdfBytes, "application/pdf");
default: // download
return File(pdfBytes, "application/pdf", request.FileName);
}
}
Imports Microsoft.AspNetCore.Mvc
<HttpPost("generate")>
Public Function GeneratePdf(<FromBody> request As PdfRequest) As IActionResult
Dim pdfBytes = _pdfService.GeneratePdfFromHtml(request.HtmlContent)
Select Case request.ResponseType?.ToLower()
Case "base64"
Return Ok(New With {
.data = Convert.ToBase64String(pdfBytes),
.filename = request.FileName
})
Case "inline"
Return File(pdfBytes, "application/pdf")
Case Else ' download
Return File(pdfBytes, "application/pdf", request.FileName)
End Select
End Function
Isso adiciona um ponto final flexível para geração de PDFs. Em vez de forçar downloads, o método GeneratePdf permite que os clientes escolham como receber os resultados: por download, diretamente no navegador ou codificados em Base64 para uso na API.
O modelo PdfRequest estende o HtmlRequest com uma opção ResponseType. Isso dá aos usuários controle sobre a entrega de PDFs, tornando a API mais versátil. Para lidar com PDFs na memória sem acesso ao sistema de arquivos, consulte a documentação de fluxo de memória do IronPDF .
Ao executarmos nosso programa, veremos esta saída no Swagger:

Como implementar operações comuns em PDF?
Vamos expandir nosso serviço para lidar com diversos cenários de geração de PDFs:
Como faço para converter URLs em PDF?
[HttpPost("url-to-pdf")]
public async Task<IActionResult> ConvertUrlToPdf([FromBody] UrlRequest request)
{
try
{
var pdfBytes = await Task.Run(() =>
_pdfService.GeneratePdfFromUrl(request.Url));
return File(pdfBytes, "application/pdf",
$"{request.FileName ?? "website"}.pdf");
}
catch (Exception ex)
{
return BadRequest($"Failed to convert URL: {ex.Message}");
}
}
public class UrlRequest
{
public string Url { get; set; }
public string FileName { get; set; }
}
[HttpPost("url-to-pdf")]
public async Task<IActionResult> ConvertUrlToPdf([FromBody] UrlRequest request)
{
try
{
var pdfBytes = await Task.Run(() =>
_pdfService.GeneratePdfFromUrl(request.Url));
return File(pdfBytes, "application/pdf",
$"{request.FileName ?? "website"}.pdf");
}
catch (Exception ex)
{
return BadRequest($"Failed to convert URL: {ex.Message}");
}
}
public class UrlRequest
{
public string Url { get; set; }
public string FileName { get; set; }
}
Imports System.Threading.Tasks
Imports Microsoft.AspNetCore.Mvc
<HttpPost("url-to-pdf")>
Public Async Function ConvertUrlToPdf(<FromBody> request As UrlRequest) As Task(Of IActionResult)
Try
Dim pdfBytes = Await Task.Run(Function() _pdfService.GeneratePdfFromUrl(request.Url))
Return File(pdfBytes, "application/pdf", $"{If(request.FileName, "website")}.pdf")
Catch ex As Exception
Return BadRequest($"Failed to convert URL: {ex.Message}")
End Try
End Function
Public Class UrlRequest
Public Property Url As String
Public Property FileName As String
End Class
Este endpoint converte URLs em PDFs para download. Quando uma solicitação POST atinge /api/pdf/url-to-pdf, o controlador usa _pdfService para converter a URL em bytes PDF em segundo plano e, em seguida, os retorna para download. Se a conversão falhar, o sistema responderá com uma mensagem de erro clara. Para sites que exigem autenticação, consulte a documentação de login do IronPDF .
Vamos tentar usar a URL "https://www.apple.com/nz "e teste a solicitação POST. Abaixo está a saída que obtivemos:
Qual é a aparência do resultado?

Como adiciono marcas d'água personalizadas?
public byte[] AddWatermarkFromFile(string filePath, string watermarkText)
{
// Load PDF directly from file
var pdf = PdfDocument.FromFile(filePath);
pdf.ApplyWatermark(
$"<h1 style='color:red;font-size:72px;'>{watermarkText}</h1>",
75,
IronPdf.Editing.VerticalAlignment.Middle,
IronPdf.Editing.HorizontalAlignment.Center
);
return pdf.BinaryData;
}
public byte[] AddWatermarkFromFile(string filePath, string watermarkText)
{
// Load PDF directly from file
var pdf = PdfDocument.FromFile(filePath);
pdf.ApplyWatermark(
$"<h1 style='color:red;font-size:72px;'>{watermarkText}</h1>",
75,
IronPdf.Editing.VerticalAlignment.Middle,
IronPdf.Editing.HorizontalAlignment.Center
);
return pdf.BinaryData;
}
Imports IronPdf
Public Function AddWatermarkFromFile(filePath As String, watermarkText As String) As Byte()
' Load PDF directly from file
Dim pdf = PdfDocument.FromFile(filePath)
pdf.ApplyWatermark(
$"<h1 style='color:red;font-size:72px;'>{watermarkText}</h1>",
75,
IronPdf.Editing.VerticalAlignment.Middle,
IronPdf.Editing.HorizontalAlignment.Center
)
Return pdf.BinaryData
End Function
Este procedimento carrega manualmente um arquivo local para fins de teste. Você pode ajustar isso para que sua API de PDF gere um PDF e, em seguida, aplique marcas d'água personalizadas facilmente. Para opções avançadas de marca d'água, incluindo marcas d'água em imagens e posicionamento personalizado, consulte o guia de marca d'água .
Qual é a aparência da marca d'água exibida?

Como adicionar dados dinâmicos com modelos?
Para aplicações práticas, você frequentemente precisará gerar PDFs a partir de modelos com dados dinâmicos:
[HttpPost("from-template")]
public IActionResult GenerateFromTemplate([FromBody] TemplateRequest request)
{
// Simple template replacement
var html = request.Template;
foreach (var item in request.Data)
{
html = html.Replace($"{{{{{item.Key}}}}}", item.Value);
}
var pdfBytes = _pdfService.GeneratePdfFromHtml(html);
return File(pdfBytes, "application/pdf", request.FileName);
}
public class TemplateRequest
{
public string Template { get; set; }
public Dictionary<string, string> Data { get; set; }
public string FileName { get; set; } = "document.pdf";
}
[HttpPost("from-template")]
public IActionResult GenerateFromTemplate([FromBody] TemplateRequest request)
{
// Simple template replacement
var html = request.Template;
foreach (var item in request.Data)
{
html = html.Replace($"{{{{{item.Key}}}}}", item.Value);
}
var pdfBytes = _pdfService.GeneratePdfFromHtml(html);
return File(pdfBytes, "application/pdf", request.FileName);
}
public class TemplateRequest
{
public string Template { get; set; }
public Dictionary<string, string> Data { get; set; }
public string FileName { get; set; } = "document.pdf";
}
Imports Microsoft.AspNetCore.Mvc
<HttpPost("from-template")>
Public Function GenerateFromTemplate(<FromBody> request As TemplateRequest) As IActionResult
' Simple template replacement
Dim html As String = request.Template
For Each item In request.Data
html = html.Replace($"{{{{{item.Key}}}}}", item.Value)
Next
Dim pdfBytes As Byte() = _pdfService.GeneratePdfFromHtml(html)
Return File(pdfBytes, "application/pdf", request.FileName)
End Function
Public Class TemplateRequest
Public Property Template As String
Public Property Data As Dictionary(Of String, String)
Public Property FileName As String = "document.pdf"
End Class
Para cenários avançados de modelos com Razor, Handlebars ou outros mecanismos, consulte a documentação de HTML para PDF do IronPDF . Você também pode explorar a conversão de CSHTML para PDF para aplicativos MVC e de Razor para PDF para aplicativos Blazor . Para renderização Razor sem interface gráfica, consulte o guia CSHTML sem interface gráfica .
Como otimizar o desempenho?
Ao construir uma API de PDF para produção, o desempenho é crucial. Aqui estão as principais estratégias de otimização:
Por que usar operações assíncronas?
Utilize programação assíncrona quando seus projetos envolverem operações de entrada/saída. Isso é especialmente útil quando o conteúdo do seu PDF provém de fontes externas, como:
- Baixando páginas HTML (
RenderUrlAsPdf) - Obtenção de imagens, CSS ou fontes via HTTP
- Leitura/gravação de arquivos em disco ou armazenamento em nuvem
Essas operações podem bloquear threads, mas o modo assíncrono impede que as threads da API fiquem ociosas. Para padrões abrangentes de geração assíncrona de PDFs, consulte o guia de geração assíncrona de PDFs .
Exemplo:
public async Task<byte[]> GeneratePdfFromHtmlAsync(string htmlContent)
{
return await Task.Run(() =>
{
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
});
}
public async Task<byte[]> GeneratePdfFromHtmlAsync(string htmlContent)
{
return await Task.Run(() =>
{
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
});
}
Imports System.Threading.Tasks
Public Async Function GeneratePdfFromHtmlAsync(htmlContent As String) As Task(Of Byte())
Return Await Task.Run(Function()
Dim pdf = _renderer.RenderHtmlAsPdf(htmlContent)
Return pdf.BinaryData
End Function)
End Function
Para cenários de geração paralela de PDFs, explore técnicas de multithreading e processamento paralelo .
Quais opções de renderização devo configurar?
Configure o IronPDF para obter o melhor desempenho:
_renderer.RenderingOptions.EnableJavaScript = false; // If JS not needed
_renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
_renderer.RenderingOptions.RenderDelay = 0; // Remove if no JS
_renderer.RenderingOptions.Timeout = 30; // Set reasonable timeout
_renderer.RenderingOptions.EnableJavaScript = false; // If JS not needed
_renderer.RenderingOptions.CssMediaType = PdfCssMediaType.Print;
_renderer.RenderingOptions.RenderDelay = 0; // Remove if no JS
_renderer.RenderingOptions.Timeout = 30; // Set reasonable timeout
Para obter opções abrangentes de configuração de renderização, incluindo configurações de viewport , tamanhos de papel personalizados e orientação da página , consulte a documentação de opções de renderização .
Como proteger sua API de PDF?
A segurança é essencial para qualquer API de produção. Aqui está uma abordagem simples para autenticação por chave de API:
// Middleware/ApiKeyMiddleware.cs
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private const string ApiKeyHeader = "X-API-Key";
public ApiKeyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.Request.Headers.TryGetValue(ApiKeyHeader, out var apiKey))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("API Key required");
return;
}
// Validate API key (in production, check against database)
var validApiKey = context.RequestServices
.GetRequiredService<IConfiguration>()["ApiKey"];
if (apiKey != validApiKey)
{
context.Response.StatusCode = 403;
await context.Response.WriteAsync("Invalid API Key");
return;
}
await _next(context);
}
}
// In Program.cs
app.UseMiddleware<ApiKeyMiddleware>();
// Middleware/ApiKeyMiddleware.cs
public class ApiKeyMiddleware
{
private readonly RequestDelegate _next;
private const string ApiKeyHeader = "X-API-Key";
public ApiKeyMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.Request.Headers.TryGetValue(ApiKeyHeader, out var apiKey))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("API Key required");
return;
}
// Validate API key (in production, check against database)
var validApiKey = context.RequestServices
.GetRequiredService<IConfiguration>()["ApiKey"];
if (apiKey != validApiKey)
{
context.Response.StatusCode = 403;
await context.Response.WriteAsync("Invalid API Key");
return;
}
await _next(context);
}
}
// In Program.cs
app.UseMiddleware<ApiKeyMiddleware>();
Imports Microsoft.AspNetCore.Http
Imports Microsoft.Extensions.Configuration
Imports System.Threading.Tasks
' Middleware/ApiKeyMiddleware.vb
Public Class ApiKeyMiddleware
Private ReadOnly _next As RequestDelegate
Private Const ApiKeyHeader As String = "X-API-Key"
Public Sub New(next As RequestDelegate)
_next = next
End Sub
Public Async Function InvokeAsync(context As HttpContext) As Task
Dim apiKey As String = Nothing
If Not context.Request.Headers.TryGetValue(ApiKeyHeader, apiKey) Then
context.Response.StatusCode = 401
Await context.Response.WriteAsync("API Key required")
Return
End If
' Validate API key (in production, check against database)
Dim validApiKey As String = context.RequestServices.GetRequiredService(Of IConfiguration)()("ApiKey")
If apiKey <> validApiKey Then
context.Response.StatusCode = 403
Await context.Response.WriteAsync("Invalid API Key")
Return
End If
Await _next(context)
End Function
End Class
' In Program.vb
app.UseMiddleware(Of ApiKeyMiddleware)()
Para cenários de autenticação avançada, considere:
- Autenticação JWT - Padrão da indústria para autenticação de API
- OAuth 2.0 - Para integrações de terceiros
- Integração com o Azure AD - Autenticação empresarial
- Limitação de taxa de API - Previna abusos e assegure o uso justo.
- Cabeçalhos HTTP - Configuração personalizada de cabeçalhos para maior segurança
Para garantir a segurança específica de PDFs, implemente proteção por senha , assinaturas digitais e higienização de PDFs para remover conteúdo potencialmente malicioso.
Como criar uma API de geração de faturas para o mundo real?
Vamos construir um endpoint prático para geração de faturas, demonstrando uma implementação completa. Este exemplo mostra como uma API .NET PDF de produção gera faturas profissionais com dados dinâmicos.
Comece a usar IronPDF no seu projeto hoje mesmo com um teste gratuito.
Primeiro, crie um novo arquivo na sua pasta Modelos. Aqui, eu chamei o meu de Invoice.cs. Em seguida, adicione o seguinte código:
public class Invoice
{
public string InvoiceNumber { get; set; }
public DateTime Date { get; set; }
public string CustomerName { get; set; }
public string CustomerAddress { get; set; }
public List<InvoiceItem> Items { get; set; }
public decimal Tax { get; set; }
}
public class InvoiceItem
{
public string Description { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal Total => Quantity * UnitPrice;
}
public class Invoice
{
public string InvoiceNumber { get; set; }
public DateTime Date { get; set; }
public string CustomerName { get; set; }
public string CustomerAddress { get; set; }
public List<InvoiceItem> Items { get; set; }
public decimal Tax { get; set; }
}
public class InvoiceItem
{
public string Description { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal Total => Quantity * UnitPrice;
}
Public Class Invoice
Public Property InvoiceNumber As String
Public Property [Date] As DateTime
Public Property CustomerName As String
Public Property CustomerAddress As String
Public Property Items As List(Of InvoiceItem)
Public Property Tax As Decimal
End Class
Public Class InvoiceItem
Public Property Description As String
Public Property Quantity As Integer
Public Property UnitPrice As Decimal
Public ReadOnly Property Total As Decimal
Get
Return Quantity * UnitPrice
End Get
End Property
End Class
Em seguida, crie um novo arquivo de serviço para o gerador de faturas. Na sua pasta Serviços, adicione o seguinte código. Criei um arquivo chamado InvoiceService.cs. Este código controla o estilo e o layout do seu PDF de fatura:
public class InvoiceService
{
private readonly ChromePdfRenderer _renderer;
public InvoiceService()
{
_renderer = new ChromePdfRenderer();
_renderer.RenderingOptions.MarginTop = 10;
_renderer.RenderingOptions.MarginBottom = 10;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GenerateInvoice(Invoice invoice)
{
var html = BuildInvoiceHtml(invoice);
// Add footer with page numbers
_renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
MaxHeight = 15,
HtmlFragment = "<center><i>{page} of {total-pages}</i></center>",
DrawDividerLine = true
};
var pdf = _renderer.RenderHtmlAsPdf(html);
return pdf.BinaryData;
}
private string BuildInvoiceHtml(Invoice invoice)
{
var subtotal = invoice.Items.Sum(i => i.Total);
var taxAmount = subtotal * (invoice.Tax / 100);
var total = subtotal + taxAmount;
var itemsHtml = string.Join("", invoice.Items.Select(item =>
$@"<tr>
<td>{item.Description}</td>
<td class='text-center'>{item.Quantity}</td>
<td class='text-right'>${item.UnitPrice:F2}</td>
<td class='text-right'>${item.Total:F2}</td>
</tr>"));
return $@"
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{
background-color: #f8f9fa;
padding: 20px;
margin-bottom: 20px;
}}
table {{
width: 100%;
border-collapse: collapse;
}}
th, td {{
padding: 10px;
border-bottom: 1px solid #ddd;
}}
th {{
background-color: #007bff;
color: white;
}}
.text-right {{ text-align: right; }}
.text-center {{ text-align: center; }}
.total-section {{
margin-top: 20px;
text-align: right;
}}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{invoice.InvoiceNumber}</h1>
<p>Date: {invoice.Date:yyyy-MM-dd}</p>
</div>
<div>
<h3>Bill To:</h3>
<p>{invoice.CustomerName}<br/>{invoice.CustomerAddress}</p>
</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{itemsHtml}
</tbody>
</table>
<div class='total-section'>
<p>Subtotal: ${subtotal:F2}</p>
<p>Tax ({invoice.Tax}%): ${taxAmount:F2}</p>
<h3>Total: ${total:F2}</h3>
</div>
</body>
</html>";
}
}
public class InvoiceService
{
private readonly ChromePdfRenderer _renderer;
public InvoiceService()
{
_renderer = new ChromePdfRenderer();
_renderer.RenderingOptions.MarginTop = 10;
_renderer.RenderingOptions.MarginBottom = 10;
_renderer.RenderingOptions.PrintHtmlBackgrounds = true;
}
public byte[] GenerateInvoice(Invoice invoice)
{
var html = BuildInvoiceHtml(invoice);
// Add footer with page numbers
_renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
MaxHeight = 15,
HtmlFragment = "<center><i>{page} of {total-pages}</i></center>",
DrawDividerLine = true
};
var pdf = _renderer.RenderHtmlAsPdf(html);
return pdf.BinaryData;
}
private string BuildInvoiceHtml(Invoice invoice)
{
var subtotal = invoice.Items.Sum(i => i.Total);
var taxAmount = subtotal * (invoice.Tax / 100);
var total = subtotal + taxAmount;
var itemsHtml = string.Join("", invoice.Items.Select(item =>
$@"<tr>
<td>{item.Description}</td>
<td class='text-center'>{item.Quantity}</td>
<td class='text-right'>${item.UnitPrice:F2}</td>
<td class='text-right'>${item.Total:F2}</td>
</tr>"));
return $@"
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{
background-color: #f8f9fa;
padding: 20px;
margin-bottom: 20px;
}}
table {{
width: 100%;
border-collapse: collapse;
}}
th, td {{
padding: 10px;
border-bottom: 1px solid #ddd;
}}
th {{
background-color: #007bff;
color: white;
}}
.text-right {{ text-align: right; }}
.text-center {{ text-align: center; }}
.total-section {{
margin-top: 20px;
text-align: right;
}}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{invoice.InvoiceNumber}</h1>
<p>Date: {invoice.Date:yyyy-MM-dd}</p>
</div>
<div>
<h3>Bill To:</h3>
<p>{invoice.CustomerName}<br/>{invoice.CustomerAddress}</p>
</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{itemsHtml}
</tbody>
</table>
<div class='total-section'>
<p>Subtotal: ${subtotal:F2}</p>
<p>Tax ({invoice.Tax}%): ${taxAmount:F2}</p>
<h3>Total: ${total:F2}</h3>
</div>
</body>
</html>";
}
}
Imports System
Imports System.Linq
Public Class InvoiceService
Private ReadOnly _renderer As ChromePdfRenderer
Public Sub New()
_renderer = New ChromePdfRenderer()
_renderer.RenderingOptions.MarginTop = 10
_renderer.RenderingOptions.MarginBottom = 10
_renderer.RenderingOptions.PrintHtmlBackgrounds = True
End Sub
Public Function GenerateInvoice(invoice As Invoice) As Byte()
Dim html = BuildInvoiceHtml(invoice)
' Add footer with page numbers
_renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
.MaxHeight = 15,
.HtmlFragment = "<center><i>{page} of {total-pages}</i></center>",
.DrawDividerLine = True
}
Dim pdf = _renderer.RenderHtmlAsPdf(html)
Return pdf.BinaryData
End Function
Private Function BuildInvoiceHtml(invoice As Invoice) As String
Dim subtotal = invoice.Items.Sum(Function(i) i.Total)
Dim taxAmount = subtotal * (invoice.Tax / 100)
Dim total = subtotal + taxAmount
Dim itemsHtml = String.Join("", invoice.Items.Select(Function(item) _
$"<tr>
<td>{item.Description}</td>
<td class='text-center'>{item.Quantity}</td>
<td class='text-right'>${item.UnitPrice:F2}</td>
<td class='text-right'>${item.Total:F2}</td>
</tr>"))
Return $"
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; }}
.invoice-header {{
background-color: #f8f9fa;
padding: 20px;
margin-bottom: 20px;
}}
table {{
width: 100%;
border-collapse: collapse;
}}
th, td {{
padding: 10px;
border-bottom: 1px solid #ddd;
}}
th {{
background-color: #007bff;
color: white;
}}
.text-right {{ text-align: right; }}
.text-center {{ text-align: center; }}
.total-section {{
margin-top: 20px;
text-align: right;
}}
</style>
</head>
<body>
<div class='invoice-header'>
<h1>Invoice #{invoice.InvoiceNumber}</h1>
<p>Date: {invoice.Date:yyyy-MM-dd}</p>
</div>
<div>
<h3>Bill To:</h3>
<p>{invoice.CustomerName}<br/>{invoice.CustomerAddress}</p>
</div>
<table>
<thead>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{itemsHtml}
</tbody>
</table>
<div class='total-section'>
<p>Subtotal: ${subtotal:F2}</p>
<p>Tax ({invoice.Tax}%): ${taxAmount:F2}</p>
<h3>Total: ${total:F2}</h3>
</div>
</body>
</html>"
End Function
End Class
Por fim, crie um novo controlador para acessar e criar faturas usando a API:
[ApiController]
[Route("api/[controller]")]
public class InvoiceController : ControllerBase
{
private readonly InvoiceService _invoiceService;
public InvoiceController(InvoiceService invoiceService)
{
_invoiceService = invoiceService;
}
[HttpPost("generate")]
public IActionResult GenerateInvoice([FromBody] Invoice invoice)
{
try
{
var pdfBytes = _invoiceService.GenerateInvoice(invoice);
var fileName = $"Invoice_{invoice.InvoiceNumber}.pdf";
return File(pdfBytes, "application/pdf", fileName);
}
catch (Exception ex)
{
return StatusCode(500, $"Error generating invoice: {ex.Message}");
}
}
}
[ApiController]
[Route("api/[controller]")]
public class InvoiceController : ControllerBase
{
private readonly InvoiceService _invoiceService;
public InvoiceController(InvoiceService invoiceService)
{
_invoiceService = invoiceService;
}
[HttpPost("generate")]
public IActionResult GenerateInvoice([FromBody] Invoice invoice)
{
try
{
var pdfBytes = _invoiceService.GenerateInvoice(invoice);
var fileName = $"Invoice_{invoice.InvoiceNumber}.pdf";
return File(pdfBytes, "application/pdf", fileName);
}
catch (Exception ex)
{
return StatusCode(500, $"Error generating invoice: {ex.Message}");
}
}
}
Imports Microsoft.AspNetCore.Mvc
<ApiController>
<Route("api/[controller]")>
Public Class InvoiceController
Inherits ControllerBase
Private ReadOnly _invoiceService As InvoiceService
Public Sub New(invoiceService As InvoiceService)
_invoiceService = invoiceService
End Sub
<HttpPost("generate")>
Public Function GenerateInvoice(<FromBody> invoice As Invoice) As IActionResult
Try
Dim pdfBytes = _invoiceService.GenerateInvoice(invoice)
Dim fileName = $"Invoice_{invoice.InvoiceNumber}.pdf"
Return File(pdfBytes, "application/pdf", fileName)
Catch ex As Exception
Return StatusCode(500, $"Error generating invoice: {ex.Message}")
End Try
End Function
End Class
Para funcionalidades avançadas de faturação, considere adicionar códigos de barras , códigos QR , números de página e cabeçalhos/rodapés personalizados . Você também pode implementar a conformidade com o PDF/A para arquivamento de longo prazo ou integrá-la a fluxos de trabalho de assinatura eletrônica .
Qual é o formato da fatura emitida?

Quais são as considerações para a implantação de contêineres?
Embora este tutorial se concentre no desenvolvimento local, aqui está uma breve visão geral da conteinerização da sua API de PDF:
Como criar um Dockerfile básico?
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["PdfApiService.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet build -c Release -o /app/build
FROM build AS publish
RUN dotnet publish -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
# IronPDF requires additional dependencies on Linux
RUN apt-get update && apt-get install -y \
libgdiplus \
libc6-dev \
libx11-dev \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["dotnet", "PdfApiService.dll"]
Para obter guias de implantação detalhados para sua API .NET PDF, consulte:
- Documentação do IronPDF para Docker - Guia completo de conteinerização
- Implantação do IronPDF no Azure - Azure Functions e Serviço de Aplicativos
- Implantação do IronPDF na AWS - Implantação do Lambda e do EC2
- Configuração do IronPDF para Linux - Configuração específica para Linux
- Executando como contêiner remoto - conteinerização do IronPDF Engine
- Mecanismo nativo vs. mecanismo remoto - opções de arquitetura de implantação
Quais são as melhores práticas para tratamento de erros?
Para programas tolerantes a falhas, implemente um manipulador de erros global para respostas de erro consistentes:
// Middleware/ErrorHandlingMiddleware.cs
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlingMiddleware> _logger;
public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred processing request {Path}", context.Request.Path);
await HandleExceptionAsync(context, ex);
}
}
private static async Task HandleExceptionAsync(HttpContext context, Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = ex switch
{
ArgumentNullException => 400,
UnauthorizedAccessException => 401,
_ => 500
};
var response = new
{
error = "An error occurred processing your request",
message = ex.Message,
statusCode = context.Response.StatusCode
};
await context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
}
// Middleware/ErrorHandlingMiddleware.cs
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlingMiddleware> _logger;
public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred processing request {Path}", context.Request.Path);
await HandleExceptionAsync(context, ex);
}
}
private static async Task HandleExceptionAsync(HttpContext context, Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = ex switch
{
ArgumentNullException => 400,
UnauthorizedAccessException => 401,
_ => 500
};
var response = new
{
error = "An error occurred processing your request",
message = ex.Message,
statusCode = context.Response.StatusCode
};
await context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
}
' Middleware/ErrorHandlingMiddleware.vb
Public Class ErrorHandlingMiddleware
Private ReadOnly _next As RequestDelegate
Private ReadOnly _logger As ILogger(Of ErrorHandlingMiddleware)
Public Sub New(ByVal [next] As RequestDelegate, ByVal logger As ILogger(Of ErrorHandlingMiddleware))
_next = [next]
_logger = logger
End Sub
Public Async Function InvokeAsync(ByVal context As HttpContext) As Task
Try
Await _next(context)
Catch ex As Exception
_logger.LogError(ex, "An error occurred processing request {Path}", context.Request.Path)
Await HandleExceptionAsync(context, ex)
End Try
End Function
Private Shared Async Function HandleExceptionAsync(ByVal context As HttpContext, ByVal ex As Exception) As Task
context.Response.ContentType = "application/json"
context.Response.StatusCode = If(TypeOf ex Is ArgumentNullException, 400, If(TypeOf ex Is UnauthorizedAccessException, 401, 500))
Dim response = New With {
.error = "An error occurred processing your request",
.message = ex.Message,
.statusCode = context.Response.StatusCode
}
Await context.Response.WriteAsync(JsonSerializer.Serialize(response))
End Function
End Class
Para cenários específicos de resolução de problemas do IronPDF , consulte:
Pronto para criar sua API de PDF .NET para produção?
Você acabou de criar uma API .NET PDF robusta usando ASP.NET Core e IronPDF , capaz de lidar com diversos cenários de geração de documentos. Esta API REST fornece uma base sólida para operações centralizadas de PDF em seus aplicativos.
Principais conclusões:
- O IronPDF simplifica a geração de PDFs em projetos de API Web com renderização baseada no Chrome .
- Edite facilmente PDFs existentes com as ferramentas avançadas de edição do IronPDF.
- Os princípios de design RESTful garantem que sua API de PDF seja intuitiva e de fácil manutenção.
- O tratamento adequado de erros e as medidas de segurança são essenciais para a produção.
- A otimização de desempenho por meio de operações assíncronas e armazenamento em cache melhora a escalabilidade.
- Suporte completo para aplicações desktop e web com soluções de documentos escaláveis.
O IronPDF permite que os desenvolvedores criem PDFs, salvem arquivos PDF e convertam HTML de forma eficiente, tornando-se a API de PDF essencial para aplicativos modernos do .NET Framework .
Quais são os próximos passos?
Pronto para implementar o IronPDF em sua API de PDF .NET de produção? Eis as suas próximas ações:
- Inicie seu teste gratuito - Teste o IronPDF com todas as funcionalidades em seu ambiente de desenvolvimento.
- Explore recursos avançados - Confira assinaturas digitais , formulários em PDF , conformidade com PDF/A , gerenciamento de metadados e outros recursos avançados de PDF .
- Expanda com confiança - Analise as opções de licenciamento para as suas necessidades de API de produção, incluindo extensões e atualizações .
Crie sua API de PDF for .NET hoje mesmo e simplifique a geração de documentos em todo o seu ecossistema de aplicativos com o IronPDF!
Perguntas frequentes
Para que serve o IronPDF em aplicações .NET?
O IronPDF é usado para gerar, manipular e converter PDFs em aplicativos .NET, tornando-o ideal para a criação de serviços de PDF centralizados.
Como posso integrar o IronPDF com o ASP.NET Core?
O IronPDF pode ser integrado ao ASP.NET Core instalando o pacote NuGet IronPDF, permitindo que você crie um serviço centralizado de geração de PDFs.
Quais são as principais funcionalidades do IronPDF para geração de PDFs?
Os principais recursos do IronPDF incluem conversão de HTML para PDF, mesclagem e divisão de PDFs, adição de cabeçalhos e rodapés e extração de texto e imagens.
O IronPDF consegue lidar com layouts de PDF complexos?
Sim, o IronPDF consegue lidar com layouts de PDF complexos devido à sua capacidade de converter conteúdo HTML e CSS em documentos PDF renderizados com precisão.
É possível personalizar a criação de PDFs com o IronPDF?
Sim, o IronPDF permite a personalização na criação de PDFs, incluindo a configuração do tamanho da página, margens e a adição de marcas d'água ou anotações.
O IronPDF oferece suporte a recursos de segurança de PDF?
O IronPDF oferece suporte a recursos de segurança de PDF, como proteção por senha e criptografia, para proteger os documentos PDF gerados.
Quais formatos o IronPDF pode converter em PDFs?
O IronPDF consegue converter diversos formatos em PDFs, incluindo HTML, URLs e arquivos ASPX, o que o torna versátil para diferentes casos de uso.
Como o IronPDF lida com a geração de PDFs em larga escala?
O IronPDF é otimizado para desempenho, permitindo que ele lide com eficiência com tarefas de geração de PDFs em larga escala em aplicativos .NET.
O IronPDF pode ser usado em aplicações baseadas na nuvem?
Sim, o IronPDF pode ser usado em aplicações baseadas na nuvem, suportando implantação em plataformas como Azure e AWS para serviços de PDF escaláveis.
Quais versões do .NET o IronPDF suporta?
O IronPDF suporta várias versões do .NET, incluindo .NET Core e .NET Framework, garantindo compatibilidade com uma ampla gama de projetos.


