Create PowerPoint (PPTX) or PDF files in ASP.NET Core

GemBox.Presentation is a standalone .NET component that's ideal for web applications because of its fast performance and thread safety when working with multiple PresentationDocument objects.

With GemBox.Presentation you can build web applications that target ASP.NET Core 2.0 and above. The following live demos show how you can create web apps that generate PowerPoint and PDF files and download them to your browser.

To use GemBox.Presentation, simply install the GemBox.Presentation package with NuGet or add the following package reference in the project file.

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net7.0</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="GemBox.Presentation" Version="*" />
    </ItemGroup>

</Project>

Create PowerPoint or PDF files in ASP.NET Core MVC

The following example shows how you can create an ASP.NET Core Razor Pages application that:

  1. Creates a PowerPoint card for a birthday, greeting, or anniversary by importing the web form data into the Placeholders from template presentation.
  2. Saves the card in a specified file format like PPTX or PDF.
  3. Downloads the generated file with a FileContentResult.
Sending form data from Razor view and generating PPTX file in ASP.NET Core MVC application
Screenshot of submitted web form and created PowerPoint presentation
@model CardModel

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>GemBox.Presentation in ASP.NET Core MVC application</title>
    <link rel="icon" href="~/favicon.ico" />
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-controller="Home" asp-action="Index">Home</a>
            </div>
        </nav>
    </header>

    <div class="container">
        <main class="pb-3 row">
            <h1 class="display-4 p-3">Card generator [Razor View]</h1>
            <div class="col-lg-6">
                <form asp-action="Download">
                    <div class="form-group">Top text: <textarea asp-for="Top" class="form-control"></textarea></div>
                    <div class="form-group">Middle text: <textarea asp-for="Middle" class="form-control"></textarea></div>
                    <div class="form-group">Bottom text: <textarea asp-for="Bottom" class="form-control"></textarea></div>
                    <div class="form-group">
                        Format:
                        <div class="row">
                            @foreach (string format in Model.FormatMappingDictionary.Select(item => item.Key))
                            {
                                <div class="col-3">
                                    <div class="form-check form-check-inline">
                                        <input asp-for="Format" class="form-check-input" type="radio" id="@format" value="@format">
                                        <label for="@format" class="form-check-label">@format</label>
                                    </div>
                                </div>
                            }
                        </div>
                    </div>
                    <div class="form-group"><input type="submit" value="Create" class="btn btn-primary" /></div>
                </form>
            </div>
        </main>
    </div>

    <footer class="footer border-top text-muted">
        <div class="container">&copy; GemBox Ltd. — All rights reserved.</div>
    </footer>
</body>
</html>
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using PresentationCoreMvc.Models;
using GemBox.Presentation;

namespace PresentationCoreMvc.Controllers
{
    public class HomeController : Controller
    {
        private readonly IWebHostEnvironment environment;

        public HomeController(IWebHostEnvironment environment)
        {
            this.environment = environment;

            // If using the Professional version, put your serial key below.
            ComponentInfo.SetLicense("FREE-LIMITED-KEY");
        }

        public IActionResult Index()
        {
            return View(new CardModel());
        }

