Creating an ASP.NET Minimal Web API to Generate PDF Documents from HTML Template Dynamically
Detailed Blog page Skeleton loader
Creating an ASP.NET Minimal Web API to Generate PDF Documents from HTML Template Dynamically

Generating PDFs from dynamic HTML can be a daunting task. However, with the appropriate tools, it can be hassle free. The Syncfusion HTML-to-PDF converter library, in combination with ASP.NET Core Minimal Web API, offers a straightforward approach for dynamically generating PDFs from HTML templates.

This tutorial will teach us how to create an ASP.NET Core Minimal Web API that dynamically generates a PDF document from an HTML template using the Syncfusion HTML-to-PDF converter library.HTML-to-PDF conversion architecture

Advantage

  • This approach allows for a streamlined and efficient process for creating professional-looking PDFs, as well as providing greater control over the design and layout of the document.
  • This can handle intricate HTML content, including tables, images, and styles, ensuring that the resultant PDF document closely resembles the source HTML. It supports modern features like HTML5, CSS3, SVG, and web fonts.

Here are the steps to create a job application from an HTML template using ASP.NET Core Minimal API in C#,

Seamlessly convert webpages and other complex HTML content to PDF with a comprehensive API set.

Create an HTML template with CSS styling

HTML Template

In an HTML file, define your page’s structure, including the head and body sections and any other elements you’d like to include, such as image, header, footer, etc.

Also, it contains placeholders with {{mustache}} syntax, and it is used to bind the actual data to the HTML template. We’ll use the Scriban scripting language to create the placeholders which is a lightweight scripting language and engine for .NET

Note: To learn more about the Scriban scripting language, refer to the documentation.

HTML

<html lang="en">
 <head>
  <meta charset="UTF-8" />
  <title>JobOfferLetter</title>
  <link rel="stylesheet" href="style.css" media="all" />
 </head>
 
 <body>
  <div class="grid-container ">
   <img class="logo" src="logo.png" style="width:70px;height:70px;margin-left: 50px;" />
   <div style="margin-left:70px; margin-top:55px">
    <b>
     AMAZE <br />
     FOX
    </b>
   </div>
   <div style="font-size: 12px; margin-left: 300px; margin-top: 55px">
    <div><b>{{company_details.street}} </b></div>
    <div><b>{{company_details.city}} </b></div>
    <div><b>Phone: {{company_details.phone}} </b></div>
    <div><b>{{company_details.website}} </b></div>
   </div>
  </div>
  <br />
  <div class="body-content" 
style="margin-left: 50px;"> <p><b>Dear {{employee_details.name}},</b></p> <p>We are pleased to offer you the position of Accountant at {{company_details.company_name}}. We are confident that you will contribute your skills and experience towards the growth of our organization.</p> <p>As per the discussion, your starting date will be {{employee_details.joining_date}}. Please find the employee handbook enclosed herewith which contains the medical and retirement benefits offered by our organizations.</p> <p>Please confirm your acceptance of this offer by signing and returning a copy of this offer letter.</p> <p>If you have any questions regarding the same, contact the manager or me via email or phone: {{company_details.phone}}</p> <p>We look forward to welcoming you on board.</p> </div> <div class="body-content"
style="margin-left: 50px;"> <p><b>Sincerely,<br /> {{company_details.company_name}} <br />{{company_details.employer_name}} <br />(Managing Director)</b></p> </div> <div id="footer"> <div class="footer-columns"
style="margin-left: 50px;"> <p>{{company_details.company_name}}</p> <p>{{company_details.website}}</p> </div> </div> </body> </html>

By default, the properties and methods of .NET objects are automatically exposed with lowercase and _ names. This means that a property like CompanyName will be exposed as company_name, and while performing the conversion, the values can be imported from the respective JSON files.

Creating an HTML template

CSS Styling

Create a CSS file to control the appearance of your HTML template. In this CSS file, you’ll define styles for your page elements, such as font sizes, colors, and images.

You can get this HTML template with CSS and fonts from this GitHub repository.

The following screenshot shows the output of the HTML template with styled CSS.Output of the HTML template with styled CSS

Furthermore, any additional resources, such as fonts, images, JSON files, etc., should be in the same folder as the HTML file. Please refer to the screenshot below for visual reference.Resource files

Create a minimal Web API project with ASP.NET Core

Minimal APIs are architected to create HTTP APIs with minimal dependencies. They are ideal for microservices and apps that want to include only the minimum files, features, and dependencies in ASP.NET Core.

Kindly refer to this tutorial to create a minimal API with ASP.NET Core using Visual Studio 2022.

