Generating PDFs in .NET Core Web API

Creating PDF documents on the fly is a common requirement in web applications, whether it's for generating invoices, certificates, reports, or any other type of document. In this guide, we’ll walk through the process of generating PDFs in a .NET Core Web API using the iText7 library. We'll create a sample project to demonstrate the process of generating a certificate PDF.

Step 1. Setup Your .NET Core Web API Project
 

Create a New Web API project

Open your terminal or command prompt and run the following command to create a new Web API project.

dotnet new webapi -n PdfGenerationDemo
cd PdfGenerationDemo

Install Necessary NuGet packages

We will use iText7 for PDF generation. Install it using the following command.

dotnet add package itext7

Step 2. Create Your Models

Create a model to represent the data needed for the certificate. Add a new class CertificateModel.cs in the Models folder.

namespace PdfGenerationDemo.Models
{
    public class CertificateModel
    {
        public string Full_Name { get; set; }
        public string University_Name { get; set; }
        public string Mobile_Number { get; set; }
        public string Email { get; set; }
        public string CampName { get; set; }
        public string From_Date { get; set; }
        public string To_Date { get; set; }
        public string Description { get; set; }
        public string Duration { get; set; }
        public string Institute_Name { get; set; }
        public string Nss_Logo { get; set; }
        public string ProfileImageBase64 { get; set; }
    }
}

Step 3. Create Your Controller

Add a new controller CertificateController.cs in the Controllers folder.

using Microsoft.AspNetCore.Mvc;
using PdfGenerationDemo.Models;
using System;
using System.IO;
using System.Threading.Tasks;
using iText.Html2pdf;
using iText.Kernel.Pdf;
namespace PdfGenerationDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CertificateController : ControllerBase
    {
        [HttpPost]
        [Route("GenerateCertificate")]
        public async Task<IActionResult> GenerateCertificate([FromBody] CertificateModel request)
        {
            if (request == null)
            {
                return BadRequest("Invalid request data.");
            }

            try
            {
                byte[] pdfBytes = GeneratePDF(request);
                string base64String = Convert.ToBase64String(pdfBytes);

                return Ok(new { Success = true, PdfBase64 = base64String });
            }
            catch (Exception ex)
            {
                return StatusCode(500, $"Internal server error: {ex.Message}");
            }
        }
        private byte[] GeneratePDF(CertificateModel request)
        {
            string body = Template_Body(request);
            using (MemoryStream outputStream = new MemoryStream())
            {
                PdfWriter writer = new PdfWriter(outputStream);
                PdfDocument pdfDoc = new PdfDocument(writer);
                pdfDoc.SetDefaultPageSize(iText.Kernel.Geom.PageSize.A4);

                HtmlConverter.ConvertToPdf(body, pdfDoc);

                return outputStream.ToArray();
            }
        }
        private string Template_Body(CertificateModel request)
        {
            string logoBase64 = request.Logo;
            string photoBase64 = Convert.ToBase64String(Convert.FromBase64String(request.ProfileImageBase64));

            return $@"
<html>
<head>
    <style type='text/css'>
        body, html {{
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            font-family: Georgia, serif;
        }}
        .container {{
            border: 15px solid #888;
            width: 90%;
            margin: 0 auto;
            padding: 20px;
            background-color: white;
            box-shadow: 0 0 10px rgba(0,0,0,0.5);
            text-align: center;
        }}
        .logo img {{
             width: 300px;
             margin-bottom: 15px;
        }}
        .marquee {{
            color: tan;
            font-size: 36px;
            margin: 10px 0;
        }}
        .assignment {{
            font-size: 20px;
            margin: 20px 0;
        }}
        .person {{
            border-bottom: 2px solid black;
            font-size: 24px;
            font-style: italic;
            margin: 20px auto;
            width: 80%;
            display: inline-block;
        }}
        .details {{
            font-size: 18px;
            margin: 20px 0;
        }}
        .photo img {{
            border: 1px solid #ddd;
            border-radius: 100%;
            padding: 0px;
            width: 150px;
        }}
        .reason {{
            margin: 20px 0;
            font-size: 18px;
        }}
        .signature {{
            margin-top: 50px;
            font-size: 18px;
        }}
        .signature .sig-line {{
            border-bottom: 1px solid black;
            width: 50%;
            margin: 20px auto;
        }}
        .footer {{
            font-size: 14px;
            color: #aaa;
            margin-top: 30px;
        }}
    </style>
</head>
<body>
    <div class='container'>
        <div class='logo'>
            <img src='data:image/png;base64,{logoBase64}' alt='Logo'>
        </div>
        <div class='marquee'>
            Certificate of NSS
        </div>
        <div class='assignment'>
            {request.University_Name}
        </div>
        <div class='assignment'>
            This certificate is presented to
        </div>
        <div class='photo'>
            <img src='data:image/jpeg;base64,{photoBase64}' alt='Student Photo'>
        </div>
        <div class='person'>
            {request.Full_Name}
        </div>
        <div class='details'>
            <p>Number: {request.Mobile_Number}</p>
            <p>Email: {request.Email}</p>
            <p>Camp Name: {request.CampName}</p>
            <p>Camp Time: {request.From_Date} To {request.To_Date}</p>
            <p>Description: {request.Description}</p>
        </div>
        <div class='reason'>
            For Participation in Camp of {request.Duration}  With College<br />
        </div>
       <div class='reason'>
               {request.Institute_Name}<br />
       </div>
        <div class='signature'>
            <p>Authorized Signature</p>
            <div class='sig-line'></div>
        </div>
        <div class='footer'>
            <p>© 2024 An Organization. All Rights Reserved.</p>
        </div>
    </div>
</body>
</html>";
        }
    }
}

Step 4. Testing the API

You can test the API using a tool like Postman. Here’s how you can do it.

Run Your Project

dotnet run

Get the Response

The response will contain a base64 encoded string of the generated PDF.

PDF

The response will contain a base64 encoded string of the generated PDF.

Encoded String

Conclusion

In this guide, we covered how to generate PDFs in a .NET Core Web API using the iText7 library. We walked through setting up the project, creating models, writing the controller, and testing the API. This approach can be extended and customized as needed for various use cases involving dynamic PDF generation.


Similar Articles