03/18/2015 08:11 PM Email notifications
Virto Commerce

Email notifications

Updated:

Introduction

This guide details how to leverage the notification/template engine to have eCommerce automatically send out email notifications for new orders, cases, and more.  The notification/template engine is used to generate different types of templated content and is mostly used to generate personalized emails for customers regarding orders.

The template engine itself is very customizable and can be completely replaced by injecting custom implementation of ITemplateService.

The default implementation we provide supports XSL, (in future will support also HTML and Text) templates that are configured using eCommerce manager (administration tool). It allows creating templates using XML Stylesheet Language (XSL). This provides a very powerful and flexible way of creating notification templates for different outgoing emails.

The emails can be sent using regular Smtp implementation if not hosted on windows azure, or using SendGrid implemented for azure platform.

Key Classes and Files

TemplateService.cs - Loads the appropriate template, formats it based on template settings and returns formatted text for email. To create custom Implementation of TemplateService just implement ITemplateService and inject instead of default TemplateService:

using System.Collections.Generic;
using System.Globalization;
 
namespace VirtoCommerce.Foundation.Frameworks.Templates
{
  public interface ITemplateService
  {
    IProcessedTemplate ProcessTemplate(string templateName, IDictionary<string, object> context, CultureInfo culture);
  }
}

ProcessedTemplate.cs - Returned by TemplateService. Contains processed body for email, Subject for email and type of template that was generated by service (xsl,html or text)

using VirtoCommerce.Foundation.AppConfig.Model;
namespace VirtoCommerce.Foundation.Frameworks.Templates
{
  public interface IProcessedTemplate
  {
    /// <summary>
    /// The processed body of template for sending email
    /// </summary>
    string Body { get; set; }
    /// <summary>
    /// Template subject
    /// </summary>
    string Subject { get; set; }
    /// <summary>
    /// The type of processed template
    /// </summary>
    EmailTemplateTypes Type { get; set; }
  }
}

NetEmailService.cs and AzureEmailService.cs - Implementation for sending email messages. To add custom implementation of EmailService implement IEmailService interface:

namespace VirtoCommerce.Foundation.Frameworks.Email
{
  public interface IEmailService
  {
    bool SendEmail(IEmailMessage message);
  }
}

EmailMessage.cs - passed as parameter for EmailService:

using System.Collections.Generic;
 
namespace VirtoCommerce.Foundation.Frameworks.Email
{
  public interface IEmailMessage
  {
    /// <summary>
    /// List of email recipient addresses
    /// </summary>
    List<string> To { get; }
    /// <summary>
    /// Address from where the email is sent
    /// </summary>
    string From { get; set; }
    /// <summary>
    /// Html body of emai message
    /// </summary>
    string Html { get; set; }
    /// <summary>
    /// Text body of email message
    /// </summary>
    string Text { get; set; }
    /// <summary>
    /// The subject of the email message
    /// </summary>
    string Subject { get; set; }
    /// <summary>
    /// Additional attachemts that can be sent by email
    /// </summary>
    List<byte[]> Attachments { get; }
  }
}

Quick Overview

In the web.config file of your public sites, look to this section:

<system.net>
  <mailSettings>
    <smtp from="email@company.com">
      <network host="localhost" port="25" />
    </smtp>
  </mailSettings>
 </system.net>

You can add username and password in there as well if your SMTP server requires authentication. The from address is optional, but will be used in EmailService implementation if no From address is passed in IEmailMessage.

DefaultEmailFrom should be configured in Commerce Manager Settings tab.

For more information about configuring the mail settings, see http://msdn.microsoft.com/en-us/library/w355a94k.aspx.

For more information on SendGrid (AzureEmailService) see sendgrid.com/docs

How it works

Relevent data, including the Order object are placed in a dictionary and passed to the TemplateService.ProcessTemplate() method with the name of the template, and a CultureInfo instance representing the desired/current culture. The Process() method returns the formatted custom text. Context data can contain any number and any type objects. The important thing is that template and passed object could be processed.

