Html To Pdf with .NET Core and Azure Functions

SelectPdf and Azure FunctionsAzure Functions allows you to run small pieces of code (called “functions”) without worrying about application infrastructure. With Azure Functions, the cloud infrastructure provides all the up-to-date servers you need to keep your application running at scale.

SelectPdf offered a .NET Core version for some time, but although it worked on some types of Azure deployments, it was not supported on Azure functions, due to some platform restrictions.


Things have changed starting with Azure Functions V3 and SelectPdf Library can run in an Azure Function. There are a few other things to take into account: similar to Azure Web Apps deployments, SelectPdf will use a restricted rendering engine to be able to run in an Azure Function. The hosting plan should be Premium or App Service Plan, starting with Standard. SelectPdf will not work with an Azure Consumption Plan nor with a Free or Shared App Service Plan.

SelectPdf and Azure Functions Sample

The following sample was created in Visual Studio 2019 and uses Azure Functions V3 with .NET Core 3.1. It shows how to read several parameters received through a GET or POST request (x-www-form-urlencoded or json encoded) and how to convert to pdf the specified url or html string.

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace SelectPdf.AzureFunctions.Sample
{
    public static class ConvertToPdf
    {
        /// <summary>
        /// Use this function to convert an url or html to pdf using SelectPdf. 
        /// The function shows how you can send a few parameters 
        /// through GET or POST (x-www-form-urlencoded or json encoded).
        /// Send at least the "url" or "html" parameter.
        /// Other parameters are also supported (see code).
        /// </summary>
        /// <returns></returns>
        [FunctionName("ConvertToPdf")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("Starting the conversion to pdf...");

            try
            {
                // read parameters from query string
                string url = req.Query["url"];
                string html = req.Query["html"];
                string base_url = req.Query["base_url"];
                string page_size = req.Query["page_size"];
                string page_orientation = req.Query["page_orientation"];
                string web_page_width_str = req.Query["web_page_width"];
                string web_page_height_str = req.Query["web_page_height"];

                // read from POST if encoding is application/x-www-form-urlencoded
                if (req.ContentType?.ToLower() == "application/x-www-form-urlencoded")
                {
                    url = url ?? req.Form["url"];
                    html = html ?? req.Form["html"];
                    base_url = base_url ?? req.Form["base_url"];
                    page_size = page_size ?? req.Form["page_size"];
                    page_orientation = page_orientation ?? req.Form["page_orientation"];
                    web_page_width_str = web_page_width_str ?? req.Form["web_page_width"];
                    web_page_height_str = web_page_height_str ?? req.Form["web_page_height"];
                }
                // read from POST if encoding is application/json
                else if (req.ContentType?.ToLower() == "application/json")
                {
                    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
                    dynamic postData = JsonConvert.DeserializeObject(requestBody);

                    url = url ?? postData?.url;
                    html = html ?? postData?.html;
                    base_url = base_url ?? postData?.base_url;
                    page_size = page_size ?? postData?.page_size;
                    page_orientation = page_orientation ?? postData?.page_orientation;
                    web_page_width_str = web_page_width_str ?? postData?.web_page_width;
                    web_page_height_str = web_page_height_str ?? postData?.web_page_height;
                }

                // parse parameters
                log.LogInformation("Parsed url: " + url?.ToString());
                log.LogInformation("Parsed html: " + html?.ToString());
                log.LogInformation("Parsed base_url: " + base_url?.ToString());

                int web_page_width = 1024;
                if (!string.IsNullOrEmpty(web_page_width_str))
                {
                    try
                    {
                        web_page_width = Convert.ToInt32(web_page_width_str);
                    }
                    catch { }
                }
                log.LogInformation("Parsed web_page_width: " + web_page_width);

                int web_page_height = 0;
                if (!string.IsNullOrEmpty(web_page_height_str))
                {
                    try
                    {
                        web_page_height = Convert.ToInt32(web_page_height_str);
                    }
                    catch { }
                }
                log.LogInformation("Parsed web_page_height: " + web_page_height);

                // pdf page size
                PdfPageSize pageSize = PdfPageSize.A4;
                try
                {
                    pageSize = (PdfPageSize)Enum.Parse(typeof(PdfPageSize), page_size, true);
                }
                catch { }
                log.LogInformation("Parsed page_size: " + pageSize.ToString());

                // pdf orientation
                PdfPageOrientation pdfOrientation = PdfPageOrientation.Portrait;
                try
                {
                    pdfOrientation = (PdfPageOrientation)Enum.Parse(
                        typeof(PdfPageOrientation), page_orientation, true);
                }
                catch { }
                log.LogInformation("Parsed page_orientation: " + pdfOrientation.ToString());


                // check for mandatory parameters
                if (string.IsNullOrEmpty(url) && string.IsNullOrEmpty(html))
                {
                    string responseMessage = "Url or html string not specified.";
                    return new BadRequestObjectResult(responseMessage);
                }

                // instantiate converter object
                SelectPdf.HtmlToPdf converter = new SelectPdf.HtmlToPdf();

                // set converter options
                converter.Options.WebPageWidth = web_page_width;
                converter.Options.WebPageHeight = web_page_height;

                converter.Options.PdfPageSize = pageSize;
                converter.Options.PdfPageOrientation = pdfOrientation;

                SelectPdf.PdfDocument doc;

                // convert url or html string to pdf
                if (!string.IsNullOrEmpty(url))
                {
                    doc = converter.ConvertUrl(url);
                }
                else
                {
                    doc = converter.ConvertHtmlString(html, base_url);
                }

                // save pdf
                byte[] pdf = doc.Save();
                doc.Close();

                log.LogInformation("Conversion finished. Returning file...");

                return new FileContentResult(pdf, "application/pdf")
                {
                    FileDownloadName = "Document.pdf"
                };
            }
            catch (Exception ex)
            {
                string responseMessage = "An error occured: " + 
                    ex.Message + "\r\n" + ex.StackTrace;
                return new BadRequestObjectResult(responseMessage);
            }
        }
    }
}

For more details about our html to pdf converter or any other feature related to our pdf library for .NET, do not hesitate to contact us.