Sana 9.1 SDK Partner Training

The course is designed for Sana SDK partners to give an overview of Sana Commerce product, describe existing possibilities, show the architecture of the framework and teach the basics of developing customizations using the Sana Commerce SDK.

All objectives of the current course are presented in the recommended learning order and are organized into the following groups:

  1. An overview of Sana Commerce functionality, hosting and configuration options (0.5-1 hour)
  2. Technical overview of the framework architecture, communication with ERP, search engine etc. (1-2 hours)
  3. Hands-on labs with the exercises to start customizing Sana (2-3 hours)

1.1. Integrated e-Commerce

Product overview


Sana Commerce is an e-Commerce solution for Microsoft Dynamics and SAP.

Sana consists of:

  • The frontend web application which is a publicly accessible webstore engine
  • The mobile/tablet ordering app
  • Sana Admin application is used to configure and manage the frontend and mobile app
  • Sana ERP add-on implementing the integration with customer's ERP system
  • Sana Commerce Framework component which connects all of the above altogether

Real-time integration

In contrast with ordinary e-commerce solutions, Sana is installed directly within customer's ERP which provides a possibility to reuse the existing ERP business logic together with the customer-specific customizations related to price calculation, stock determination, order placement etc. Other e-commerce solutions integrate by using the scheduled background tasks which synchronize the data between the webstore and the ERP. In this case, the chance that the data is out-of-date is much higher and most of the customer's customizations should be re-implemented in the webstore as well.

Changing the product price in ERP results in the updated price on the webstore. Meanwhile, placing an order on the webstore results in a new sales document in the ERP.

How does Sana integrate with ERP?

  • Scheduled background task is used to synchronize customer-specific prices
  • Customer-specific prices are always retrieved from ERP in real-time
  • Custom price calculations in ERP should be also implemented in Sana
  • Sana is installed within ERP
  • Product stock is always retrieved from ERP in real-time

1.2. Business Scenarios

B2X e-Commerce

Sana Commerce is a hybrid e-commerce solution which implements all Business-to-Consumer (B2C), Business-to-Business (B2B) and mixed (B2X) webstore scenarios.

The most common webstore scenarios are shown on the following picture:

And here is how do they behave:

  1. In closed B2B webstore anonymous customers does not even see the catalog, but when logged in, the catalog is visible and customer-specific prices are used.
  2. The B2B webstore can also have an open catalog, but until the customer logs in, the product prices are not shown at all.
  3. Hybrid configuration lets to support both B2C and B2B scenarios in a single webstore. In this case consumers will see special consumer prices while logged in B2B customers will see their specific pricing.

In addition to the above scenarios, there is also a way to enable or disable new customers registration.

Multi-store scenarios

Sana Commerce is a multi-store platform which allows to host multiple similar or completely different webstores in a single installation. Each webstore can have it's own design, catalog, customers, branding etc.

Below is an example of the multi-store solution where every webstore has its own catalog, design and branding, while all of them are connected to a single ERP administration.

And here is a use-case of the multi-store environment, where the design of all webstores is the same, the brand is the same, but all of them are targeting different countries and provide a country-specific content on each individual webstore.

Which are True?

  • Sana Commerce can be configured in B2B-only mode, so that only existing customers can log in to the webstore and place orders
  • Webstore can be only configured in B2B or B2C modes, but it cannot serve both types of customers at the same time
  • Multiple webstores in a single installation can have different designs

1.3. Webstore Design

Why does design matter?

The webstore design plays a huge role in webstore success. First of all, the webstore design represents a company brand, which is always recognizable and trusted by the end-users. Another fact is that a webstore design must be modern, attractive, user-friendly and the most important is that it should be unique. Fortunately, the standard design of Sana Commerce is already modern, attractive and user-friendly, but it's still standard. That is why it is so important to have a possibility to make it unique with as little effort as possible.

Sana Commerce provides several ways to customize the webstore design. Each one is targeting its own use-cases and has its own pros and cons. For example, one possibility is limited in functionality, but requires no cost during an upgrade to a newer version of Sana, while another has almost no limitations, but will add additional costs during future upgrades.

Use-case: Using standard template

Below is an example of webstore design which is using the standard Sana design template with the applied branding. Here the only customized things are the logo and some colors to match the brand's color scheme.

Use-case: Small customizations

There might be also a case which requires some minor customizations to the standard design which mostly can be done with some extra CSS or JavaScript code, but the overall webstore layout stays the same. Here is an example of the custom design which contains several small adjustments:

Use-case: Completely custom design

Another example scenario is a requirement for a completely custom webstore design. The one shown on the screenshots below has been created on top of Sana, but it is not using the standard Sana Commerce design template.

Available customization options

The design of the Sana Commerce webstore can be customized in several different ways, each having its own pros and cons:

Configurable Themes
Out of the box Sana provides a theming engine which gives a possibility to easily apply the company branding through the Sana Admin user interface without any modifications to the standard Sana. Theme lets the store owner to change the webstore logo, favicon, fonts and colors of the visual elements on the frontend. The limitation of this approach is that the webstore layout stays unchanged.

Design Packs
In order to customize the look and feel of the webstore, standard Sana installation can be also extended by uploading design packs. Design packs are special redistributable NuGet packages which can contain customized store layouts, custom page layouts and additional assets, like images, JS and CSS files. With the help of design packs, the layout of the whole webstore can be easily customized. Current store layout and page layouts are configurable per webstore. More information about the configurable themes and design packs can be found on this page of the Sana help website.

Inject custom CSS/JS
In several cases it might be needed to inject some extra JavaScript or CSS into a standard Sana, for example, in the situation when a custom client-side control is used somewhere in the content, like a banner slider or similar. This becomes possible with the HTML injections which can be configured in Sana Admin and provide a way to inject any pieces of HTML into the <head> element, at the beginning and at the end of the <body> tag.

SDK Customization
The last (but not least) possibility to customize the design is to change it using the Sana Commerce SDK. SDK provides a complete freedom to modifications, so that a standard design can be replaced with a completely new one and can even introduce some additional functionality to the standard webstore behavior.

Which options can be used to apply company branding to the webstore?

  • Configurable themes
  • Design packs
  • Custom CSS/JS injections
  • SDK customizations

Lets assume that company branding includes a custom logo, favicon and text color.

Choose all that apply.

Which options can be used to change the layout of web pages?

  • Configurable themes
  • Design packs
  • Custom CSS/JS injections
  • SDK customizations
Choose all that apply.

What is the easiest way to use different store layouts on different webstores within a single Sana installation?

  • Use configurable themes
  • Use design packs
  • Inject custom CSS/JS
  • Customize SDK

1.4. Installation & Configuration

Hosting: Simple setup

Below is a picture showing the most simple hosting option of Sana Commerce:

In this setup, the whole Sana Commerce is installed on a single server which combines both the web role and the SQL server role. The customer's ERP server is located somewhere inside the perimeter network behind the firewall.

Hosting: Complex scenario 1

Another hosting scenario is shown on the picture below:

This scenario demonstrates one of the ways to improve webstore performance by setting up several web service tier servers connected to a single ERP database server. Each web service executes ERP business logic, while all of them are connected to the same ERP database. As the ERP is the slowest part of the whole infrastructure, such configuration is mostly used in the following two scenarios:

  1. In a multi-store environment each individual web service handles requests for each individual webstore.
  2. Separate web services are configured to handle different requests, for example, price & stock calculations are handled by the first server, order management — by the second one and the rest — by the third server. This scenario can be used to improve the performance of a single webstore under high load.

In addition to scaling the ERP part, Sana Commerce SQL database can be also moved to a dedicated SQL server to improve the performance of the Sana Commerce web application itself which allows to handle more concurrent web users.

Hosting: Complex scenario 2

In this hosting example, different web services are connected to different ERP administrations. Such setup is mostly used in the next scenarios:

  1. In a multi-store environment, each individual webstore connects to different ERP administration and works with its own catalog, customers etc.
  2. There are some cases, when the catalog might be stored in one ERP, customers in another and orders are being placed to a third ERP administration. This case is possible in both single-store and multi-store environments.

Basically, knowing that different webstores as well as separate subsystems of Sana (like catalog, customers, orders etc.) can be connected to a single or different connection points, hosting options can vary a lot from project to project depending on the concrete requirements.

System requirements

The list of Sana Commerce software requirements is as follows:

  • Windows 2008 or later
  • SQL Server 2008 or later (express or better)
  • .NET Framework 4.5.1
  • MS Dynamics NAV 2009 or later (earlier versions support can be added on demand)
  • MS Dynamics AX 2009 SP1 or later (earlier versions support can be added on demand)

Hardware requirements:

  • Dual core CPU (Xeon recommended)
  • 2GB+ RAM
  • 40GB HDD

Hardware requirements highly depend on a concrete case. More powerful hardware will allow to handle more concurrent users, faster serve requests etc.

The full list of all supported ERP versions and editions as well as a separate hosting checklist document can be found on Sana Community portal.

Sana Installer

Sana Installer is a standalone application which automates most of the Sana Commerce installation steps. Sana Installer is provided in two forms:

  1. WinForms application, where all installation parameters are specified through the user interface
  2. Console application, where all installation parameters are specified in the configuration file