        public FileStreamResult Download(CardModel model)
        {
            // Load template presentation.
            var path = Path.Combine(this.environment.ContentRootPath, "%#CardWithPlaceholderElements.pptx%");
            var presentation = PresentationDocument.Load(path);

            // Get first slide.
            var slide = presentation.Slides[0];

            // Get placeholder elements.
            var placeholders = slide.Content.Drawings.OfType<Shape>()
                .Where(s => s.Placeholder != null && s.Placeholder.PlaceholderType == PlaceholderType.Text);

            // Set text on placeholders.
            var top = placeholders.First(p => p.Name == "Top Placeholder");
            top.TextContent.LoadText(model.Top);
            var middle = placeholders.First(p => p.Name == "Middle Placeholder");
            middle.TextContent.LoadText(model.Middle);
            var bottom = placeholders.First(p => p.Name == "Bottom Placeholder");
            bottom.TextContent.LoadText(model.Bottom);

            // Save presentation in specified file format.
            var stream = new MemoryStream();
            presentation.Save(stream, model.Options);

            // Download file.
            return File(stream, model.Options.ContentType, $"OutputFromView.{model.Format.ToLower()}");
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel() { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }
}

namespace PresentationCoreMvc.Models
{
    public class CardModel
    {
        [DisplayFormat(ConvertEmptyStringToNull = false)]
        public string Top { get; set; } = "Happy Birthday Jane!";
        [DisplayFormat(ConvertEmptyStringToNull = false)]
        public string Middle { get; set; } = "May this be your best birthday ever.\nMay your joy never end.";
        [DisplayFormat(ConvertEmptyStringToNull = false)]
        public string Bottom { get; set; } = "from John 😊";
        public string Format { get; set; } = "PPTX";
        public SaveOptions Options => this.FormatMappingDictionary[this.Format];
        public IDictionary<string, SaveOptions> FormatMappingDictionary => new Dictionary<string, SaveOptions>()
        {
            ["PPTX"] = new PptxSaveOptions(),
            ["PDF"] = new PdfSaveOptions(),
            ["XPS"] = new XpsSaveOptions(),
            ["BMP"] = new ImageSaveOptions(ImageSaveFormat.Bmp),
            ["PNG"] = new ImageSaveOptions(ImageSaveFormat.Png),
            ["JPG"] = new ImageSaveOptions(ImageSaveFormat.Jpeg),
            ["GIF"] = new ImageSaveOptions(ImageSaveFormat.Gif),
            ["TIF"] = new ImageSaveOptions(ImageSaveFormat.Tiff)
        };
    }
}

Create PowerPoint or PDF files in ASP.NET Core Razor Pages

The following example shows how you can create an ASP.NET Core Razor Pages application that:

  1. Creates a PowerPoint card by importing the web form data into a template presentation using Find and Replace operations.
  2. Saves the card in a specified file format like PPTX or PDF.
  3. Downloads the generated file with a FileContentResult.
Sending data from Razor page and generating PDF file in ASP.NET Core Razor Pages application
Screenshot of submitted web form and created PDF document
@page
@model IndexModel

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>GemBox.Presentation in ASP.NET Core Razor Pages application</title>
    <link rel="icon" href="~/favicon.ico" />
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-page="/Index">Home</a>
            </div>
        </nav>
    </header>

    <div class="container">
        <main class="pb-3 row">
            <h1 class="display-4 p-3">Card generator [Razor Page]</h1>
            <div class="col-lg-6">
                <form method="post">
                    <div class="form-group">Top text: <textarea asp-for="Card.Top" class="form-control"></textarea></div>
                    <div class="form-group">Middle text: <textarea asp-for="Card.Middle" class="form-control"></textarea></div>
                    <div class="form-group">Bottom text: <textarea asp-for="Card.Bottom" class="form-control"></textarea></div>
                    <div class="form-group">
                        Format:
                        <div class="row">
                            @foreach (string format in Model.Card.FormatMappingDictionary.Select(item => item.Key))
                            {
                                <div class="col-3">
                                    <div class="form-check form-check-inline">
                                        <input asp-for="Card.Format" class="form-check-input" type="radio" id="@format" value="@format">
                                        <label for="@format" class="form-check-label">@format</label>
                                    </div>
                                </div>
                            }
                        </div>
                    </div>
                    <div class="form-group"><input type="submit" value="Create" class="btn btn-primary" /></div>
                </form>
            </div>
        </main>
    </div>

    <footer class="footer border-top text-muted">
        <div class="container">&copy; GemBox Ltd. — All rights reserved.</div>
    </footer>
</body>
</html>
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using PresentationCorePages.Models;
using GemBox.Presentation;

namespace PresentationCorePages.Pages
{
    public class IndexModel : PageModel
    {
        private readonly IWebHostEnvironment environment;

        [BindProperty]
        public CardModel Card { get; set; }

        public IndexModel(IWebHostEnvironment environment)
        {
            this.environment = environment;
            this.Card = new CardModel();

            // If using the Professional version, put your serial key below.
            ComponentInfo.SetLicense("FREE-LIMITED-KEY");
        }

        public void OnGet() { }