To create new email template first you need to open commerce manager and go to settings/email templates

  • Display name used to identify template, which is loaded in when sending specific email
  • Type Xsl to use xslt as Body for template
  • Default language code identifies default language when specific template in Languages for this template is not found
  • Subject is used when sending email

Code Example for Sending Out Emails

The following code is taken from the OrderChangeEventListener.cs that is registered as event through EntityEventInterceptor and raised after new Order entity is added.

private void SendNewOrderNotificationsAsync(Order order)
{
  // the whole function should be async
  Task.Run(() =>
  {
    //Create a context object
    IDictionary<string, object> context = new Dictionary<string, object>();
    context.Add("order", order);

    //Send order-confirmation email
    var confirmTempate = _templateService.ProcessTemplate("order-confirmation", context, new CultureInfo("en-us"));

    var recipientAddress = order.OrderAddresses.FirstOrDefault(oa => oa.OrderAddressId == order.AddressId);
    if (recipientAddress != null)
    {
      SendEmail(confirmTempate, recipientAddress.Email);
    }

    //Send order-notification email
    var notifyTemplate = _templateService.ProcessTemplate("order-notify", context, new CultureInfo("en-us"));

    if (_storeService != null)
    {
      var store = _storeService.Stores.FirstOrDefault(s => s.StoreId == order.StoreId);

      if (store != null)
      {
        SendEmail(notifyTemplate, store.Email);
      }
    }
  });
}
 
private bool SendEmail(IProcessedTemplate template, string recipient)
{
  if (string.IsNullOrEmpty(recipient) || template == null || string.IsNullOrEmpty(template.Body))
  {
    return false;
  }
  var isHtml = template.Type != EmailTemplateTypes.Text;
  IEmailMessage message = new EmailMessage(recipient, template.Body, isHtml);
  message.Subject = template.Subject;
  message.From = "orders@virtoway.com";
  try
  {
    _emailService.SendEmail(message);
  }
  catch
  {
    //Log
    return false;
  }

  return true;
}

XSL/XML processing Template Service

Template service renders templates using a XSL content saved in database EmailTemplates table. It expects that all the parameters passed in the dictionary context can be serialized to xml. It then looks for the specific template by template name. If it can't find language specific template in EmailTemplateLanguage it will use the default template.

For example when Order is passed to the template service the following XML is generated:

<?xml version="1.0"?>
<ContextDoc>
  <Order xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
    <Created>2013-05-14T12:04:34.1027676Z</Created>
    <Errors xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
    <LastModified>2013-05-14T12:04:34.1027676Z</LastModified>
    <AddressId>e80bf493-c2cf-4cd3-8794-91e3dc49f400</AddressId>
    <BillingCurrency>USD</BillingCurrency>
    <CustomerId>1</CustomerId>
    <CustomerName>John Doe</CustomerName>
    <HandlingTotal>0</HandlingTotal>
    <Name>Order_For_John Doe</Name>
    <OrderAddresses>
      <OrderAddress z:Id="i2">
        <Created>2013-05-14T12:04:34.1027676Z</Created>
        <Errors xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
        <LastModified>2013-05-14T12:04:34.1027676Z</LastModified>
        <City>Los Angeles</City>
        <CountryCode>US</CountryCode>
        <CountryName>United States</CountryName>
        <DaytimePhoneNumber>none</DaytimePhoneNumber>
        <Email>john_doe_work@gmail.com</Email>
        <EveningPhoneNumber i:nil="true" />
        <FaxNumber i:nil="true" />
        <FirstName>John</FirstName>
        <LastName>Doe</LastName>
        <Line1>8237 Santa Monica Blvd</Line1>
        <Line2 i:nil="true" />
        <Name>Shipping</Name>
        <OrderAddressId>75d5ae03-7a4d-4fc5-85c9-991a6548290f</OrderAddressId>
        <OrderGroup z:Ref="i1" />
        <OrderGroupId>816dd41c-d393-4ed4-925e-4269dcd47c93</OrderGroupId>
        <Organization i:nil="true" />
        <PostalCode>90210</PostalCode>
        <RegionId i:nil="true" />
        <RegionName i:nil="true" />
        <StateProvince i:nil="true" />
      </OrderAddress>
      <OrderAddress z:Id="i3">
        <Created>2013-05-14T12:04:34.1027676Z</Created>
        <Errors xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
        <LastModified>2013-05-14T12:04:34.1027676Z</LastModified>
        <City>Los Angeles</City>
        <CountryCode>US</CountryCode>
        <CountryName>United States</CountryName>
        <DaytimePhoneNumber>none</DaytimePhoneNumber>
        <Email>john_doe_work@gmail.com</Email>
        <EveningPhoneNumber i:nil="true" />
        <FaxNumber i:nil="true" />
        <FirstName>John</FirstName>
        <LastName>Doe</LastName>
        <Line1>8237 Santa Monica Blvd</Line1>
        <Line2 i:nil="true" />
        <Name>Billing</Name>
        <OrderAddressId>e80bf493-c2cf-4cd3-8794-91e3dc49f400</OrderAddressId>
        <OrderGroup z:Ref="i1" />
        <OrderGroupId>816dd41c-d393-4ed4-925e-4269dcd47c93</OrderGroupId>
        <Organization i:nil="true" />
        <PostalCode>90210</PostalCode>
        <RegionId i:nil="true" />
        <RegionName i:nil="true" />
        <StateProvince i:nil="true" />
      </OrderAddress>
    </OrderAddresses>
    <OrderForms>
      <OrderForm z:Id="i4">
        <Created>2013-05-14T12:04:34.1027676Z</Created>
        <Errors xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
        <LastModified>2013-05-14T12:04:34.1027676Z</LastModified>
        <BillingAddressId>e80bf493-c2cf-4cd3-8794-91e3dc49f400</BillingAddressId>
        <DiscountAmount>0</DiscountAmount>
        <Discounts />
        <HandlingTotal>0</HandlingTotal>
        <LineItems>
          <LineItem z:Id="i5">
            <Created>2013-05-14T12:04:34.1027676Z</Created>
            <Errors xmlns:d6p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
            <LastModified>2013-05-14T12:04:34.1027676Z</LastModified>
            <AllowBackordersAndPreorders>false</AllowBackordersAndPreorders>
            <BackorderQuantity>0</BackorderQuantity>
            <Catalog>VendorVirtual</Catalog>
            <CatalogCategory i:nil="true" />
            <CatalogItemCode>v-b004nzb8tu</CatalogItemCode>
            <CatalogItemId>v-b004nzb8tu</CatalogItemId>
            <CatalogOutline i:nil="true" />
            <Comment i:nil="true" />
            <Description i:nil="true" />
            <Discounts />
            <DisplayName>Samsung LN26D450 26-Inch 720p 60Hz LCD HDTV (Black)</DisplayName>
            <ExtendedPrice>349.9900</ExtendedPrice>
            <FulfillmentCenterId i:nil="true" />
            <InStockQuantity>0</InStockQuantity>
            <InventoryStatus i:nil="true" />
            <LineItemDiscountAmount>0</LineItemDiscountAmount>
            <LineItemId>5f715fb5-f774-4a82-95a1-d819b3602006</LineItemId>
            <ListPrice>349.99</ListPrice>
            <MaxQuantity>10.00</MaxQuantity>
            <MinQuantity>1.00</MinQuantity>
            <Options />
            <OrderForm z:Ref="i4" />
            <OrderFormId>21b9f8f6-c56c-4303-ba2e-e649a90ce269</OrderFormId>
            <ParentCatalogItemId />
            <PlacedPrice>349.99</PlacedPrice>
            <PreorderQuantity>0</PreorderQuantity>
            <Quantity>1.00</Quantity>
            <ShippingAddressId>75d5ae03-7a4d-4fc5-85c9-991a6548290f</ShippingAddressId>
            <ShippingMethodId>FreeShipping</ShippingMethodId>
            <ShippingMethodName>Free Shipping</ShippingMethodName>
            <Status i:nil="true" />
          </LineItem>
          <LineItem z:Id="i6">
            <Created>2013-05-14T12:04:34.1027676Z</Created>
            <Errors xmlns:d6p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
            <LastModified>2013-05-14T12:04:34.1027676Z</LastModified>
            <AllowBackordersAndPreorders>false</AllowBackordersAndPreorders>
            <BackorderQuantity>0</BackorderQuantity>
            <Catalog>Apple</Catalog>
            <CatalogCategory i:nil="true" />
            <CatalogItemCode>5b24ada9-3</CatalogItemCode>
            <CatalogItemId>04c7f90f-ae47-4ad9-b256-edbb96a6b793</CatalogItemId>
            <CatalogOutline />
            <Comment i:nil="true" />
            <Description i:nil="true" />
            <Discounts>
              <LineItemDiscount z:Id="i7">
                <Created>2013-05-14T12:04:34.1027676Z</Created>
                <Errors xmlns:d8p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
                <LastModified>2013-05-14T12:04:34.1027676Z</LastModified>
                <DiscountAmount>10.00</DiscountAmount>
                <DiscountCode i:nil="true" />
                <DiscountId>5917bccb-b202-4616-8378-408fce6a6d50</DiscountId>
                <DiscountName>$10 Gift Card</DiscountName>
                <DisplayMessage>$10 Gift card for orders over $100</DisplayMessage>
                <PromotionId>a9804bdf-dbc2-4b46-af06-6145fc085d8c</PromotionId>
                <LineItem z:Ref="i6" />
                <LineItemId>8b0fddb9-e82a-42aa-941d-358e9fb18c94</LineItemId>
              </LineItemDiscount>
            </Discounts>
            <DisplayName>$10 Gift card</DisplayName>
            <ExtendedPrice>0</ExtendedPrice>
            <FulfillmentCenterId i:nil="true" />
            <InStockQuantity>0</InStockQuantity>
            <InventoryStatus i:nil="true" />
            <LineItemDiscountAmount>10.00</LineItemDiscountAmount>
            <LineItemId>8b0fddb9-e82a-42aa-941d-358e9fb18c94</LineItemId>
            <ListPrice>10.00</ListPrice>
            <MaxQuantity>0</MaxQuantity>
            <MinQuantity>1.00</MinQuantity>
            <Options />
            <OrderForm z:Ref="i4" />
            <OrderFormId>21b9f8f6-c56c-4303-ba2e-e649a90ce269</OrderFormId>
            <ParentCatalogItemId i:nil="true" />
            <PlacedPrice>10.00</PlacedPrice>
            <PreorderQuantity>0</PreorderQuantity>
            <Quantity>1.00</Quantity>
            <ShippingAddressId>75d5ae03-7a4d-4fc5-85c9-991a6548290f</ShippingAddressId>
            <ShippingMethodId>FreeShipping</ShippingMethodId>
            <ShippingMethodName>Free Shipping</ShippingMethodName>
            <Status i:nil="true" />
          </LineItem>
        </LineItems>
        <Name>OrderForm_For_John Doe</Name>
        <OrderFormId>21b9f8f6-c56c-4303-ba2e-e649a90ce269</OrderFormId>
        <OrderGroup z:Ref="i1" />
        <OrderGroupId>816dd41c-d393-4ed4-925e-4269dcd47c93</OrderGroupId>
        <Payments>
          <Payment z:Id="i8" xmlns:d5p1="http://schemas.datacontract.org/2004/07/VirtoCommerce.Foundation.Orders.Model" i:type="d5p1:OtherPayment">
            <Created>2013-05-14T12:04:34.1027676Z</Created>
            <Errors xmlns:d6p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
            <LastModified>2013-05-14T12:04:34.1027676Z</LastModified>
            <Amount>0</Amount>
            <AuthorizationCode i:nil="true" />
            <BillingAddressId>e80bf493-c2cf-4cd3-8794-91e3dc49f400</BillingAddressId>
            <ContractId i:nil="true" />
            <OrderForm z:Ref="i4" />
            <OrderFormId>21b9f8f6-c56c-4303-ba2e-e649a90ce269</OrderFormId>
            <PaymentId>2c778a59-64db-42a7-9579-c8bba425a7c4</PaymentId>
            <PaymentMethodId>Phone</PaymentMethodId>
            <PaymentMethodName>Phone</PaymentMethodName>
            <PaymentType>0</PaymentType>
            <PaymentTypeId>0</PaymentTypeId>
            <Status>Processing</Status>
            <TransactionType i:nil="true" />
            <ValidationCode i:nil="true" />
          </Payment>
        </Payments>
        <Shipments>
          <Shipment z:Id="i9">
            <Created>2013-05-14T12:04:34.1027676Z</Created>
            <Errors xmlns:d6p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
            <LastModified>2013-05-14T12:04:34.1027676Z</LastModified>
            <Discounts />
            <FulfillmentCenterId i:nil="true" />
            <ItemSubtotal>0</ItemSubtotal>
            <ItemTaxTotal>0</ItemTaxTotal>
            <OrderForm z:Ref="i4" />
            <OrderFormId>21b9f8f6-c56c-4303-ba2e-e649a90ce269</OrderFormId>
            <Picklist xmlns:d6p1="http://schemas.datacontract.org/2004/07/VirtoCommerce.Foundation.Orders.Model.Fulfillment" i:nil="true" />
            <PicklistId i:nil="true" />
            <ShipmentId>b24cbecd-3fb5-4886-8ef3-578c93aa9cce</ShipmentId>
            <ShipmentItems>
              <ShipmentItem z:Id="i10">
                <Created>2013-05-14T12:04:34.1027676Z</Created>
                <Errors xmlns:d8p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
                <LastModified>2013-05-14T12:04:34.1027676Z</LastModified>
                <LineItem z:Ref="i5" />
                <LineItemId>5f715fb5-f774-4a82-95a1-d819b3602006</LineItemId>
                <Quantity>1.00</Quantity>
                <Shipment z:Ref="i9" />
                <ShipmentId>b24cbecd-3fb5-4886-8ef3-578c93aa9cce</ShipmentId>
                <ShipmentItemId>75ab3aae-9605-44bc-a0ac-96c82ddbe703</ShipmentItemId>
              </ShipmentItem>
            </ShipmentItems>
            <ShipmentTotal>0</ShipmentTotal>
            <ShipmentTrackingNumber i:nil="true" />
            <ShippingAddressId>75d5ae03-7a4d-4fc5-85c9-991a6548290f</ShippingAddressId>
            <ShippingDiscountAmount>0</ShippingDiscountAmount>
            <ShippingMethodId>FreeShipping</ShippingMethodId>
            <ShippingMethodName>Free Shipping</ShippingMethodName>
            <ShippingTaxTotal>0</ShippingTaxTotal>
            <Status>AwaitingInventory</Status>
            <Subtotal>0</Subtotal>
            <TotalBeforeTax>0</TotalBeforeTax>
          </Shipment>
        </Shipments>
        <ShippingTotal>0</ShippingTotal>
        <Status i:nil="true" />
        <Subtotal>359.9900</Subtotal>
        <TaxTotal>0</TaxTotal>
        <Total>349.9900</Total>
      </OrderForm>
    </OrderForms>
    <OrderGroupId>816dd41c-d393-4ed4-925e-4269dcd47c93</OrderGroupId>
    <OrganizationId i:nil="true" />
    <ShippingTotal>0</ShippingTotal>
    <Status>Pending</Status>
    <StoreId>SampleStore</StoreId>
    <Subtotal>359.9900</Subtotal>
    <TaxTotal>0</TaxTotal>
    <Total>349.9900</Total>
    <ExpirationDate i:nil="true" />
    <RmaRequests />
    <TrackingNumber>Order-2013.05.14-00000</TrackingNumber>
  </Order>
