Create Word (DOCX) or PDF file in ASP.NET Core

GemBox.Document provides support for .NET Standard 2.0 which is why it can be used on various .NET platforms such as .NET Framework, .NET Core, Xamarin and Universal Windows Platform (UWP). The .NET Standard version of GemBox.Document has full functionality of .NET Framework version, but with few rendering limitations (unsupported features):

  • Printing documents.
  • Saving documents to PDF, XPS and image formats.
  • Calling GetPaginator methods.

Also, GemBox.Document provides a version for .NET Core 3.0 that has no rendering limitations when used on Windows. However, when used on a non-Windows platform then the same .NET Standard limitations are applied. For more information see Linux / macOS example.

To create a PDF file from ASP.NET Core 3.0 web application using GemBox.Document, you'll need to add Microsoft.WindowsDesktop.App framework reference in the project file.

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

 <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <FrameworkReference Include="Microsoft.WindowsDesktop.App" />
  </ItemGroup>

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

</Project>

Or in case of a .NET Core 3.0 desktop application, you'll need to use Microsoft.NET.Sdk.WindowsDesktop SDK and add UseWPF property in the project file.

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

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

  <PropertyGroup>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

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

</Project>

GemBox.Document is ideal for web applications (like ASP.NET Core, ASP.NET MVC and ASP.NET Web Forms) because of its fast performance and thread safety when working with multiple DocumentModel objects.

The following example shows how you can create a simple ASP.NET Core MVC application that imports data from a web form to a template document using mail merge process, creates a Word file of a specified format and downloads it to the client's browser.

Sending form data from Razor view in ASP.NET Core MVC demo application
Screenshot of submitted web form Razor view in ASP.NET Core MVC
Generated DOCX file from template Word document in ASP.NET Core MVC demo application
Screenshot of created Word file of DOCX format in ASP.NET Core MVC
@using System.Globalization
@model Document.Samples.Core.Controllers.InvoiceModel

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <meta charset="utf-8" />
    <title>Create a Word Document</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <style type="text/css">
        .col-form-label {
            font-weight: bold;
        }

        input.form-control, select.form-control {
            font-size: 0.9rem;
        }

        .form-group > label:after {
            content: ": ";
        }
    </style>
</head>
<body style="padding:20px; font-size: 0.9rem">
    <form asp-action="Create">
        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
        <div class="form-group row">
            <label asp-for="Number" class="col-md-2 col-sm-3 col-form-label"></label>
            <div class="col-md-5 col-sm-7">
                <input asp-for="Number" type="text" class="form-control" readonly />
            </div>
        </div>
        <div class="form-group row">
            <label asp-for="Date" class="col-md-2 col-sm-3 col-form-label"></label>
            <div class="col-md-5 col-sm-7">
                <input asp-for="Date" type="date" class="form-control" />
            </div>
        </div>
        <div class="form-group row">
            <label asp-for="Name" class="col-md-2 col-sm-3 col-form-label"></label>
            <div class="col-md-5 col-sm-7">
                <input asp-for="Name" class="form-control" />
            </div>
        </div>
        <div class="form-group row">
            <label asp-for="Address" class="col-md-2 col-sm-3 col-form-label"></label>
            <div class="col-md-5 col-sm-7">
                <input asp-for="Address" class="form-control" />
            </div>
        </div>
        <div class="form-group row">
            <label asp-for="Country" class="col-md-2 col-sm-3 col-form-label"></label>
            <div class="col-md-5 col-sm-7">
                @Html.DropDownListFor(m => m.Country, Model.Countries, null, new { @class = "form-control" })
            </div>
        </div>
        <div class="form-group row">
            <label asp-for="ContactPerson" class="col-md-2 col-sm-3 col-form-label"></label>
            <div class="col-md-5 col-sm-7">
                <input asp-for="ContactPerson" class="form-control" />
            </div>
        </div>

        <div>
            <h4>Output format:</h4>
            <div class="form-check">
                <input id="DOCX" name="SelectedFormat" type="radio" class="form-check-input" checked value="DOCX" />
                <label for="DOCX" class="form-check-label">DOCX</label>
            </div>
            <div class="form-check">
                <input id="HTML" name="SelectedFormat" type="radio" class="form-check-input" value="HTML" />
                <label for="HTML" class="form-check-label">HTML</label>
            </div>
            <div class="form-check">
                <input id="RTF" name="SelectedFormat" type="radio" class="form-check-input" value="RTF" />
                <label for="RTF" class="form-check-label">RTF</label>
            </div>
            <div class="form-check">
                <input id="TXT" name="SelectedFormat" type="radio" class="form-check-input" value="TXT" />
                <label for="TXT" class="form-check-label">TXT</label>
            </div>
            <div class="form-check">
                <input id="PDF" name="SelectedFormat" type="radio" class="form-check-input" value="PDF" />
                <label for="PDF" class="form-check-label">PDF</label>
            </div>
            <div class="form-check">
                <input id="XPS" name="SelectedFormat" type="radio" class="form-check-input" value="XPS" />
                <label for="XPS" class="form-check-label">XPS</label>
            </div>
            <div class="form-check">
                <input id="BMP" name="SelectedFormat" type="radio" class="form-check-input" value="BMP" />
                <label for="BMP" class="form-check-label">BMP</label>
            </div>
            <div class="form-check">
                <input id="GIF" name="SelectedFormat" type="radio" class="form-check-input" value="GIF" />
                <label for="GIF" class="form-check-label">GIF</label>
            </div>
            <div class="form-check">
                <input id="JPG" name="SelectedFormat" type="radio" class="form-check-input" value="JPG" />
                <label for="JPG" class="form-check-label">JPG</label>
            </div>
            <div class="form-check">
                <input id="PNG" name="SelectedFormat" type="radio" class="form-check-input" value="PNG" />
                <label for="PNG" class="form-check-label">PNG</label>
            </div>
            <div class="form-check">
                <input id="TIF" name="SelectedFormat" type="radio" class="form-check-input" value="TIF" />
                <label for="TIF" class="form-check-label">TIF</label>
            </div>
            <div class="form-check">
                <input id="WMP" name="SelectedFormat" type="radio" class="form-check-input" value="WMP" />
                <label for="WMP" class="form-check-label">WMP</label>
            </div>
        </div>
        <hr />
        <button type="submit" class="btn btn-default">Generate</button>
    </form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.IO;