The program.cs file involves receiving files, such as HTML, JSON, and assets (such as fonts, images, etc.), from a client request.

Finally, the HTML text, JSON data, and assets are combined and converted into a PDF document using HtmlToPdfConverter.

app.MapPost("/api/convertToPDF", async (HttpContext context) =>
{
    try
    {
        var html = await context.Request.ReadFormAsync();
        var value = html.AsQueryable().ToList().Where(x => x.Key == "application/json").FirstOrDefault().Value.ToString();
        var options = JsonConvert.DeserializeObject<ConversionOptions>(value);
 
        string htmlText = "";
        string jsonData = "";
        if (options != null)
        {
            htmlText = ReadText(html.Files[options.Index].OpenReadStream());
            jsonData = ReadText(html.Files[options.Data].OpenReadStream());
            CopyAssets(options.Assets, html.Files);
        }
 
        String path = Path.GetFullPath("template/");
        var converter = new HtmlToPdfConversion();
        var pdfDocument = converter.ConvertToPDF(htmlText, path, jsonData, options); 
        context.Response.ContentType = "application/pdf";
        await context.Response.Body.WriteAsync(pdfDocument);
    }
    catch (Exception exception)
    {
    }
});
 
app.UseCors("AllowBlazorClient");
app.Run();

void CopyAssets(List<string> assets, IFormFileCollection files)
{
    if (Directory.Exists("template/"))
    {
        System.IO.DirectoryInfo di = new DirectoryInfo("template/");
        foreach (FileInfo file in di.GetFiles())
        {
            file.Delete();
        }
    }
    else
        Directory.CreateDirectory("template/");
 
    var formFiles = files.ToList();
    foreach (var asset in assets)
    {
        Stream stream = formFiles.FirstOrDefault(x => x.FileName == asset).OpenReadStream();
        if (stream != null)
        {
            var fileStream = new FileStream("template/" + asset, FileMode.Create);
            stream.CopyTo(fileStream);
            fileStream.Close();
            stream.Close();
        }
    }
}
string ReadText(Stream stream)
{
    StreamReader reader = new StreamReader(stream);
    string text = reader.ReadToEnd();
    reader.Close();
    strem.Dispose();
    return text;
}

Next, the HtmlToPdfConverter converts the HTML string, accompanied by the assets, into a PDF document via the blink rendering engine within the HtmlToPdfConversion.cs file. During this conversion, we established the size and margin of the PDF page and the viewport size using the BlinkConverterSettings class. Please refer to the accompanying code example for further information.

//Fill the template with real job offer letter data and assets 
var expando = JsonConvert.DeserializeObject<ExpandoObject>(modelData);
var sObject = BuildScriptObject(expando);
var templateCtx = new Scriban.TemplateContext();
templateCtx.PushGlobal(sObject);
var template = Scriban.Template.Parse(pageContent);
var result = template.Render(templateCtx);

//Initialize HTML to PDF converter with Blink rendering engine
HtmlToPdfConverter htmlConverter = new HtmlToPdfConverter();

//Initialize blink converter settings to set the page size
BlinkConverterSettings blinkConverterSettings = new BlinkConverterSettings();
if (options.Width != 0 && options.Height != 0)
{
    blinkConverterSettings.PdfPageSize = new Syncfusion.Drawing.SizeF(options.Width, options.Height);
}
else
{
    blinkConverterSettings.ViewPortSize = new Syncfusion.Drawing.Size(595, 842);
}

blinkConverterSettings.Margin = new PdfMargins() { All = options.Margin };
htmlConverter.ConverterSettings = blinkConverterSettings;

//Convert HTML string to PDF
PdfDocument document = htmlConverter.Convert(result, path);

MemoryStream output = new MemoryStream();

//Save and close the PDF document 
document.Save(output);
document.Close(true);

A to Z about Syncfusion’s versatile HTML-to-PDF converter and its rich feature set.

Create Blazor WebAssembly application (client)

The client application in this implementation is a Blazor WebAssembly application built with .NET version 7.0. To create a new ASP.NET Core Blazor WebAssembly application using Visual Studio 2022, please follow this documentation. Within the application, we utilize the HttpClient.PostAsync method to send a POST request to the specified URI as an asynchronous operation.

//Send a request to the server
var response = await client.PostAsync("https://localhost:7045/api/convertToPDF", content);

Incorporating HTML files and additional assets

The inclusion of the HTML and CSS files in the HttpClient is necessary. Additionally, supplementary assets such as fonts, images, and PDF size specifications should be sent with the request using the MultipartFormDataContent.

