Skip to main content Link Search Menu Expand Document Toggle dark mode Copy Code (external link)
paperwork.help

The Factory

The factory is set up once for the application. It holds everything that is shared between documents, and starts a document builder for each one.

using Paperwork;

// Once, at startup
using var factory = PaperworkFactory.Create().Build();

// For each document
await factory.NewDocument()
    .WithLayoutFile("invoice.html")
    .WithData("model", invoice)
    .SaveAsync("invoice.pdf");

On this page

The factory holds everything shared between documents: the HttpClient used for remote templates, data, images and fonts, and any authentication, tracing and file-request services. Create it once and re-use it - it can be used by many documents at the same time.

Creating a factory

// With its own HttpClient
using var factory = PaperworkFactory.Create().Build();

// With your own HttpClient - e.g. to set a timeout or default headers
var client = new HttpClient { Timeout = TimeSpan.FromSeconds(30) };
using var factory = PaperworkFactory.Create(client).Build();

Factory options

Options are added between Create() and Build().

Method Description
WithAuth(IPaperworkAuthService) Adds a service that fetches authenticated remote content - templates, styles and data loaded with an auth name. Can be called more than once.
WithFileRequests(IPaperworkRemoteFileRequestService) A service that loads the images, fonts and stylesheets a template asks for, e.g. from your own storage.
WithTracing(IPaperworkTracingService) A service that records the stages and requests of each generation.
WithSerializerOptions(JsonSerializerOptions) The JSON options used to read requests and template definitions.
WithGenerator(IPaperworkGeneratorFactory) Adds a custom generator, for your own template versions or output types.
using var factory = PaperworkFactory.Create(client)
    .WithAuth(new MyApiAuthService())
    .WithFileRequests(new MyAssetService())
    .Build();

Dependency injection

In ASP.NET Core and other hosted applications, register the factory at startup, and inject IPaperworkFactory where documents are generated.

using Paperwork.Generation;

builder.Services.AddPaperwork(builder.Configuration);

The registered factory uses the application’s HttpClient, IPaperworkTracingService and IPaperworkRemoteFileRequestService when they are registered, and its own defaults when they are not.

public class InvoiceController : Controller
{
    private readonly IPaperworkFactory _factory;

    public InvoiceController(IPaperworkFactory factory) => _factory = factory;

    [HttpGet("invoice/{id}")]
    public async Task<IActionResult> Invoice(int id)
    {
        var pdf = await _factory.NewDocument()
            .WithLayoutFile("Templates/invoice.html")
            .WithData("model", GetInvoice(id))
            .BuildBytesAsync();

        return File(pdf, "application/pdf", $"invoice-{id}.pdf");
    }
}

Configuration

Fonts, images, parsing, output and logging options for every document are read from the "Paperwork" section of the configuration (the "Scryber" section is also read, and "Paperwork" values replace any that are in both).

{
  "Paperwork": {
    "Fonts": {
      "Register": [
        { "Family": "Open Sans", "File": "Fonts/OpenSans-Regular.ttf" }
      ]
    },
    "Parsing": {
      "Namespaces": [
        { "Source": "http://mycompany.com/components", "Namespace": "MyCompany.Components", "Assembly": "MyCompany" }
      ]
    }
  }
}

AddPaperwork(configuration) passes the configuration to the engine. Without dependency injection, do it once at startup:

var configuration = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .Build();

PaperworkConfiguration.Init(configuration);

See Configuration Structure for all the sections.


Next

The Document Builder collects the layouts, styles, data and fields for one document and generates it.

See also