Loading...
Area: Optimizely B2B Commerce

Custom PDF implementation

Recommended reading 

This guide is to provide an approach to creating custom PDF generation within the Optimizely Commerce Cloud platform.

Use Cases

  • A customer would like to generate a PDF that represents the current items in the cart, as this functionality is not in the base platform.
  • A customer would like to create a PDF that shows the top ten most purchased products for a given category.
  • A customer would like to create a PDF that shows a category’s marketing content.

Steps to Create a Custom PDF

The create a custom PDF, a developer will need to modify a custom view template, modify a custom TypeScript controller and create a custom API controller.

Modify a Custom View Template

Add a line to your custom view template, where you want the end-user to trigger the PDF via a button or another action on the page. The getPdf() method will exists on your custom TypeScript controller.

Code Sample

<a href="#" ng-click="vm.getPdf()">View Cart as PDF</a>

Modify your TypeScript Controller

Add your getPdf() method to your TypeScript controller, that facilitates calling out to your custom API controller.

Code Sample

getPdf() {
  let url = "/api/CustomCartV1/GetPdf";
  if (this.accessToken.exists()) {
    uri += "?access_token=" + encodeURIComponent(this.accessToken.get());
  }
  window.open(url, "_blank");
}

Modify your Custom API Controller

Modify your custom API controller by adding a method to be called asynchronously.

Code Sample

[System.Web.Http.Route("GetPdf")]

public HttpResponseMessage GetPdf()
{
  var pdfStream = new MemoryStream();
  string renderedHtml = this.GetPdfHtml();

  PdfGeneratorHelper.GeneratePdf(renderedHtml, pdfStream);
  var response = Request.CreateResponse(HttpStatusCode.OK);

  response.Content = new StreamContent(pdfStream);

  response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("inline");

  response.Content.Headers.ContentDisposition.FileName = "ShoppingCart.pdf";

  response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
  return response;

}

Implement your GetPdfHtml() method to return your PDF view as HTML. This method would be a member of the following API class:

Code Sample

[System.Web.Http.RoutePrefix("api/ CustomCartV1")]

public class CustomCartController : BaseApiController
{
  …
}

Code Sample

  private string GetPdfHtml()

  {

  var theme = this.UnitOfWork.GetRepository<Theme>().Get(SiteContext.Current.WebsiteDto.ThemeId);
  var themeSourceName = theme.ThemeSource == null

  ? (theme.IsSystemTheme ? "System" : "User")

  : theme.ThemeSource.Name;

  

  // Generate cart pdf html.

  var templatePath = $"~/frontendresources/{themeSourceName}/{theme.Name}/pdfviews/CartPdfTemplate.cshtml";
  var getByPathParameter = new GetByPathParameter { Path = templatePath };

  var getByPathResult =

  this.ThemeContentProvider.GetByPath(getByPathParameter);

var cartModelJson = cartModel.ToJson(false);
dynamic cartModelDynamic = cartModelJson.ToExpando();
  var viewHtml = getByPathResult.ThemeContentDto != null

  ? getByPathResult.ThemeContentDto.Content

  : string.Empty;
  var renderedViewHtml =

  this.EmailService.ParseTemplate(viewHtml, cartModelDynamic);
  return renderedViewHtml;

  }

Add or Modify your Custom PDF View Template

The custom template that represents the PDF view you’re presenting, needs to be in DotLiquid format and needs to be of the Razor view extension .cshtml. The template will also need to be located at the following location:
$"~/frontendresources/{themeSourceName}/{theme.Name}/pdfviews/CartPdfTemplate.cshtml";

This path would resolve to the following structure in your project directory structure:
YourThemeProjectRoot/PdfViews/CartPdfTemplate.cshtml, but B2B will handle locating this for you with the Theme Content Provider.

Code Sample

  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  <html xmlns="http://www.w3.org/1999/xhtml">

  <head>

  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

  <title>[% translate 'Share Order' %]</title>

  <style>

  body {

  font-family: Helvetica, Arial, Sans-Serif;

  font-size: 16px;

  color: #252525;

  }

  </style>

  </head>

  <body>

  [% if Model.LogoImagePath != null and Model.LogoImagePath != "" -%]

  <div>

  <img src="[[Model.LogoImagePath]]" max-height="150" max-width="300" alt="Company
  Logo" />

  </div>

  [% endif -%]

  <div>

  </body>

  </html>
Do you find this information helpful? Please log in to provide feedback.

Last updated: Dec 11, 2020

Recommended reading