private async Task ConvertToPDF()
{
    //Create an http client to send both files and json data
    using (var client = new HttpClient())
    {
            //Create multipart form data content
            using (var content = new MultipartFormDataContent())
            {
                var html = await Http.GetByteArrayAsync(" JobOfferLetter /index.html");
                var css = await Http.GetByteArrayAsync(" JobOfferLetter /style.css");
                var data = await Http.GetByteArrayAsync(" JobOfferLetter /Data.json");
                var logo = await Http.GetByteArrayAsync(" JobOfferLetter /logo.png");
                var font = await Http.GetByteArrayAsync(" JobOfferLetter / OpenSans-Regular.ttf");
 
                //Add file to content
                content.Add(CreateContent("index.html", "index.html", html));
                content.Add(CreateContent("style.css", "style.css", css));
                content.Add(CreateContent("Data.json", "Data.json", data));
                content.Add(CreateContent("logo.png", "logo.png", logo));
                content.Add(CreateContent(" OpenSans-Regular.ttf", " OpenSans-Regular.ttf", font));
                var json = new JsonObject
                {
                        ["index"] = "index.html",
                        ["data"] = "Data.json",
                        ["width"] = 0,
                        ["height"] = 0,
                        ["margin"] = 40,
                        ["assets"] = new JsonArray
                        {
                           "style.css",
                           "logo.png",
                          " OpenSans-Regular.ttf"
                        }
                };
            //Add json data to content
            content.Add(new StringContent(json.ToString()), "application/json");

            //Send a request to the server
            var response = await client.PostAsync("https://localhost:7045/api/convertToPDF", content);
            if (response.StatusCode == HttpStatusCode.OK)
            {
                  var responseContent = await response.Content.ReadAsStreamAsync();
                  using var Content = new DotNetStreamReference(stream: responseContent);
                  await JS.InvokeVoidAsync("SubmitHTML", "HTMLToPDF.pdf", Content);
            }
        }
   }
}

Once the requested response status code is OK, invoke the JavaScript (JS) function in the index.html file to save the PDF document.

<script>
    window.SubmitHTML = async (fileName, contentStreamReference) => {
        const arrayBuffer = await contentStreamReference.arrayBuffer();
        const blob = new Blob([arrayBuffer]);
        const url = URL.createObjectURL(blob);
        const anchorElement = document.createElement('a');
        anchorElement.href = url;
        anchorElement.download = fileName ?? '';
        anchorElement.click();
        anchorElement.remove();
        URL.revokeObjectURL(url);
    }
</script>

While building and running the application, the website will open in your default browser.

Blazor WebAssembly HTML-to-PDF conversion app

Check out our demo of converting URLs to PDFs with custom features.

Launching the Server and Invoking the PDF Generation API from the Client

Here are the steps to launching the server and invoking the PDF generation API from the client application.

Step 1: Run the Web API application to launch the published web API in the browser.

Step 2: To generate a PDF document using the client application, send an asynchronous POST request to the specified URI (e.g., https://localhost:7094/api/convertToPDF) on the localhost. This will send the request to the server application, which will convert the HTML to PDF and send the response back to the client. After running the client application, click the Convert to PDF button to initiate the HTML to PDF conversion process and generate a PDF document named HTMLToPDF.pdf in the designated folder.

The following screenshot illustrates that you will receive a PDF document upon successful conversion.Converting an HTML content to PDF 

GitHub Samples

For better understanding, we have committed the source for this project in the Generate PDF from the HTML C# GitHub repository.

Join thousands of developers who rely on Syncfusion for their PDF needs. Experience the difference today!

Conclusion

In this blog post, we have learned how to generate PDF documents from an HTML template using Syncfusion HTML to PDF library in combination with ASP.NET Core minimal API.

Take a moment to look at the documentation, where you will find other options and features, all with accompanying code samples.

Please let us know in the comments below if you have any questions about these features. You can also contact us through our support forum, support portal, or feedback portal. We are happy to assist you!

Related Blogs

If you liked this article, we think you would also like the following articles about PDF Library:

Be the first to get updates

Sowmiya Loganathan

Meet the Author

Sowmiya Loganathan

Sowmiya is a software engineer at Syncfusion. She has been a .NET developer since 2016 and has specialized skills in PDF file format.

Comments (2)

How can I integrate this into an existing Wasm application with hosted?

Prakash Viswanathan
Prakash Viswanathan
@ Boot Dat  

Our HTML to PDF converter only works on the Blazor server side. At present it is not supported in Blazor WebAssembly. You can call the web service from Blazor WebAssembly to convert a HTML template to PDF.

Comments are closed.