Sana Installer automated the following installation steps:

  • Creates a new application and application pool is IIS
  • Adds the website bindings to the new application in IIS
  • Restores the SQL database backup and creates a new SQL login for it
  • Extracts the Sana Commerce codebase
  • Sets the appropriate permissions for the application pool identity
  • Configures SMTP settings
  • Enables basic authentication on the corresponding parts of the website based on the selected deployment mode

But, Sana Installer does not install Sana into an ERP. This step should be done manually.

Additionally, there is a way to create a Sana Installer package out of the preconfigured customized Sana SDK and install it on the beta or live server.

The list of all installation steps is described on the Sana online help website.

Configuration options

Sana Commerce configuration options can be split into three categories.

Technical settings

Technical settings are configured in "web.config" file and include SMTP configuration, SQL connection strings, encryption keys, logging configuration etc.

Website settings

Website settings are configured after installation of Sana through the Sana Admin web application. They include, but are not limited to: ERP connection settings, webstore behavior, user interface settings etc. More information about all the available settings can be found in the user guide section of the Sana help website.

Settings in ERP

The last, but not least, portion of configuration should be done on the ERP side. The set of configuration settings in ERP varies per ERP type, but usually they should be configured at the early beginning of the webstore setup. For example, there are such settings, like which customer should be used for anonymous price & stock calculation, which countries are available on the webstore etc.

Security options

Web application security

Sana Commerce web application can be configured for full or partial HTTPS browsing to avoid the risk of man-in-the-middle attacks. Partial SSL configuration allows to use HTTPS protocol only on a subset of webstore pages which have higher security requirements (like profile or checkout sections) while the usual content can be still served over HTTP.

Sana Commerce has been fully tested against OWASP Top Ten vulnerabilities, like SQL injection, HTML injection, XSS, CSRF attacks and others.

Additionally, it is recommended to enable basic or windows authentication on top of the whole webstore or only on the Sana Admin area depending on the hosting setup.

Connection to ERP 

Taking into account that Sana Commerce is usually installed outside of the ERP network, the connection between them must be also secure.

First of all, the connection should be protected from the man-in-the-middle attacks. There are two recommended ways to achieve this goal:

  • Using SSL certificate to encrypt communication
  • Setup a VPN connection between the web server and the ERP server

In addition to the above, all requests to the ERP must be authenticated, so the recommended approach is to setup Windows authentication for the web service calls.

It is also advised to add IP-address checking in order to validate the origin of the request.

The security guidelines document with all the details is available on the Sana Community portal.

Scalability options

Several scalability options have been already explained in the hosting section which allow to split the load on the ERP server by pointing different webstores or different types of requests to different web services.

Another option is to scale the Sana Commerce web application to handle the high load. This can be done by configuring the load-balanced web environment which Sana supports out of the box.

Microsoft Azure virtual machines are also supported, so with the help of Azure traffic manager and availability sets the load-balanced environment can be easily configured. Azure App Service and Web/Worker roles are not supported at the current moment.

Sana Commerce also supports SQL Azure which, in its turn, provides a highly available triplicated SQL server instance.

More about load-balancing of Sana Commerce can be found in the help article about Sana Enterprise.

What is true about Sana Commerce?

  • Multiple webstores can be connected to different ERP administrations
  • Multiple webstores can be connected to a single ERP administration
  • Sana Commerce can be deployed in an Azure Web Role
  • Sana Commerce can be deployed on Azure Virtual Machine
  • SQL Azure is not supported
  • Sana Commerce can be deployed on Windows Server 2003
  • Sana Commerce does not support Microsoft SQL Server 2008

Which installation steps are automated by Sana Installer?

  • Creating web site in IIS
  • SQL database restore
  • Installing Sana in ERP
  • SMTP configuration
  • Upgrade to a newer version
Choose all that apply.

2.1. Sana Architecture

Technology Stack

Here is the technology stack of Sana Commerce:

Most of the things on the above picture are self-explaining, but some of them require additional clarification:

  • NHibernate ORM is used for SQL data access from the Sana Commerce framework
  • Lucene.NET library is used by Sana to perform lightning-fast full text search on the catalog with additional filtering functionality
  • Knockout.js library is used by a subset of pages on both the frontend and Sana Admin areas, but only on those pages which get benefit from using it
  • Bootstrap CSS framework is used only in Sana Admin area

High-level Overview

The overall picture of Sana Commerce components is shown below. It gives a high-level overview of the product architecture and structure.

Sana Commerce consists of the following components:

  • Sana Commerce Framework is a core of the product containing all the business logic.
  • With the help of eBusiness Connector component framework communicates to ERP.
  • On the other side of the communication channel (on the ERP side) there is a Sana Commerce ERP Extension which responds to all requests from the framework and is re-using the existing business logic of ERP. This extension is specific per ERP type, version, edition and localization and is installed within the ERP.
  • On top of the framework the REST Web Service API resides. It is used by the Sana Mobile app for integration with the webstore.
  • The Webstore itself and the Sana Admin area are built on top of the framework and share the same codebase with it.

Under the Hood

The internals of the Sana Commerce Framework are shown on the following picture:

Sana Commerce Framework consists of two layers: the higher Web Framework layer and the lower Commerce Framework layer.

Commerce Framework contains all the e-commerce business logic related to catalog & customers management, basket calculation, order placement etc. and it is also responsible for communication with the ERP.

The entry point of the commerce framework API is the corresponding CommerceFramework class which provides a set of static properties for each individual subsystem responsible for manipulating its own kind of data. Some of these subsystems (represented by the corresponding managers) are shown on the above picture and are grouped into the "Framework" block. Full list of managers available in CommerceFramework class is shown on the next page.

All managers and providers share the same component which is called the CommerceContext. This context holds the common execution state of the current context and provides such information as the current webstore identifier, language, e-commerce related settings, current customer identifier etc. Commerce context is also used in the higher level API and can be always accessed by the static "Context" property of the already familiar CommerceFramework class.

Web Framework resides between the MVC infrastructure and the Commerce Framework and encapsulates the webstore related functionality including the high-level data management on the user level and implements all required permission checks.

The entry point of the Web Framework API is the ShopApi class. Additional context information, like the logged in user, user interface settings etc. can be accessed through the ShopContext class which also belongs to the Web Framework layer.

The details of Web Framework itself and the integration of Sana into ASP.NET MVC is covered later in this course.


Full list of managers available in CommerceFramework class is shown in the following table:

Manager Responsibility Data source
ProductManager Retrieving products ERP
Managing product facets Search index
Managing product categories ERP
Retrieving variant components ERP
ShopManager Managing an e-commerce related data SQL database
Managing customer segments SQL database
Accessing shop settings SQL database
ProductSetManager Managing product sets SQL database
Retrieving shipping methods, calculating shipping rates SQL database
Determining payment methods, managing of payment related data SQL database


Managing shop accounts SQL database
BasketManager Managing baskets SQL database
Searching products, managing of product search index Search index
Searching customers, managing of customer search index Search index
OrderManager Calculating baskets, placing of orders and quotes promoting, retrieving of orders ERP
Managing order authorization data SQL database
CommonManager Retrieving currencies, countries, entities, etc ERP
CustomerManager Managing customers, customer statistics ERP
SalesPersonManager Retrieving sales persons ERP
ContactManager Managing contacts ERP
AddressManager Retrieving shipping addresses, billing addresses, shipping origin ERP
ContentManager Managing content items like news items, news letter subscription, content items, etc SQL database
SanaTextManager Retrieving sana texts SQL database
ThemeManager Retrieving themes SQL database
Managing field translations of various entities SQL database
Managing content items translations SQL database

Managing mobile device information

SQL database
Managing ERP connection and ERP data status SQL database
EnterpriseManager Managing Sana Enterprise data SQL database
NavigationManager Retrieving navigation SQL database
Managing product content information (ratings, reviews, product images) SQL database
WebsiteManager Retrieve website information (domains, languages) SQL database
PriceManager Retrieving product price information ERP
StockManager Retrieving product stock information ERP

Some managers are using only SQL providers to manage the data stored in Sana Commerce SQL database. Another set of managers are using providers which communicate directly with ERP, these providers belong to eBusiness Connector. Managers which are using ERP data also use another set of providers which retrieve ERP data from SQL database. The data is prepared and saved to SQL database by scheduled tasks. ProductFacetManager, ProductSearchManager, CustomerSearchManager are using the search engine API based on Lucene.NET library to perform a fast search of the corresponding records. Each manager has its underlying data provider to manage the corresponding data. Providers are responsible only for data manipulation, while the corresponding higher-level managers also contain business logic and data caching logic to avoid unnecessary calls to ERP.

ERP data usage

Sana Commerce saves needed ERP data in SQL database using scheduled tasks. It is needed to allow working in maintenance mode without ERP connection and to improve performance by reducing amount of calls to ERP system.  "Product import" task performs importing of product data, this data is indexed by search engine based on Lucene.NET library and it is saved in Sana Commerce SQL database. "Customer import" task performs the same actions for customers data. "General information import" task imports the rest of ERP data needed for Sana Commerce and saves it in Sana Commerce SQL database (for example currencies, countries, etc). 

When ERP data is available in Sana Commerce SQL database, it can be used by managers. Managers which use eBusiness Connector as a data source have two sets of providers: providers to communicate directly with ERP and providers to retrieve prepared ERP data from SQL database. For example ProductManager class uses two providers: ProductProvider which communicates with ERP and OfflineProductProvider which uses SQL database. The ERP data saved in SQL database is called internally "offline data" in Sana Commerce and providers which are using "offline data" are called "offline providers". The ERP data retrieved directly from ERP is called "online data".