</ContextDoc>

It is then processed by the template similar to this:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ms="urn:schemas-microsoft-com:xslt">
  <xsl:output method="html" />
  <xsl:template match="/">
    <html>
      <head id="Head1">
        <style type="text/css">
          #PurchaseOrder {}
          h1 {font-size: 20px;}
          h2 {font-size: 18px;}
          h3 {font-size: 16px; background-color: #cccccc; padding: 2px 2px 2px 2px}
          .introduction {padding: 5px 0 0 0}
          .footer {padding: 5px 0 0 0}
        </style>
        <title>
          Order Notification
        </title>
      </head>
      <body>
        <xsl:apply-templates select="//Order"></xsl:apply-templates>
      </body>
    </html>
  </xsl:template>
  <xsl:template match="Order">
    <div id="PurchaseOrder">
      <h1>Sale/Order Notification from the Store</h1>
      <h1>**ORDER SUMMARY</h1>
      <xsl:call-template name="OrderHeader"></xsl:call-template>
      <div class="OrderForms">
        <h2>Products Purchased:</h2>
        <xsl:apply-templates select="OrderForms/OrderForm"></xsl:apply-templates>
      </div>
      <xsl:call-template name="OrderFooter"></xsl:call-template>
      <div class="Footer">
        Regards,<br/> your Company.
      </div>
    </div>
  </xsl:template>
  <xsl:template name="PaymentPlanSchedule">
    <div class="schedule">
      Payment Schedule: starting&#160;<xsl:value-of select="ms:format-date(StartDate, 'MMM dd, yyyy')"/>&#160;every&#160;<xsl:value-of select="CycleLength"/>&#160;<xsl:call-template name="PlanCycle" />&#160;for&#160;<xsl:value-of select="MaxCyclesCount"/>&#160;<xsl:call-template name="PlanCycle" />&#160;till&#160;<xsl:value-of select="ms:format-date(EndDate, 'MMM dd, yyyy')"/>
    </div>
  </xsl:template>
  <xsl:template name="PlanCycle">
    <xsl:value-of select="CycleMode"/>(s)
  </xsl:template>
  <xsl:template name="OrderHeader">
    Order Number: <xsl:value-of select="TrackingNumber"/><br/>
    Status: <xsl:value-of select="Status"/><br/>
    Name: <xsl:value-of select="CustomerName"/><br/>
    Email: <a>
      <xsl:attribute name="href">
        mailto:<xsl:value-of select="//OrderAddresses/OrderAddress[OrderAddressId=//AddressId]/Email"/>
      </xsl:attribute>
      <xsl:value-of select="//OrderAddresses/OrderAddress[OrderAddressId=//AddressId]/Email"/>
    </a>
  </xsl:template>
  <xsl:template name="OrderFooter">
    <h3>Order Summary</h3>
    <div class="OrderSummary">
      Sub Total: <xsl:value-of select="BillingCurrency"/>&#160;<xsl:value-of select="format-number(Subtotal, '###,##0.00')"/><br/>
      Handling Total: <xsl:value-of select="BillingCurrency"/>&#160;<xsl:value-of select="format-number(HandlingTotal, '###,##0.00')"/><br/>
      Shipping Total: <xsl:value-of select="BillingCurrency"/>&#160;<xsl:value-of select="format-number(ShippingTotal, '###,##0.00')"/><br/>
      Total Tax: <xsl:value-of select="BillingCurrency"/>&#160;<xsl:value-of select="format-number(TaxTotal, '###,##0.00')"/><br/>
      TOTAL: <xsl:value-of select="BillingCurrency"/>&#160;<xsl:value-of select="format-number(Total, '###,##0.00')"/><br/>
    </div>
  </xsl:template>
  <xsl:template match="OrderForm">
    <div class="OrderForm">
      <div class="OrderForms">
        <h3>Line Items</h3>
        <xsl:apply-templates select="LineItems/LineItem"></xsl:apply-templates>
        <h3>Payments</h3>
        <xsl:apply-templates select="Payments/Payment"></xsl:apply-templates>
      </div>
      <div class="OrderSummary">
      </div>
    </div>
  </xsl:template>
  <xsl:template match="LineItem">
    <div class="LineItem">
      <xsl:value-of select="format-number(Quantity, '###,###.##')"/>&#160;<xsl:value-of select="DisplayName"/> - <xsl:value-of select="//BillingCurrency"/>&#160;<xsl:value-of select="format-number(ListPrice, '###,###.00')"/> each
    </div>
  </xsl:template>
  <xsl:template match="Payment">
    <div class="Payment">
      Payment Method: <xsl:value-of select="PaymentMethodName"/><br/>
      Amount: <xsl:value-of select="//BillingCurrency"/>&#160;<xsl:value-of select="format-number(Amount, '###,##0.00')"/>
    </div>
  </xsl:template>
</xsl:stylesheet>

The resulting output would be:

<html xmlns:ms="urn:schemas-microsoft-com:xslt">
  <head id="Head1">
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <style type="text/css">
                    #PurchaseOrder {}
                    h1 {font-size: 20px;}
                    h2 {font-size: 18px;}
                    h3 {font-size: 16px; background-color: #cccccc; padding: 2px 2px 2px 2px}
                    .introduction {padding: 5px 0 0 0}
                    .footer {padding: 5px 0 0 0}
                </style>
    <title>
                    Order Notification
                </title>
  </head>
  <body>
    <div id="PurchaseOrder">
      <h1>Sale/Order Notification from the Store</h1>
      <h1>**ORDER SUMMARY</h1>
        Order Number: Order-2013.05.14-00000<br>
        Status: Pending<br>
        Name: John Doe<br>
        Email: <a href="mailto:john_doe_work@gmail.com">john_doe_work@gmail.com</a><div class="OrderForms">
        <h2>Products Purchased:</h2>
        <div class="OrderForm">
          <div class="OrderForms">
            <h3>Line Items</h3>
            <div class="LineItem">1 Samsung LN26D450 26-Inch 720p 60Hz LCD HDTV (Black) - USD 349.99 each
        </div>
            <div class="LineItem">1 $10 Gift card - USD 10.00 each
        </div>
            <h3>Payments</h3>
            <div class="Payment">
            Payment Method: Phone<br>
            Amount: USD 0.00</div>
          </div>
          <div class="OrderSummary"></div>
        </div>
      </div>
      <h3>Order Summary</h3>
      <div class="OrderSummary">
            Sub Total: USD 359.99<br>
            Handling Total: USD 0.00<br>
            Shipping Total: USD 0.00<br>
            Total Tax: USD 0.00<br>
            TOTAL: USD 349.99<br></div>
      <div class="Footer">
                Regards,<br> your Company.
            </div>
    </div>
  </body>
</html>

Namespaces

  • VirtoCommerce.Foundation.Frameworks.Templates - Contains interfaces for template service
  • VirtoCommerce.Web.Client.Services.Templates - Contains implementation of template service
  • VirtoCommerce.Foundation.Frameworks.Email - Contains interfaces for email service
  • VirtoCommerce.Web.Client.Services.Emails - Contains implementation of email service