using System.Linq;
using GemBox.Document;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;

namespace Document.Samples.Core.Controllers
{
    public class DocumentController : Controller
    {
        private static readonly SelectListItem[] countries = CultureInfo.GetCultures(CultureTypes.SpecificCultures)
            .Select(c => new RegionInfo(c.LCID).EnglishName)
            .Distinct()
            .OrderBy(k => k)
            .Select(k => new SelectListItem() { Text = k, Value = k })
            .ToArray();

        private static int invoiceNumber = 1;
        private IWebHostEnvironment environment;

        public DocumentController(IWebHostEnvironment environment)
        {
            this.environment = environment;
        }

        private static SaveOptions GetSaveOptions(string format)
        {
            switch (format.ToUpperInvariant())
            {
                case "DOCX":
                    return SaveOptions.DocxDefault;
                case "HTML":
                    return SaveOptions.HtmlDefault;
                case "RTF":
                    return SaveOptions.RtfDefault;
                case "TXT":
                    return SaveOptions.TxtDefault;
                case "PDF":
                    return SaveOptions.PdfDefault;
                case "XPS":
                    return SaveOptions.XpsDefault;
                case "BMP":
                    return new ImageSaveOptions() { Format = ImageSaveFormat.Bmp };
                case "GIF":
                    return new ImageSaveOptions() { Format = ImageSaveFormat.Gif };
                case "JPG":
                    return new ImageSaveOptions() { Format = ImageSaveFormat.Jpeg };
                case "PNG":
                    return new ImageSaveOptions() { Format = ImageSaveFormat.Png };
                case "TIF":
                    return new ImageSaveOptions() { Format = ImageSaveFormat.Tiff };
                case "WMP":
                    return new ImageSaveOptions() { Format = ImageSaveFormat.Wmp };
                default:
                    throw new NotSupportedException("Format '" + format + "' is not supported.");
            }
        }

        private static byte[] GetBytes(DocumentModel document, SaveOptions options)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                document.Save(stream, options);
                return stream.ToArray();
            }
        }

        private DocumentModel Process(InvoiceModel model)
        {
            string path = Path.Combine(this.environment.ContentRootPath, "Invoice.docx");

            // Load template document
            DocumentModel document = DocumentModel.Load(path);

            // Create data source for mail merge process.
            var data = new
            {
                model.Number,
                model.Date,
                Company = model.Name,
                model.Address,
                model.Country,
                FullName = model.ContactPerson
            };

            // Execute mail merge process.
            document.MailMerge.Execute(data);

            invoiceNumber = invoiceNumber == int.MaxValue ? 1 : invoiceNumber + 1;

            return document;
        }

        public IActionResult Create()
        {
            return View(new InvoiceModel()
            {
                Number = invoiceNumber,
                Date = DateTime.UtcNow,
                Name = "ACME Corp.",
                Address = "240 Old Country Road, Springfield, IL",
                Countries = countries,
                Country = "United States",
                ContactPerson = "Joe Smith",
                SelectedFormat = "DOCX"
            });
        }

        [HttpPost]
        public ActionResult Create(InvoiceModel model)
        {
            ComponentInfo.SetLicense("FREE-LIMITED-KEY");

            if (!ModelState.IsValid)
                return View(model);

            SaveOptions options = GetSaveOptions(model.SelectedFormat);
            DocumentModel document = this.Process(model);

            return File(GetBytes(document, options), options.ContentType, "Create." + model.SelectedFormat.ToLowerInvariant());
        }
    }

    public class InvoiceModel
    {
        public int Number { get; set; }
        public DateTime Date { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        public IList<SelectListItem> Countries { get; set; }
        public string Country { get; set; }
        public string SelectedFormat { get; set; }

        [Display(Name = "Contact person")]
        public string ContactPerson { get; set; }
    }
}

GemBox.Document is only licensed per developer and the licenses include a royalty-free deployment. There are no server or OEM licenses, there are no additional costs for anything (like building, testing and deploying).

So, you're free to build an unlimited number of applications and deploy or distribute them to an unlimited number of servers or end user machines with no extra cost.

Want more?

Next example GitHub

Check the next example or select an example from the menu. You can also download our examples from the GitHub.


Like it?

Download Buy

If you want to try the GemBox.Document yourself, you can download the free version. It delivers the same performance and set of features as the professional version, but with some operations limited. To remove the limitation, you need to purchase a license.