Every manager has its own policy of using online and offline providers. For example, Product manager always tries to use offline general product data, while Price and Stock managers always try to fetch actual online data from ERP and use offline data only in maintenance mode. 

Product data retrieval from different sources is shown on the following activity diagram:

Which technologies are used in Sana Commerce?

  • Lucene.NET
  • Apache Solr
  • Bootstrap
  • Zurb Foundation
  • AngularJS
  • KnockoutJS
  • .NET Framework 4 and C# 4
  • .NET Framework 4.5 and C# 5
  • jQuery
  • NHibernate
  • Entity Framework
  • LINQ to SQL
Choose all that apply.

True or False?

  • eBusiness Connector is used to communicate to ERP
  • Caching logic is a part of providers layer
  • CommerceFramework is using ShopContext for a context-specific information
  • CommerceFramework is using CommerceContext for a context-specific information
  • Content provider is a part of eBusiness Connector
  • Shop subsystem is using the SQL provider to connect to Sana SQL database

2.2. Sana Mobile & Web Service API

Ordering App for Sales Agents

Out of the box, Sana provides a mobile ordering application for sales agents which allows to place an order on behalf of customer in a mobile-friendly approach. The app is developed for iPad.

Ordering app is not a standalone application, but instead it is built on top of the reusable and extendable Sana Commerce Mobile framework which is described later in this topic.

Here are some screenshots of the application to get a visual understanding of how it looks:


Under the Hood

As it was noticed, the Sana's "Ordering app for sales agents" is built on top of the Sana Commerce Mobile framework which is connected to the Web Service API to get the real-time product data, pricing & stock information and to place the orders.

Here is an overview of the Sana Mobile architecture:

Sana Mobile consists of:

  • Sana Mobile Shell application
  • Inner single-page web app built with HTML, JS and CSS

Sana Mobile Shell is a native application for iOS wrapped into the PhoneGap infrastructure. It does not contain any application-specific functionality, but the main thing it does is that it downloads the inner app from the specified web installation of Sana Commerce and connects it to the corresponding Web Service API. This means that:

  1. The application logic is not embedded into the native mobile application and can be easily customized
  2. All users will always have the most recent version of their application

The "Ordering App" is an inner HTML5 single-page application hosted inside Sana Mobile Shell, but it does not mean that this is the only application which can be hosted there. Sana Mobile Shell is a unified extension on top of PhoneGap which can download, update and host almost any inner HTML5 app.

The inner app itself communicates with the REST Web Service API hosted inside the Sana Commerce installation to get the real-time product or customer data and place real-time orders.

Technology Stack

The technologies used to build Sana Mobile are shown on the following picture:

Sana Mobile Shell is built on top of PhoneGap and is compiled into a native app for iPad. The inner "Ordering app for sales agents" is a single-page client web application built on HTML 5, CSS 3 and JavaScript. It is also using several JS libraries, like jQuery, jQuery Mobile and Knockout.js. SQLite is used from inside the app to store the local data.

Knockout.js has been chosen among the variety of different MVVM JavaScript frameworks due to its low entrance barrier for developers.

Web Service API

Sana Mobile app is connecting to the Web service API hosted inside the Sana Commerce installation in order to get the product data, price & stock information, place orders etc.

Web service is built using Windows Communication Foundation (WCF) on top of the Sana Commerce framework. The communication with the service is REST-based and the authentication ticket is required to be sent in each request to identify the caller. The web service itself is a part of the Sana Commerce SDK which means that it is easily extendable, customizable and have an access to the full framework API.

Both XML and JSON messaging formats are supported by the web service and is determined based on the "Accept" HTTP request header.

Customization options

"Ordering app for sales agents" can be customized for project needs in several different ways. As usual, each way is different and has its advantages and disadvantages.

Customized app inside the standard shell

The first and the simplest way to customize the app is just to change the existing HTML, JS and CSS files of the app and place an updated version into the Sana Commerce installation directory. Sana Mobile Shell will download the updated app automatically, so there is no need to publish the app to the App Store, because the shell app is already published there. 

Customized app inside a re-branded shell

The second option is to customize the provided Sana Mobile Shell in order to apply custom branding including a custom app name, an icon, etc. Shell can be customized in addition to the first approach, but in this case it should be built into the native apps and published to the application markets as a brand new application. Please, notice, that the customized shell will still be capable of downloading the inner app and all its updates from the server in the same way as the standard one does. Also be aware, that it takes some time for an app to be reviewed and published as well as it requires to have developer accounts on all of these markets.

Sana Mobile Questions

  • The app code is hosted within a webstore and the latest application is downloaded on startup
  • The app code is embedded and the application is updated via App Store
  • Only inner HTML5 application can be customized while the native app cannot be re-branded
  • Only iPad is supported

The truth about Web Service API

  • Built using ASP.NET Web API
  • Built using WCF
  • REST-based
  • Supports XML requests
  • Supports JSON requests

2.3. eBusiness Connector

What is eBusiness Connector?

eBusiness Connector is a component of Sana Commerce which is responsible for communication with ERP. It consists of:

  1. a set of providers which constructs the XML requests to be sent, and parses XML responses received from the ERP
  2. an extendable set of connections which are responsible for sending the prepared XML requests to different ERP systems and receiving back the responses

Dynamics Integration

Here is a self-describing picture which visualizes the integration with Microsoft Dynamics ERP systems and the role of eBusiness Connector in this process:

As shown on the picture, the communication with Microsoft Dynamics is based on SOAP web services.

SAP Integration

Almost the same picture below describes the communication with SAP:

The only difference between this picture and the previous one is in steps 5 to 8 where a different type of connection is used, but everything else stays the same.

Integrate with Any ERP

And here is an example of integrating Sana Commerce with any other ERP system:

So, the only thing to be implemented and plugged-in into Sana Commerce is the communication channel (the connection implementation) and the business logic on the ERP side.


eBusiness Connector is fully covered with the documentation including:

  • The internal architecture of eBusiness Connector
  • Extensive descriptions of all methods which are invoked on the ERP side with examples of XML requests and responses
  • A how-to guide about connecting Sana Commerce to a custom ERP system

The documentation can be found here.

eBusiness Connector can be used to connect only to...

  • Microsoft Dynamics
  • SAP
  • Microsoft Dynamics & SAP
  • Any ERP system

Which data format is used in eBusiness Connector?

  • JSON
  • XML
  • YAML
  • Comma-separated values
  • BSON

2.4. Sana Search

About Sana Search

Sana Search is a separate low-level component of Sana Commerce which is based on Lucene.NET library and provides a possibility to perform very fast full text search over the full set of records. Sana Search engine provides an API to search records using full text keywords, apply miscellaneous filters on the result set and calculate counts of results for user-defined facets.

Sana Commerce is using it to search products, customers, contacts and sales agents. In order to make these records searchable, first they have to be added to the Lucene search index. While the search is real-time, indexing process is performed by the background scheduled tasks.

The details of the products indexing process which influence the search and filter possibilities are configurable in Sana Admin on the Index fields page.

Additionally, the Search settings page can be used to tweak the search behavior, but these settings do not influence the indexing process, so that they can be changed at any time without the need to rebuild the search index.

Indexing Products

Below is a data flow of the products indexing process.


First of all, the index must be configured to setup which data and how should be actually indexed. Next, the Product import task should be started (manually or scheduled for a specific time).

Then, the task gets the products from ERP, adds them to the index and also stores in the offline storage to be used in emergency cases when the real-time connection to ERP is not available.

Initially, the "Product import" task will process all products which are marked in ERP to be visible on the webstore. At the next run, the task will perform an incremental indexing process by requesting only those products which have been changed since the last task run. If the task fails at some moment, it will continue the indexing process starting from a failure point during the next run.

Changing any index settings requires a full index to be rebuilt, so that instead of an incremental indexing, a full re-index process is started at the next task run.

Searching Products

This picture shows the data flow of the product search:

Sana Search engine evaluates the search request and returns the ordered list of products references which match the search request. After that, a real-time product data is requested from ERP for the list of products returned by the search engine, so that the real-time customer-specific prices and inventory are still used.

Which search engine is Sana Search built on?

  • Sphinx
  • Elastic
  • Solr
  • Lucene
  • SQL Server Full-Text Search

What entities are being searched in Sana Commerce using Sana Search engine?

  • Contacts
  • Customers
  • Orders
  • Countries
  • Products
  • Sales agents
  • Product categories
Choose all that apply.

2.5. Sana Commerce SDK

SDK Structure

Sana Commerce SDK is a Visual Studio solution containing the following projects:

  • Sana.Commerce.Sdk
    A class library project containing all common code used in all other SDK projects. Particularly, it contains classes for all entities used in Sana Commerce, pre-registered classes for all providers and managers which are ready for customizations, NHibernate mappings and a "FrameworkInitializer" class containing all the initialization logic.
  • Sana.Commerce.Startersite
    This is the main web application project containing the frontend and Sana Admin webstore areas. The internal structure of this project is described later in this course.
  • Sana.Commerce.Webservice
    A web application project containing a REST Web Service which is used by Sana Mobile.
  • Sana.Commerce.TaskService
    A Windows service application used in Sana Enterprise to run the scheduled background tasks.


Setting Up Development Environment

This article covers the steps to setup a development environment in order to develop a project customizations based on Sana Commerce SDK.