        public FileContentResult OnPost()
        {
            // Load template presentation.
            var path = Path.Combine(this.environment.ContentRootPath, "%#CardWithPlaceholderTexts.pptx%");
            var presentation = PresentationDocument.Load(path);

            // Get first slide.
            var slide = presentation.Slides[0];

            // Execute find and replace operations.
            slide.TextContent.Replace("{{Top Text}}", this.Card.Top);
            slide.TextContent.Replace("{{Middle Text}}", this.Card.Middle);
            slide.TextContent.Replace("{{Bottom Text}}", this.Card.Bottom);

            // Save presentation in specified file format.
            using var stream = new MemoryStream();
            presentation.Save(stream, this.Card.Options);

            // Download file.
            return File(stream.ToArray(), this.Card.Options.ContentType, $"OutputFromPage.{this.Card.Format.ToLower()}");
        }
    }
}

namespace PresentationCorePages.Models
{
    public class CardModel
    {
        [DisplayFormat(ConvertEmptyStringToNull = false)]
        public string Top { get; set; } = "Happy Birthday Jane!";
        [DisplayFormat(ConvertEmptyStringToNull = false)]
        public string Middle { get; set; } = "May this be your best birthday ever.\nMay your joy never end.";
        [DisplayFormat(ConvertEmptyStringToNull = false)]
        public string Bottom { get; set; } = "from John 😊";
        public string Format { get; set; } = "PDF";
        public SaveOptions Options => this.FormatMappingDictionary[this.Format];
        public IDictionary<string, SaveOptions> FormatMappingDictionary => new Dictionary<string, SaveOptions>()
        {
            ["PPTX"] = new PptxSaveOptions(),
            ["PDF"] = new PdfSaveOptions(),
            ["XPS"] = new XpsSaveOptions(),
            ["BMP"] = new ImageSaveOptions(ImageSaveFormat.Bmp),
            ["PNG"] = new ImageSaveOptions(ImageSaveFormat.Png),
            ["JPG"] = new ImageSaveOptions(ImageSaveFormat.Jpeg),
            ["GIF"] = new ImageSaveOptions(ImageSaveFormat.Gif),
            ["TIF"] = new ImageSaveOptions(ImageSaveFormat.Tiff)
        };
    }
}

Host and deploy ASP.NET Core

GemBox.Presentation is licensed per individual developer, and the licenses include a royalty-free deployment. You can feel free to build an unlimited number of applications and deploy or distribute them to an unlimited number of services, servers, or end-user machines with no extra cost.

GemBox.Presentation licenses are compatible with SaaS or PaaS solutions, as long as they don't offer similar or competing functionality to our component, or expose our features through an API for use by an unlicensed third party. For more information, please check the EULA.

Create PNG, JPG, or XPS files on Windows

GemBox.Presentation supports saving to XPS and image formats (like PNG and JPG) on applications that target .NET 6.0 or above.

However, these features currently work only on Windows. In other words, besides .NET Core Runtime, you also need a .NET Windows Desktop Runtime installed on the server.

To export an XPS or image file in an ASP.NET Core application, you need to use a Windows-specific TFM in the project file.

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net7.0-windows</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="GemBox.Presentation" Version="*" />
    </ItemGroup>

</Project>

Also, enable the following compatibility switch with the AppContext class.

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;

        // Add compatibility switch.
        AppContext.SetSwitch("Switch.System.Windows.Media.ShouldRenderEvenWhenNoDisplayDevicesAreAvailable", true);
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // ...
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // ...
    }
}

Or you can enable that compatibility switch by adding the following runtimeconfig.template.json file to your project.

{
  "configProperties": {
    "Switch.System.Windows.Media.ShouldRenderEvenWhenNoDisplayDevicesAreAvailable": true
  }
}

Limitations on Linux or macOS

You can use the full functionality of GemBox.Presentation on Unix systems, but with the following exceptions:

These features currently have WPF dependencies which means they require a .NET Windows Desktop Runtime. However, we do have plans for providing cross-platform support for them in future releases.

See also


Next steps

GemBox.Presentation is a .NET component that enables you to read, write, edit, convert, and print presentation files from your .NET applications using one simple API.

Download Buy