Here are the software requirements which have to be checked first:

  • Visual Studio 2013 Professional or higher
  • Microsoft SQL Server 2008 or later (can be also a remote server accessible from the developer computer)
  • Internet connection (only when building the solution for the first time)
  • (Optional) Web Essentials extension for Visual Studio 2013

When all software requirements are satisfied, the next steps should be followed to start up with Sana Commerce SDK:

  1. Download both Sana Commerce Framework and SDK packages
  2. Restore the database "SanaStore.bak" from the framework package to the prepared SQL server
  3. Unpack the SDK package and open solution file "SDK\Sana Commerce.sln" in Visual Studio
  4. Build the solution (during the first build Visual Studio downloads all NuGet dependencies)
  5. Open the "web.config" file in the "Sana.Commerce.Startersite" project and do the following:
    • Change the connection string to point to a recently restored database
    • Set the value of "DefaultWebsite" application setting to "SanaStore" (this is an identifier of the default webstore provided in the out of the box database)
  6. Open the "Package Manager Console" window in Visual Studio and run the script ".\AesKeysGenerator.ps1" - it generates new encryption keys and puts them into "web.config" file
  7. Start the "Sana.Commerce.Startersite" project right from the Visual Studio - the home page of the webstore will be opened
  8. Append the "/admin" to the webstore URL in browser to navigate to Sana Admin area
  9. Create the first admin user, login, read and accept the EULA and follow the "First use guide" to get acquainted with Sana and connect it to ERP

How many projects are in Sana Commerce SDK solution?

  • 2
  • 3
  • 4
  • 5

2.6. Two Pillars of Sana Code

Entity & Entity Fields

The first pillar of everything in Sana Commerce is that all entity classes, like products, customers, orders, countries etc. are inherited from a single common base class called Entity which also implements a corresponding IEntity interface.

The "Entity" class has a "Fields" property which is designed to store custom additional fields with the entity without a need to add any extra properties to the final class:

Here is an example of using a custom field:

The first line gets the value of a custom field and casts it to a string, the second line shows how to set a value of a custom field.

The last line marks the custom field to be saved in the corresponding column of the corresponding table in ERP when the entity itself is being saved.

Another feature is to request the values of custom fields or columns from ERP together with the entities. Almost all methods which get the data from ERP accept an instance of load options which tells how and which entities to retrieve. All these load options implement a common interface "IEntityBaseLoadOptions", which has a property with the name "EntityFields". This property is a list of string names of extra fields to be requested from ERP:

When the load options are setup in this way, the values of these fields will become available in the "Fields" property of each fetched entity.

Be aware, that all functionality related to saving or requesting extra fields from ERP does not work with calculated fields (also flow fields in NAV).

Another use-case of the extra fields functionality is its integration with Sana SQL database. Most entities which are stored in SQL database are also inherited from "Entity" class and have a special "Fields" column in the corresponding SQL tables. This column is of type XML and stores the values of all properties which do not participate in queries so are not needed to be represented by separate table columns. There are two ways to store a custom data within the entity record in SQL database:

  1. All custom fields added to the fields collection (the "Fields" property) are automatically saved into the "Fields" column of the corresponding SQL table.
  2. Another way is to add a usual property to the final entity class (for example, "Product" class) and mark it with XmlFieldAttribute. The value of this property is added automatically to the fields collection before saving an entity in SQL database and is also automatically moved back when the entity is loaded from the database.

The third important generic feature is a GetEntities method of the Common manager. It provides a possibility to load the data from any table in ERP which is not covered by the standard Sana Commerce API. This method also accepts the load options instance of type IEntityListLoadOptions which gives a possibility to specify the list of fields or columns to load, the filter to apply as well as paging and sorting options.

Here is an example of its usage:

As a result, the "entities" variable holds a collection of entities for the list of requested vendors. Each entity contains two fields: "No." and "Name" which are filled with values from the corresponding columns in ERP. The resulting list contains only non-blocked vendors sorted by name in ascending order (according to the load options). Due to the paging settings, no more than 10 vendors have been requested. When paging is not set up, all records are returned. Additionally, the collection of entities also contains a TotalCount property which can be used to check how many records are there in total ignoring paging options.

Which method of the Common manager can be used to get the records from a custom table in ERP?

  • GetItems
  • GetRecords
  • GetList
  • GetObjects
  • GetEntities

What is the name of the base class of all entities in Sana Commerce?

  • Record
  • BusinessObject
  • Entity
  • BusinessEntity

Which attribute should be applied to a custom property in order to be saved in the "Fields" XML column in SQL database?

  • AutoFieldAttribute
  • StoreWithEntityAttribute
  • XmlFieldAttribute
  • XmlIncludeAttribute
  • CustomFieldAttribute

Object Manager

The second pillar of Sana Commerce internal infrastructure is the ObjectManager class. This class is a wrapper over a dependency injection pattern based on Unity.

It is used in Sana Commerce to register and resolve implementation classes for almost all types in the framework. It also keeps track of the lifetime of all contexts and services within the framework.

The most common use-case of the ObjectManager is to replace a standard Sana implementation of some component with a customized or extended one. Here is an example of the ObjectManager API:

The first four lines demonstrate the API to register implementation using different objects lifetime while the last line is used to get a new or current instance of the component depending on the configured lifetime.

  • RegisterType method just maps the "T" type to "TImpl" type and each time GetInstance method is called a new instance of "TImpl" is returned.
  • RegisterSingletonType and RegisterInstance methods set up a singleton object lifetime which means that each time GetInstance method is called the same instance of "TImpl" is returned.
  • RegisterSingletonTypePerRequest method sets the objects lifetime in a such way that within a single web request the same "TImpl" instance is returned, while in a different web request a different instance is used. This lifetime is mostly used for per request contexts, like the CommerceContext and ShopContext.

Almost all standard Sana registrations can be found in the FrameworkInitializer class located in the "Sana.Commerce.Sdk" project. All other are located in "Global.asax.cs" file in the root of the "Sana.Commerce.Startersite" project.

Which class is used to register entities and services in Sana Commerce and to resolve their instances?

  • ObjectManager
  • ObjectResolver
  • EntityManager
  • EntityResolver
  • ServiceLocator
  • DependencyResolver

What dependency injection container is used inside the ObjectManager class?

  • Autofac
  • Unity
  • Castle Windsor
  • Ninject
  • StructureMap
  • MEF

2.7. Web Framework

Web Application

Both the webstore frontend and the Sana Admin are two parts of a single "Sana.Commerce.Startersite" web application project.

Below is an overview of the project structure:

  • App_Data
    This directory contains the resource files for all installed language packs including translations of the standard page elements and messages, e-mail templates and Sana Admin UI texts.
  • App_Start
    This folder contains several independent classes which perform miscellaneous registrations on application startup.
  • Areas/Admin
    This is the root of the Sana Admin application area.
    • Metadata
      Contains the classes describing the Sana Admin model metadata of existing entities used to generate dynamic edit forms.
    • Views
      Admin area views directory.
    • AdminAreaRegistration.cs
      The class which contains Admin area-specific registrations, like controllers, model binders etc.
  • content
    A root folder for all publicly accessible content.
    • admin
      A folder which contains all public content files for the Admin area.
    • css
      A folder for all CSS and LESS files.
    • files
      A folder for all content files which are also manageable via the Sana Admin user interface.
    • fonts
      A folder which contains all custom fonts.
    • script
      A folder which contains all JavaScript files.
  • Views
    A root directory for all frontend views and helpers.
  • Global.asax.cs
    Invokes all common registration pipelines as well as registers frontend-specific stuff.


Each web request to the application starts with a routing pipeline. Sana is using a standard ASP.NET Routing infrastructure, but extends its functionality with several additional concepts.

First of all, instead of the standard "Route" class from the "System.Web.Routing" namespace, Sana is using an open-source library "Elastic.Routing" which is quite similar to the standard one, but exposes some extra functionality. The description of all features can be found on the GitHub project page.

Additionally, all frontend routes in Sana are organized into several groups which are registered in the following priority:

Routes group



These are mostly the technical routes to match requests to the content files, web services etc. These routes do not depend on the current context and will always serve the content corresponding to the requested URLs.


Routes for system pages with predefined URLs. They are almost not depending on the context, except that the language parameter is also present in the URL.


This group contains routes to the content pages which URLs are specified in Sana Admin as properties of the corresponding entities (news items, flexi-pages, website redirects etc.). To match one of these routes a request to the database is required. The result of the route evaluation depends on the requested webstore.


There are only two dynamic routes in Sana which can match almost any URL. They are a product page route and a product list page route with the facets as an extra path appended to the initial URL. These two are the most heavy and complicated routes.


This group may contain any routes matching the request which all previous routes failed to evaluate. Standard Sana does not provide any fallback routes out of the box.

Sana Admin routes are registered in the route table before any frontend routes, because all their URL templates are starting with the "admin/" prefix. Admin area routes registrations are located in the "AdminAreaRegistration" class.

Frontend routes are registered through the routing add-on infrastructure. A routing add-on is represented by a class implementing the "IRoutingAddon" interface. All such classes are plugged in via the "RegisterAddon" method of the "FrontendRoutesRegistrator" class. The "FrontendRoutesRegistrator" class is single-instance and can be retrieved through the "ObjectManager.GetInstance" method.

Each routing add-on can add, remove or replace any route at the beginning or at the end of any group of routes described above with the help of "SanaRouteCollection" class API. It also contains several shorthand methods for common routes registrations, like "MapSystemPageRoute", "MapActionRoute" and "MapActionsRoute". Refer to the API documentation for more details.

Below is an example of the routing add-on:

In this example, a routing add-on registers a new route at the beginning of the static routes group and replaces an existing route to the ‘Contact us’ page with a custom one. Additionally, the static "Initialize" method can be used to register this add-on in the "FrontendRoutesRegistrator" class.

All standard Sana frontend routes are being registered through the frontend controller classes in order to logically group the routes and actions handling them in a single place. Technically, all frontend controllers are also individual routing add-ons and can register their own routes in any of the defined groups. It is described in more details in the section about controllers.

URL Construction

The URLs to the Admin area pages are constructed in a usual way by passing the controller and action names into the "Action" method of the default "UrlHelper" class. The Admin area has a standard generic route "admin/{controller}/{action}/{id}", which can be used to access any action of any controller of the Admin area.

To construct the URL to one of the frontend pages, first of all refer to the "UrlsBuilder" class. It contains methods to build the URL to the corresponding standard Sana pages. Inside the frontend controller or frontend Razor view the "UrlsBuilder" instance can be accessed through the "Sana" property of the "FrontendUrlHelper" class, like in the following example:

In the example above "Url.Sana.NewsOverview()" builds the URL to the news overview page, while "Url.Sana.InternalPage(item)" builds the canonical URL to the news item page.


All controllers in Sana Commerce are registered through the "ObjectManager" class in the Unity container, where the contract type is the standard ASP.NET MVC interface "IController" and the registration name is the controller name.

An example from the "FrameworkInitializer" class:

Admin area controllers are registered under the names prefixed with the area name, but there is already a shorthand extension method for the "AreaRegistrationContext" class to provide a more handy API to area controllers registration.

Below is an example from the "AdminAreaRegistration" class:

The controller  in the example above is registered in "ObjectManager" under the name ‘admin_home’ to avoid conflicts between the frontend and Admin area controllers, but this is just an internal name which does not mean that while constructing a URL to any page in the Admin area the "admin_" prefix has to be specified all the time - the Sana's implementation of the controller factory automatically appends the prefix if required depending on the current area and/or the area specified in the route values as a parameter.

All controllers in Sana Commerce are inherited from the custom base classes to provide the common behavior and several shorthand methods and properties to the context state, API and miscellaneous MVC helpers. Therefore, all frontend controllers are inherited from the "FrontendControllerBase" class, while all controllers that belong to the Admin area are inherited from the "AdminControllerBase" class. Both "FrontendControllerBase" and "AdminControllerBase" classes are abstract and have "SanaControllerBase" class as their common parent.

Both the frontend and Admin base classes have several shorthand properties and methods common for all controllers in the corresponding area.


Member Description

Shop (property)

Returns the current shop context. The overview of the context details is described in the next section.

Url (property)

Returns an instance of the "FrontendUrlHelper" class which is an extended version of the standard MVC "UrlHelper" and contains URL-related functionality of the frontend area.

LayoutManager (property)

Returns the current layout manager that is used to get the name of the view for the appropriate configured page layout.

IsPreviewMode (property)

Returns a Boolean value indicating whether the current action is being executed in the content preview mode.

IsTrackingAvailable (property) Determines whether Google Tag Manager tracking is available.

SetCanonicalUrl (method)

Sets the canonical URL of the current page which is stored in the context and rendered later in the "head" section of the page.

RegisterStaticRoutes, RegisterSystemRoutes etc. (methods)

These methods should be overridden in order to register the appropriate routes corresponding to the actions of the current controller.


Member Description

Shop (property)

Returns the current shop context. The overview of the context details is described in the next section.

Url (property)

Returns an instance of the "AdminUrlHelper" class which is an extended version of the standard MVC "UrlHelper" and contains the URL-related functionality of the Admin area.

DataManager (property)

Returns the current instance of the "AdminDataManager" class which is used for data management from the Admin area.

Insert/Update/Delete (methods)

These methods should be called in most of the cases to save, update or delete an entity that is managed by the current Admin controller.

OnBeforeInsert, OnAfterUpdate etc. (methods)

These methods are called from the "Insert", "Update" and "Delete" methods before and after the corresponding persistence operation. By default, they just invoke all registered entity persistence handlers, but can be also overridden in a derived class to add extra logic to be executed in a certain moment of time.


These are the shorthand methods which send the commands to refresh the corresponding portion of cache on all servers. Mostly they are called to make any change directly available on the frontend.

AuthorizeAdmin, AdminNotFoundFilter and AdminStartFilter (attributes)

These are the action filter attributes inherited by all Admin controllers in order to deny access to unauthorized users, handle ‘page not found’ scenario and redirect to the initial setup page if needed.

Shop Context

The shop context is a class called "ShopContext" which lifetime is a "singleton per request". It stores the Sana-specific context data of the current request.

Below is an overview of the shop context properties:




Holds a reference to the current HTTP context.


Holds a reference to the current commerce context, which, in its turn, holds the information about the current webstore identifier, language, currency etc.


Contains a value indicating the request target ("Shop", "WebService", "Admin" or "Content").


The website domain which was used to match the requested webstore.


Holds a reference to the current webstore settings API.


When this property is initialized it holds a reference to the currently logged in Admin user.


Gets the value indicating whether any shop account is currently authenticated. Basically, it checks only whether the "ShopAccount" property is initialized with any account information.


Holds a reference to the currently logged in shop account information.


Returns the value indicating whether the currently logged in or anonymous customer is a consumer or represents a company.


Gets the value indicating whether the logged in shop account is a sales agent who is currently representing another customer.


A reference to the API which is used to check whether the current visitor has an access to a particular feature or behavior.

The "ShopContext" class holds only the current state, but it is not responsible for initializing itself with the concrete values. The request initialization is a responsibility of different components represented by:



RequestInitializer class

This class is used to initialize the general request state, like the requested webstore, settings, language, to determine the request scope etc.

UserStateApi class

Represents a general API to manage the state of the currently logged in user and has a method called "InitializeContext" which fills in the shop context with the information about the currently logged in visitor, admin user, impersonation state etc. This is a default implementation of the IUserStateApi interface.

Shop API

Shop API is a high-level API which entry point are the static properties of the "ShopApi" class and in most of the cases it reflects the actions performed by the end user.

Shop API is a collective notion which consists of the next areas:




This API provides high-level methods to get products, prices and track the last visited products in scope of the current user.

User state

In addition to initializing the request state with the user information, it also contains an API to manage the customer impersonation, perform authentication, create new accounts and manage passwords.


This is an API to send e-mail messages.


Provides a set of methods to manage the current basket state.


Checkout API is used to provide the data required by the order checkout process and contains high-level methods to place an order.


Contains methods to access the order history, edit or re-order existing orders.


A set of methods to manage the user's wish list.

Order templates

An API to manage the user's order templates.

Quote promotion A quote promotion API.

Below is an example on how to add a promotion code to the current basket using the basket API:


All Sana views are built using the Razor template engine. The ‘Sana.Commerce.Startersite’ project uses the ‘RazorGenerator’ NuGet package which precompiles all views into an output assembly which gives the following benefits:

  • All syntax errors in the views are found during compilation rather than at the run time.
  • No time is needed to precompile views before they are rendered the first time.

All views are configured to be compiled using the custom base classes of Sana which provide some extra functionality. All frontend views have a "Sana.Commerce.Web.Frontend.SanaWebViewPage" base class and all views in the Admin area have a "Sana.Commerce.Web.Admin.SanaWebViewPage" base class.

Below are the most useful properties and methods accessible in each view of a certain area.


Member Description


This property is used to set an additional CSS class from a view which is later rendered in layout as the CSS class of the ‘body’ HTML tag.


This property provides a reference to the current page information class which can be used to set the page title, meta description, meta-robots instructions etc. Later this information is used by the parent layout for page rendering.


Returns a reference to the current shop context.


A reference to the Sana frontend view helper which provides the most common functionality required by the frontend views and is described in details later in this section. Returns an instance of the "SanaViewHelper" class which is described separately later in this article.


Gets a reference to the frontend URL helper described previously in the ‘URL Construction’ section.


Member Description


This property is used to set an additional CSS class from a view which is later rendered in layout as the CSS class of the ‘body’ HTML tag.


Returns a reference to the current shop context.


Gets a reference to the admin area URL helper described previously in the ‘URL Construction’ section.


This method is a shorthand to the "FeatureAccessManager" API which is used to check if the currently logged in Admin user has a permission to access the requested feature.

The "SanaViewHelper" class is used all across the frontend views and provides the next commonly used functions:




Gets a value indicating whether the current page is opened in the print mode.


Gets a value indicating whether the current page is opened in the content preview mode.


Gets a value indicating whether the "In-site editor" is currently enabled.


Renders a Sana text (page message) as HTML with all HTML tags and newline characters being removed.


Renders a Sana text (page message) as HTML with all formatting preserved.

PromotionalText() Renders a partial view from a "PromotionalTexts" folder which contains promotional text.


Gets a value under the specified key from the currently enabled theme.


Renders an entity into a display template represented by a specific Sana text (page element) with injecting the entity properties values into the corresponding replace tags with the same names.


Gets the string representation of the currency symbol for the specified currency identifier.

In both areas, the frontend and Admin, there is a special folder called ‘Helpers’ which contains the special Sana Razor view helpers rather than the usual Razor views. The view helpers are described in the next article.

View Helpers

View helpers are the special Razor files located in the ‘Helpers’ subdirectory which has its own ‘web.config’ file for correct functioning. These Razor files are neither views nor partial views - they may contain only Razor helper methods (those starting with the ‘@helper’ directive). Using ‘RazorGenerator’ library these helpers are compiled into static methods of the generated helper classes.

For example, the contents of the ‘Helpers\Buttons.cshtml’ file which contains 2 helpers to render different kinds of buttons on the frontend can be changed in order to customize the markup of all buttons altogether:

‘RazorGenerator’ compiles this file into a class similar to the following:

Each of its methods will render the specified markup with the injected method arguments.

Notice, that to access the "HtmlHelper" instance in the Razor file a special class called "CurrentView" should be used. Properties of the base class "HelperPage" provide URL and HTML helpers from the Web Pages infrastructure instead of their MVC versions. Therefore, all required helpers are exposed via the static properties of the "CurrentView" class. Actually, there are two such classes in Sana Commerce with the same name but with a different namespace: one for the frontend and another one for the Admin area, because they use different URL helpers and base classes for pages.

To invoke the compiled helper, Sana provides a set of extension methods for the "SanaViewHelper" or "HtmlHelper" classes. Below is an example of how to render a link button to the new product review page:

Match the definitions

Connect a class name to its definition.
  • UrlsBuilder
    is used to construct URLs to the webstore pages.
  • FrontendRoutesRegistrator
    is used to register routing add-ons.
  • SanaControllerBase
    is a base class for all controllers.
  • FrontendControllerBase
    is a base class for all frontend controllers.
  • AdminControllerBase
    is a base class for all controllers of the admin area.
  • ShopContext
    holds the information about the current webstore, logged in account, admin user etc.
  • RequestInitializer
    is used to initialize the current ShopContext.
  • ShopApi
    is an entry point to a high-level webstore API.
  • SanaWebViewPage
    is a base class for all generated classes of Razor views.
  • CurrentView
    is a class which should be used inside the Sana Razor view helpers to access the current instances of HtmlHelper, UrlHelper etc.

2.8. Debugging & Troubleshooting

Web application debugging

There are several ways to troubleshoot the errors occurred in a web application.

Sana Commerce logging

All errors which occur inside the Sana Commerce web application are logged. With the help of Microsoft Logging Application Block the logging configuration can be easily modified in the "web.config" file. In some cases, Sana also writes plain informational messages and warnings to the log. All log entries contain the timestamp, the message and the stack trace in case of exception.

Additionally, there is a separate logging configuration and output for online payment processes which helps to troubleshoot the communication between Sana Commerce and payment service providers API.

The Sana logging configuration is described in details on the online help website.

IIS log

Sometimes, the page or the entire web application doesn't work, but there is nothing in the Sana log files. In most of the cases the reason for it is that an error occurs before the execution is passed to the Sana Commerce application. In this case the IIS logs come to the rescue.

It is also possible to configure request logging in IIS to check the details of the failed requests. More about configuring logging in IIS can be found in this article.

Sana Commerce Performance Profiler

One more option to troubleshoot the web application behavior is to use the Performance Profiler integrated into Sana Commerce. It can give an overview of all SQL queries and requests to ERP which happen during a request processing. The main limitation of this tool is that it can help to identify only non-critical issues when the requested page is still able to render.

The usage and explanation of the Sana Commerce Performance Profiler is described on the Sana online help website.

ERP connection logging

Another way to find out the cause of a problem is to enable logging of all requests to ERP on the ERP Connection page in Sana Admin. When enabled, all XML requests and responses are logged to the standard Sana log files.

Sana Source Browser

If none of the above ways helped to understand the reason of the incorrect application behavior, there is an option to analyze the Sana Commerce source code to find it out.

Sana Source Browser is a web application which provides a way to browse the source code of Sana Commerce in a similar way as Microsoft's Reference Source does. There you can search for a class or member, jump to the definition and browse all places which are using a particular token.

The access to the Sana Source Browser can be requested on individual basis using this page. It might take some time for the Sana Support team to check and approve the request.

NAV / AX logging & debugging


There are two ways to enable logging of requests and responses to Microsoft Dynamics NAV or AX:

  1. Enable logging on the ERP Connection page
  2. Enable logging on the Sana Commerce Setup form in NAV / AX

The first option is described in the previous topic and the second one is explained in the following articles on the help website:


In order to debug specific request in ERP, the easiest way is to use the Manual Process Requests form in NAV or AX. This form takes an XML file with a problematic request, executes it through the Sana pipeline as the usual request from the webstore and saves the response XML into a new file. The request XML file can be just one of the files created by ERP logging described above. With the help of this form an individual request can be debugged using a native debugger of NAV or AX.

Almost the same form is also present in Sana Admin and is called Debug ERP request. On this page you can paste the request XML into a text area and execute it through the currently configured connection. But it is quite difficult to debug the underlying ERP code when using this page as it sends the request through the web service instead of the development environment.

These two features give a possibility to optimize project development process when two independent parties are involved: one for .NET development and another one for customizations in ERP.

Sana Commerce task logging

Sana Commerce has several background tasks which can be started manually on demand, but are usually run on schedule in background. Due to that fact it is important to have an overview of the last task runs to know if they succeeded or not and troubleshoot the reason of their failures.

That is why all logs of a certain task are written to a separate folder and the logs of each task run is written to a separate file inside that folder. This means that at any point of time it is possible to view the logs of the last 20 task runs of each individual task.

More about scheduled tasks management and task logging can be found here.


The first and the most important resource which should be used to troubleshoot any problems related to Sana Commerce is the Sana Help website. It gives an overview of the required functionality and describes all the configuration options which can influence the webstore behavior.

Another very useful resource to find a solution for a problem is the Knowledge base section of Sana Community portal. There are a lot of descriptions of common errors and the ways to fix or avoid them.

When the two above resources don't help, the Sana Support can be contacted in order to help resolving an issue.

Any issues found in Sana Commerce or suggestions on how the product can be improved should be posted to the Sana's UserVoice channel which all will be handled in offline mode by the Sana Support team.

What to do when an error occurs on the webstore page?

First of all,  to find an error message. Based on the message, try to figure out which functionality is the error related to. If it originates from ERP, use the  or  to get the problematic XML request and debug it using the  in ERP. If the error is not related to ERP, navigate to Sana Admin and  to check if everything is configured correctly. If this is not the case, try to find the solution . When the cause of the problem has been found and it appears to be a result of some problem in Sana Commerce, , so that we can solve it in one of the next product updates.

When none of the above helped to solve the issue, contact Sana Support for assistance.

3.1. Hands-on Lab: Extending Checkout Process


This hands-on lab shows how to extend and customize Sana Commerce step-by-step in order to add an additional step to the checkout process on the webstore.

The goal of this lab is to learn the following topics:

  • Use  existing CommerceFramework API
  • Manipulate entity fields
  • Use ObjectManager to register customized classes
  • Get and save custom data to ERP

This lab does not cover customizations in ERP, but shows how to use "ERP mock" feature to customize the webstore independently of ERP development part.

All steps of this hands-on lab should be repeated on the local development environment to better learn the material and get familiar with Sana Commerce SDK and the available API. The development environment can be obtained by downloading one of the demo VPC images. Both NAV and AX images are acceptable for this lab, but the NAV one is recommended. A VPC image contains a fully functional Sana Commerce installation with a plenty of demo data and Sana Commerce SDK solution which is already pre-configured to connect to the same environment.

The demo VPC image is almost an exact copy of the Sana Demo Store.

User Story

Here are the requirements to be implemented:

  • When placing an order a customer should be able to select a "customer site" from a drop-down list during the checkout process.
  • The selected value should be saved with order in ERP.
  • All available customer sites are stored in the "Customer Site" table in ERP which has three columns: "Customer No.", "Site No." and "Address".
  • The identifier of the selected customer site should be saved with an order into existing "Your Reference" column.

Up and Running

To get started, launch the downloaded VPC image and open the Sana Commerce SDK solution which is located in the "C:\SDK" directory.

This solution is already configured to use the same SQL database and search indexes which the hosted demo installation is using (hosted installation is located under "C:\inetpub\wwwroot\Sana Commerce").

Launch the "Sana.Commerce.Startersite" web application from Visual Studio to check if the webstore is opened correctly. The "DefaultWebsite" application setting in the "web.config" file of the web application is configured to "MaddoxNav", so that when started from Visual Studio on IIS Express (http://localhost:5923/), Sana will use "MaddoxNav" website as the current one, because there are no mappings for "localhost" domain in the database.

Where to Start?

According to the requirements, let's start from creating a new blank page inside the checkout process which will later collect the required information.

First of all, let's take a look on the existing checkout pages and their corresponding MVC actions. To do this, request an access to the Sana Source Browser if not done yet. Next, navigate to the current version of Sana and search for a "CheckoutController" and "CheckoutApi" classes which implement all the checkout-related MVC actions.

After exploring the source code of CheckoutControllerBase, CheckoutApi classes and ICheckoutProcess interface, it becomes clear that there is some list of checkout steps being returned from the ICheckoutProcess interface:

The list of steps is initialized in implementations of the ICheckoutProcess interface (for example in OrderCheckoutProcess class):

This method creates a list of objects inherited from a CheckoutStep class. This means that this method can be overridden in a derived class and an additional checkout step can be inserted into the resulting collection.

From the source code of the CheckoutStep class the following conclusions can be done:

  • The constructor accepts a unique string identifier of the step and a URL to the corresponding page or MVC action
  • IsComplete method checks whether all required information has been collected by this step
  • IsAvailable method checks whether the current step should be visible in the checkout process based on the current settings (in our case it will always return "true")

Later, a new step will be injected into this collection, but first let's start from a simple page.

New Blank Page

Now it's time to start real development. In order to keep all customizations altogether, create a folder "Training" in the root of the "Sana.Commerce.Sdk" project.

Add a new class CustomCheckoutController inside the "Training" folder, inherit it from a standard CheckoutController class from Sana.Commerce.Web library. Add two empty CustomerSite MVC action method (one for GET requests and another one for POST). The second method will take a "string siteId" parameter which later will be used to send a selected customer site to the server. In order to make the new page accessible from the browser, override the RegisterSystemRoutes method and map a route for the newly created action. 

Here is what should be in a result:

And next step is to replace the standard implementation of checkout controller with a customized one by adding the following line at the end of Initialize method of the FrameworkInitializer class in the "Sana.Commerce.Sdk" project:

And the last step is to add a corresponding view for the new MVC action. To do this, add a new file "Views\Default\Checkout\CustomerSite.cshtml" to the "Sana.Commerce.Startersite" project with temporary text content (for example, "This is my new page"). Let's also connect it to the general "Shop" layout. This is done by adding the following code at the beginning of the "CustomerSite" view:

Launch the webstore and navigate the browser to "/checkout/site". The temporary text is shown, and shop layout has been rendered around the page content.

Checkout Step Page

Next action is to convert the new page into a checkout step page and integrate it into the "Checkout" layout.

"Checkout" layout requires the model of the embedded view to be inherited from CheckoutBaseViewModel class. Due to that fact, create a new class CustomerSiteViewModel under the "Training" directory and inherit it from the CheckoutBaseViewModel. For now, new model class will not contain any additional properties.

Then, change the CustomerSite action methods to create an instance of the view model and pass it to the view. Source Browser can help to find out how similar view models are created in another checkout action methods, for example in "OrderAddress":

So, to create a view model, a custom checkout step is already required. Create a new class CustomerSiteCheckoutStep under the same "Training" folder with the following contents and inherit it from the base CheckoutStep class:

For now, IsComplete method will always return "true" as no data is being collected yet.

Sana Commerce handles different types of checkout processes, for example: order checkout, quote checkout, order editing, etc. For every type of checkout process there is a class which controls behavior of the checkout. All these classes implement ICheckoutProcess interface. OrderCheckoutProcess class needs to be customized to extend order checkout. Let's create a new class CustomOrderCheckoutProcess and inherit it from OrderCheckoutProcess class. Custom checkout process needs to be registered by adding the following line at the end of Initialize method of the FrameworkInitializer class in the "Sana.Commerce.Sdk" project:Next, override the GetCheckoutSteps method of OrderCheckoutProcess class and add a new step to the collection:

In the code above, the new step is inserted as the second step of checkout.

As we can see in model classes for other checkout steps (for example ShippingMethodsPageModel) they contain Initialize method for it's initialization. Let's follow this approach and create Initialize method in CustomerSiteViewModel class. It accepts shop context instance and instance of CheckoutGeneralInfo class:

Finally, the CustomerSite action methods should be changed to pass a correct model to the view:

The POST action method has been already changed to navigate to the next step of checkout process.

The final stage is to change the "CustomerSite.cshtml" to use correct layout instead of "Shop". Just remove the line where Layout property is set. Needed layout is automatically applied by the code inside "_ViewStart.cshtml" file.

Now, build solution, go to the webstore, add any product to the basket, proceed to checkout, login under one of the provided customer accounts, select a shipping method and click "Next".

The temporary text ("This is my new page") is shown, the previous step number is "1", the next step number is "3", but there is no title of the current newly added step. This text can be supplied by navigating to the Sana Admin area ("/admin"), clicking "Tools" -> "In-Site Editor" and navigating back to the new checkout page to see the following:

Hover the text "EMPTY PAGE MESSAGE", and change it to "{0}. Customer site". The "{0}" part will be automatically replaced by the corresponding step number.

The only thing which is still missing on this page is a possibility to go to the next step of checkout. To do this, add an empty form with "Back" and "Next" buttons to the "CustomerSite.cshtml" view which will be posted to the server and the server will perform a redirect to the next step of checkout:

Refresh the page in the browser, check that both "Back" and "Next" buttons are present, click on the "Next" button and... an error occurs:

The error message tells that there is no view with the name "SiteLine.cshtml" in the "CheckoutSummaryLines" subdirectory. Exploring this folder gives an understanding that all these views are used to show the values selected by the customer during the previous steps of checkout. Let's add the one for the customer site step. It should have a name "SiteLine.cshtml" which is constructed dynamically as the checkout step identifier plus a "Line" suffix. For now this view can be just left empty.

Refresh the page in the browser to ensure that it is rendered correctly.

The List of Customer Sites

Now it's a turn to show the drop-down list with customer sites on the new page. To do this, the following is needed:

  1. A class representing customer site object
  2. An API to get the list of customer sites from ERP
  3. An extra property in the "CustomerSiteViewModel" class to pass the list of sites to the view
  4. A drop-down control to select a customer site on the page
  5. Setup "ERP Mock" to return a test XML response with the list of customer sites

1. Create a class CustomerSite under the "Training" directory with the following two string properties: Id (the customer site identifier) and Address (the customer site address text).

2. Next, open the ExtendedCustomerManager class from the "Sana.Commerce.Sdk" project which is located in the "Customization\Customer" directory and add a new method GetCustomerSites which takes a customer identifier as a single argument and returns a list of customer sites.

As it was noticed in the requirements, customer sites are stored in ERP in the "Customer Site" table. The easiest way to get the list of  these records is by using the GetEntities method of the Common manager as shown here:

The code in this method initializes the load options by setting the list of columns which should be included in the result and applying the filter on "Customer No." column. Then, all entities matching the filter are retrieved from the "Customer Site" table and are converted from "IEntity" type to "CustomerSite" class to have better IntelliSense experience. Method call UseOnlineDataOnly of CommerceFramework class and "using" block create a scope where managers use only online providers. As a result method GetEntities will make direct call to ERP without trying to load it from SQL database. However it is possible to customize OfflineCommonProvider class to improve performance of entities loading. It can support saving the "Customer Site" entities to the SQL database and method GetEntities can return previously saved offline data. Additionally "General information import" task should be extended to retrieve entities from ERP and to save it to SQL database.

Due to the fact that the "GetEntities" method of the common manager is used instead of the provider version, it also caches the result, so that during the next call to get customer sites for the same customer, the cached data will be returned instead of making an additional call to ERP.

3. Open the CustomerSiteViewModel class from the "Training" directory and add a property "Sites" of type "IList<CustomerSite>". Also add additional parameter "sites" to Initialize method, and initialize "Sites" property by value of "sites" parameter:

Now let's properly initialize the view model in the controller, so that the list of customer sites in available in the view:

4. Then, add the drop-down control with the list of customer sites to the form in the "CustomerSite.cshtml" view:

4. At the current moment, a call to "GetEntities" method to get the records from the "Customer Site" table returns no results or raises an error (depends on the type of ERP), because no changes have been made to ERP yet.

In order to test the customizations independently from ERP, a test data should be returned when "GetEntities" ERP method is invoked. "ERP Mock" feature of Sana Commerce can help with it. The details of this feature are described in the "How to develop a connector" guide of the eBusiness Connector documentation.

First of all, navigate to the "App_Data\ErpMock\GetEntities" folder of the "Sana.Commerce.Startersite" SDK project. There is a file "Response.xml" which contents are returned when a redirect to ERP Mock is enabled for the "GetEntities" operation. Change the contents of this file to the following:

Then, go to the Sana Admin and search for a "Mocked operations" page. On this page check the checkbox in front of "GetEntities" operation, like on the picture below and click "Save changes" button at the bottom of the page.

Build solution and refresh the page in the browser to see that the list of customer sites is correctly shown in the drop-down. 

Move on to add customizations to remember the selected value and finally save it with an order to ERP.

Remember Selected Site

All choices made by the customer during the checkout process (like shipping method, payment method etc.) are stored in a Basket entity, so it should be customized as well.

Open the file "DomainModel\Shop\Basket.cs" inside the "Sana.Commerce.Sdk" project and add a property "Site" of type "CustomerSite" which will be used to store the selected customer site. In order to persist the value of this property in SQL database, mark it with a XmlField attribute:

Next, change the "CustomerSite" POST action method to save the selected item in the basket:

The ModifyCurrentBasket method of the basket API gets the current basket from the database, evaluates the modification action passed as an argument and saves the modified basket back to the database. 

The above change remembers the selected customer site in the source basket, but the value of this property should be also copied to the calculated basket right after the calculation. This can be done by overriding the UpdateCalculatedBasket method in the ExtendedOrderProvider class which is located in the "Customization\Order" directory of the "Sana.Commerce.Sdk" project:

Next, change the "CustomerSite.cshtml" view to initialize the drop-down with the previously selected value if any and wrap the drop-down list with the following HTML elements to add nice styling to it:

Notice, that now the "selectedSiteId" variable is passed into the "SelectList" constructor. This will automatically select an entity with identifier matching the value of this variable.

Now when the customer goes back in the checkout process, the previously selected site will be already pre-selected in the drop-down list.

The last thing to change is the IsComplete method of the CustomerSiteCheckoutStep class in order to check if the site has been selected to avoid a possibility to jump over directly to the next step of checkout without selecting a customer site:

Also it might be very handy to show the selected site address in the checkout summary on all next steps of checkout. This is where the "SiteLine.cshtml" view can do its job. The view is located under "Views\Default\Checkout\CheckoutSummaryLines" directory. Open the file and put the following content into it:

This will show the selected site address, but for now without a title. The title can be specified using the "In-Site Editor" feature in Sana Admin in the same way as it has been done for checkout step title.

Now build the solution and test the changes.

Save With Order

Finally, the last task of this lab is to save the identifier of the selected customer site to ERP into the "Your Reference" column.

Custom data can be saved together with an order by adding an appropriate entity field to the Order entity and setting the StoreWithEntity property of this field to "true".

By exploring the source code of Sana Commerce in the Source Browser starting from the "CheckoutController" class, the following is encountered:

  1. Each checkout step calls the GoToNextCheckoutStep method from its POST action method.
  2. The GoToNextCheckoutStep method calls the PlaceOrder method if the current step is the last step of checkout.
  3. PlaceOrder method is using a Submit method of the ICheckoutApi interface.
  4. The only implementation of the ICheckoutApi interface is the CheckoutApi class.
  5. Digging into the code of the CheckoutApi class shows that there is a method CreateOrderToSubmit of ICheckoutProcess interface which creates a new order instance based on the current basket context. So this method should be overridden to get the selected customer site from the basket and put it into an order.

So, override a CreateOrderToSubmit method in the CustomOrderCheckoutProcess class in the "Training" directory of "Sana.Commerce.Sdk" project. Add the following  code there: 

That's it! Now when a customer places an order, the identifier of the selected customer site is automatically saved into the "Your Reference" column in ERP.

Which Sana Commerce classes have been changed, customized or extended in this lab?

  • FrameworkInitializer
  • Order
  • Basket
  • CheckoutController
  • ExtendedCustomerManager
  • ExtendedCatalogManager
  • ExtendedOrderProvider
  • ExtendedCustomerProvider
  • CheckoutApi
  • OrderCheckoutProcess
  • CustomerController

Choose all that apply.

3.2. Hands-on Lab: Creating a Design Pack


This hands-on lab is designed to show how to create a simple design pack for Sana Commerce with a custom store layout in order to create a unique look and feel of the webstore.

A store layout consists of a set of CSS, JavaScript and Razor ".cshtml" files which are copied into the "Sana.Commerce.Startersite" project during the package installation.

The guide covers the full package creation process including start-up, development and final packaging to create a redistributable design pack.

Start With a Sample

The easiest way to create a design pack is to start with a sample one. A sample design pack can be downloaded from this page on the Sana Community portal by clicking "Design Packages Example Pack" download link at the right. Open the downloaded ZIP archive and extract the file "StoreLayoutSamplePack.1.0.0.nupkg". 

The example pack does not contain any custom content files or views, but it provides a skeleton for a new design pack.

Internally, a design pack is a NuGet package which is installed in a usual way when the package is uploaded into Sana Commerce installation. The easiest way to create and edit NuGet packages is to use a NuGet Package Explorer tool. To download and install this tool click this link.

Now, run the tool and open the extracted ".nupkg" file which contains a sample design pack:

The first step in creating a new design pack is changing a sample package metadata. It consists of two parts:

  1. Edit the NuGet package metadata by clicking the "Edit Metadata" button in the top left corner. Change the package identifier, authors, owners and package description. All other properties can be left unchanged.
  2. Edit the file "sanamanifest.xml" which contains the information about all included store layouts and page layouts. To do this, right-click the "sanamanifest.xml" file in the right window, choose "Edit" from a context menu, change the name and title of the store layout and save changes. The name of the store layout should match the corresponding folder name inside the package contents, so try to keep it short.

Here is an edited package metadata:

And the modified "sanamanifest.xml":

The store layout name "Training" will be used later also as the name of all corresponding folders. The full description of the Sana package manifest file can be found on this page of Sana online help website.

The last step in preparing a design pack with a new store layout is to change the name of the folders which will contain the files related to the custom store layout. All files and directories located under the "content" element of the package are copied to the corresponding places of the "Sana.Commerce.Startersite" project when the package is installed.

In the "Package contents" window at the right, expand the "content" item, then expand the "Views" directory and rename the inner folder to match the name of the new store layout:

Then do the same to the "content\content\css\SampleStoreLayout" directory:

The initial empty package is ready to be saved and uploaded into Sana Commerce installation. Click "File" -> "Save As..." in the NuGet Package Explorer to assemble and save the new package in the local file system. Then start the webstore from Visual Studio (can be started without debugging using Ctrl+F5 keyboard shortcut). Navigate to Sana Admin, open the "Design packs" page and upload the recently created package:

After that, navigate to the second tab called "Store layouts" and activate a new store layout to be used on the webstore:

At the current moment, while no custom views, CSS or JS files exist in the new store layout, the webstore will look exactly the same as in the standard installation, but starting from that moment it is ready for customizations.

Custom Styling

Let's start to fill in the new store layout with custom styling.

All CSS files in Sana Commerce are located under the "content\css" directory and are grouped into subfolders for different store layouts. The "Default" directory contains all standard Sana CSS files, while the "Training" directory is for a new store layout. By default, the "Training" folder is not visible in the Solution Explorer, because it has not been included into the project. In order to make it visible, select a "Sana.Commerce.Startersite" project and click the "Show All Files" button on the Solution Explorer toolbar.

The store layouts engine for CSS and JavaScript files is designed in a such way, that the files from both folders (the "Training" folder and the "Default" folder) are merged into a single file set sorted by file name. When there are two files with the same name in both folders, the one from the "Training" folder will be used. When some file exists only in "Training" folder, it is inserted into the resulting file set into the corresponding place according to the alphabetical sorting.

The JavaScript files of a store layout have the same structure and behavior as the CSS files and are located under the "content\script" directory instead of "content\css".

For example, given the following set of files:

  • Default
    • store.css
    • store.custom.css
    • z-mobile.css
  • Training
    • before.css
    • store.custom.css
    • store.extra.css

When using a default store layout, the following files are included into the page in the following order:

  1. Default/store.css
  2. Default/store.custom.css
  3. Default/z-mobile.css

When "Training" store layout is activated, the following CSS files are included into the page and in the following order:

  1. Training/before.css
  2. Default/store.css
  3. Training/store.custom.css
  4. Training/store.extra.css
  5. Default/z-mobile.css

So with this approach a custom store layout can replace any standard file with a custom one or insert an additional file between any other standard files in a resulting set.

For demo purposes, the new store layout will contain just a single CSS file with the name "". All styles from this file according to the alphabetical sorting will be applied after the styles from default "store.css" but before the styles in "z-mobile.css".

To make it simple but contrast, lets make all "H1" HTML elements to be of red color. To do this, create a new file "" in the "content\css\Training" directory and put the following CSS in it:

Now open the webstore in the browser and navigate to the news overview page (e.g. "http://localhost:5923/news/") to ensure that the title is red.

The source of the HTML document looks as follows:

Custom Markup

Now let's extend the "Training" store layout to also provide a different Razor markup to be used when the store layout is activated.

For this example, let's change the layout of the news overview page in order to render news headlines in the right column and the list of news items in the left one.

To do this, first of all copy a standard news layout file from "Views\Default\News\_Layout.cshtml" to "Views\Training\News\_Layout.cshtml". The paths are almost identical except the name of the store layout ("Training" instead of "Default").

Next, swap the columns in "Views\Training\News\_Layout.cshtml" to be like this:

Now refresh the news overview page in the browser to see that the headlines are now at the right.

If the store layout is now deactivated in Sana Admin, the default layout will be used and the headlines are at the left again and title is not red anymore.

Packing Changes

All the changes in the store layout are ready, so they should be also included in the design pack to make them redistributable.

Open the NuGet Package Explorer again, add the newly created files to the corresponding folders in the "Package contents" window as shown on the picture below and save the package.


Let's test the final package to make sure that all changes have been included:

  1. Delete the newly created files from the SDK solution which was used for development
  2. Go to Sana Admin and change the store layout back to default
  3. Delete the previously installed design pack using the corresponding Sana Admin page
  4. Upload the final package
  5. Activate a custom store layout again
  6. Go to the news overview page to check if the title is red and the headlines are at the right

That's it - a new redistributable design pack is ready!

Which types of files are used by store layouts?

  • *.css
  • *.js
  • *.sql
  • *.dll
  • *.cshtml
Choose all that apply.

Additional Resources

Additional Resources

Technical Documentation

Additionally to this course, Sana provides the list of extra technical materials including:

  • How-to guides
  • Style guide
  • Online payments infrastructure
  • Sana Enterprise architecture
  • Maintenance Mode explanation

All these documents can be found on this page of the Sana Community portal.

Sana Source Browser

The source code of Sana Commerce framework is available through the Sana Source Browser web application.

An access to the Source Browser can be requested from this page.

eBusiness Connector Documentation

All XML contracts of eBusiness Connector as well as the guide on connecting Sana Commerce to a custom ERP can be found on the eBusiness Connector documentation page.